/// <summary> /// 添加或移除一个元素布局 /// </summary> private void LayoutItem(UIElement item) { //开始布局 StackLayoutContext minStack = layoutContext.First(c => c.Lenght == layoutContext.Min(s => s.Lenght)); if (Orientation == Orientation.Vertical) { Size availableSize = new Size(minStack.Width, double.PositiveInfinity); Point coordinate = new Point(minStack.Offset, minStack.Lenght); item.Measure(availableSize); SetArrange(item, new Rect(coordinate, item.DesiredSize)); minStack.Lenght += item.DesiredSize.Height + ItemsSpacing; } else { Size availableSize = new Size(double.PositiveInfinity, minStack.Width); Point coordinate = new Point(minStack.Lenght, minStack.Offset); item.Measure(availableSize); SetArrange(item, new Rect(coordinate, item.DesiredSize)); minStack.Lenght += item.DesiredSize.Width + ItemsSpacing; } if (item is IVirtualizingItem) { if (ShouldBeVirtualized(item)) { (item as IVirtualizingItem).Virtualize(); } else { if (minStack.FirstRealizedItemIndex == -1) { minStack.FirstRealizedItemIndex = minStack.Elements.Count; } minStack.RealizedItemCount++; (item as IVirtualizingItem).Realize(); } } minStack.Elements.Add(item); //完成一个子项布局,布局请求递减 layoutRequest--; }
/// <summary> /// 布局初始化,初始化所有子项的布局 /// </summary> private void LayoutInitialize(Size availableSize) { //清除布局上下文数据 layoutContext.Clear(); double availableWidth = availableSize.Width - Padding.Left - Padding.Right; double availableHeight = availableSize.Height - Padding.Top - Padding.Bottom; //计算子项固定边大小 _columnWidth = Math.Min(DesiredColumnWidth, availableWidth); int numColumns = Math.Max(1, (int)Math.Floor(availableWidth / _columnWidth)); double totalWidth = _columnWidth + ((numColumns - 1) * (_columnWidth + ColumnSpacing)); if (totalWidth > availableWidth) { numColumns--; } else if (double.IsInfinity(availableWidth)) { availableWidth = totalWidth; } if (HorizontalAlignment == HorizontalAlignment.Stretch) { availableWidth = availableWidth - ((numColumns - 1) * ColumnSpacing); _columnWidth = availableWidth / numColumns; } double offset = ((Orientation == Orientation.Vertical ? availableWidth : availableHeight) - (numColumns * ColumnSpacing)) / numColumns; //为每个栈生成布局上下文数据 for (int i = 0; i < numColumns; i++) { layoutContext.Add(new StackLayoutContext() { //每个栈的子项的固定偏移,纵向排版就为 X 坐标,横向就为 Y 坐标 Offset = (offset + ColumnSpacing) * i, Width = offset }); } //遍历子项为每个子项进行测量 foreach (var item in this.Children) { //寻找长度最短的栈 StackLayoutContext minStack = layoutContext.First(c => c.Lenght == layoutContext.Min(s => s.Lenght)); //根据不同的布局方向进行布局 if (Orientation == Orientation.Vertical) { //栈的固定长度,纵向排版为宽,横向为高 availableSize.Width = offset; //子项的坐标,栈的目前长度与栈的固定偏移 Point coordinate = new Point(minStack.Offset, minStack.Lenght); //测量子项所需尺寸 item.Measure(availableSize); //将测量结果保存在附加属性 Arrange 中,以便布局时使用 SetArrange(item, new Rect(coordinate, item.DesiredSize)); //将最短栈加上当前子项的长度与子项间距 minStack.Lenght += item.DesiredSize.Height + ItemsSpacing; } else { availableSize.Height = offset; Point coordinate = new Point(minStack.Lenght, minStack.Offset); item.Measure(availableSize); SetArrange(item, new Rect(coordinate, item.DesiredSize)); minStack.Lenght += item.DesiredSize.Width + ItemsSpacing; } //判断子项是否实现 IVirtualizingItem 接口 if (item is IVirtualizingItem) { //判断子项是否应该被虚拟化 if (ShouldBeVirtualized(item)) { (item as IVirtualizingItem).Virtualize(); } else { if (minStack.FirstRealizedItemIndex == -1) { minStack.FirstRealizedItemIndex = minStack.Elements.Count; } minStack.RealizedItemCount++; (item as IVirtualizingItem).Realize(); } } //添加子项到最短栈的结尾 minStack.Elements.Add(item); } layoutRequest = 0; }