UWP自定义面板尺寸基于面板儿童安排的高度

时间:2017-10-04 17:06:18

标签: c# uwp custom-controls

我目前正在尝试创建一个与VariableGridView类似的控件,但不会使用列/行跨度预先计算的项目高度和宽度,内容将控制项目高度。使用Column span确定控件宽度。您可以找到WIP样本here

我目前唯一的问题是控件的初始加载。当控件在ScrollViewer中并且它的高度超过窗口/父级的高度时,它不会滚动。见下文:

Scrollbar fills the right hand side

但是,一旦我调整窗口大小,滚动就会按预期正常工作。见下文:

You can see here the scrollbar has fixed itself and is the right size for the content of the Panel

可能很难看到,但是如果你看一下右侧滚动条的较暗部分,你可以看到它在初始载荷时没有正确调整尺寸。

我怀疑我在控件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;
 }

在设置控件的大小之前,如何计算项目的高度?

1 个答案:

答案 0 :(得分:0)

我能够解决自己的问题。我需要在安排之前弄清楚我的卡片的位置。这样就会计算columnOffsets,我可以将面板的高度从最大列偏移量开始。

我还没有更新github repo,但是这里需要更新的代码才能工作:

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);
}