UWP Custom Panel sized based on the Panel children arranged height
UWP Custom Panel sized based off the Panel Childrens arranged height
我目前正在尝试创建一个类似于 VariableGridView 的控件,但是内容将控制项目高度,而不是使用 Column/Row 跨度预先计算的项目高度和宽度。使用 Column span 决定控件的宽度。您可以找到 WIP 示例 here.
我目前遇到的唯一问题是控件的初始加载。当控件位于 ScrollViewer 中并且它的高度超过 window/parent 的高度时,它不会滚动。见下文:
然而,一旦我调整 window 的大小,滚动就会按预期正常工作。见下文:
可能很难看清,但如果您查看右侧滚动条较暗的部分,您会发现它在初始加载时未正确调整自身大小。
我怀疑我在控制 MeasureOverride
方法中犯了一个错误,但是我看不出我做错了什么:
protected override Size MeasureOverride(Size availableSize) {
// Need to use this method LimitUnboundedSize as when within a
// ScrollViewer an infinite height is supplied within the availableSize
var desiredSize = LimitUnboundedSize(availableSize);
UpdateColumnOffsets();
foreach (var child in Children) {
child.Measure(desiredSize);
}
return desiredSize;
}
private Size LimitUnboundedSize(Size input) {
if (Double.IsInfinity(input.Height)) {
var scrollViewer = this.FindAscendant<ScrollViewer>();
var contentHeight = scrollViewer.ViewportHeight.Equals(0)
? Window.Current.Bounds.Height : scrollViewer.ViewportHeight;
input.Height = (contentHeight >= GetMaxOffset ? contentHeight :
GetMaxOffset);
}
return input;
}
在设置控件大小时,如何计算项目将占用的高度?
我能够解决我自己的问题。我需要在安排之前弄清楚我的牌的位置。这样将计算 columnOffsets,我可以将面板的高度基于最大列偏移量。
我还没有更新 github 存储库,但这里是需要更新才能正常工作的代码:
protected override Size ArrangeOverride(Size finalSize) {
foreach (var child in Children) {
var resizable = child as IArrangeable;
resizable?.Arrange(pointDictionary.GetValueOrDefault(resizable.Card));
}
return finalSize;
}
private double GetMaxOffset {
get { return columnOffsetY.Max(); }
}
protected override Size MeasureOverride(Size availableSize) {
var desiredSize = availableSize;
UpdateColumnOffsets();
foreach (var child in Children) {
child.Measure(desiredSize);
CreateOffsetCache(child);
}
if (Double.IsPositiveInfinity(desiredSize.Height))
desiredSize.Height = GetMaxOffset;
return desiredSize;
}
private Dictionary<Card, Point> pointDictionary;
private void CreateOffsetCache(UIElement child) {
var arrangeable = child as IArrangeable;
if (arrangeable == null) return;
var card = arrangeable.Card;
var useColumnOffset = columnOffsetY[card.Column] < columnOffsetY[card.Column + card.ColumnSpan - 1]
? columnOffsetY[card.Column + card.ColumnSpan - 1] : columnOffsetY[card.Column];
var point = new Point(columnOffsetX[card.Column], useColumnOffset);
pointDictionary[card] = point;
SetColumnOffsetY(card.Column, card.ColumnSpan, child.DesiredSize.Height);
}
我目前正在尝试创建一个类似于 VariableGridView 的控件,但是内容将控制项目高度,而不是使用 Column/Row 跨度预先计算的项目高度和宽度。使用 Column span 决定控件的宽度。您可以找到 WIP 示例 here.
我目前遇到的唯一问题是控件的初始加载。当控件位于 ScrollViewer 中并且它的高度超过 window/parent 的高度时,它不会滚动。见下文:
然而,一旦我调整 window 的大小,滚动就会按预期正常工作。见下文:
可能很难看清,但如果您查看右侧滚动条较暗的部分,您会发现它在初始加载时未正确调整自身大小。
我怀疑我在控制 MeasureOverride
方法中犯了一个错误,但是我看不出我做错了什么:
protected override Size MeasureOverride(Size availableSize) {
// Need to use this method LimitUnboundedSize as when within a
// ScrollViewer an infinite height is supplied within the availableSize
var desiredSize = LimitUnboundedSize(availableSize);
UpdateColumnOffsets();
foreach (var child in Children) {
child.Measure(desiredSize);
}
return desiredSize;
}
private Size LimitUnboundedSize(Size input) {
if (Double.IsInfinity(input.Height)) {
var scrollViewer = this.FindAscendant<ScrollViewer>();
var contentHeight = scrollViewer.ViewportHeight.Equals(0)
? Window.Current.Bounds.Height : scrollViewer.ViewportHeight;
input.Height = (contentHeight >= GetMaxOffset ? contentHeight :
GetMaxOffset);
}
return input;
}
在设置控件大小时,如何计算项目将占用的高度?
我能够解决我自己的问题。我需要在安排之前弄清楚我的牌的位置。这样将计算 columnOffsets,我可以将面板的高度基于最大列偏移量。
我还没有更新 github 存储库,但这里是需要更新才能正常工作的代码:
protected override Size ArrangeOverride(Size finalSize) {
foreach (var child in Children) {
var resizable = child as IArrangeable;
resizable?.Arrange(pointDictionary.GetValueOrDefault(resizable.Card));
}
return finalSize;
}
private double GetMaxOffset {
get { return columnOffsetY.Max(); }
}
protected override Size MeasureOverride(Size availableSize) {
var desiredSize = availableSize;
UpdateColumnOffsets();
foreach (var child in Children) {
child.Measure(desiredSize);
CreateOffsetCache(child);
}
if (Double.IsPositiveInfinity(desiredSize.Height))
desiredSize.Height = GetMaxOffset;
return desiredSize;
}
private Dictionary<Card, Point> pointDictionary;
private void CreateOffsetCache(UIElement child) {
var arrangeable = child as IArrangeable;
if (arrangeable == null) return;
var card = arrangeable.Card;
var useColumnOffset = columnOffsetY[card.Column] < columnOffsetY[card.Column + card.ColumnSpan - 1]
? columnOffsetY[card.Column + card.ColumnSpan - 1] : columnOffsetY[card.Column];
var point = new Point(columnOffsetX[card.Column], useColumnOffset);
pointDictionary[card] = point;
SetColumnOffsetY(card.Column, card.ColumnSpan, child.DesiredSize.Height);
}