![]() // 自定義一個從左至右排列、從上往下?lián)Q行的面板,并且提供一個附加屬性可以指示在哪個子元素前換行 public class MyWrapPanel : Panel { // 定義一個指示在哪個子元素前換行的附加屬性 public static readonly DependencyProperty LineBreakBeforeProperty; static MyWrapPanel() { var metadata = new FrameworkPropertyMetadata { AffectsMeasure = true, AffectsArrange = true }; LineBreakBeforeProperty = DependencyProperty.RegisterAttached("LineBreakBefore", typeof(bool), typeof(MyWrapPanel), metadata); } public static void SetLineBreakBefore(UIElement element, bool value) { element.SetValue(LineBreakBeforeProperty, value); } public static bool GetLineBreakBefore(UIElement element) { return (bool)element.GetValue(LineBreakBeforeProperty); } protected override Size MeasureOverride(Size availableSize) { var totalWidth = 0.0; var totalHeight = 0.0; var rowHeight = 0.0; var rowWidth = 0.0; foreach (UIElement uiElement in this.Children) { uiElement.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); // 當(dāng)行寬超過了可用空間的寬度或者子元素設(shè)置了換行的附加屬性時換行 if (rowWidth + uiElement.DesiredSize.Width >= availableSize.Width || GetLineBreakBefore(uiElement)) { // 面板的總寬度是所有行的最大寬度 totalWidth = Math.Max(totalWidth, rowWidth); // 面板的高度是所有行的高度之和 totalHeight += rowHeight; // 換行后重置行高和行寬 rowHeight = 0.0; rowWidth = 0.0; } else { // 每一行的寬度是所有子元素寬度之和 rowWidth += uiElement.DesiredSize.Width; // 每一行的高度都是這一行中所有子元素的最大高度 rowHeight = Math.Max(rowHeight, uiElement.DesiredSize.Height); } } // 加上最后一行的高度 totalHeight += rowHeight; return new Size(totalWidth, totalHeight); } protected override Size ArrangeOverride(Size finalSize) { var x = 0.0; var y = 0.0; var rowHeight = 0.0; foreach (UIElement uie in this.Children) { // 如果該子元素將要超出邊界或者設(shè)置了換行,則換一行從頭顯示 if (x + uie.DesiredSize.Width >= finalSize.Width || GetLineBreakBefore(uie)) { x = 0.0; y += rowHeight; // 重置行高 rowHeight = 0.0; } uie.Arrange(new Rect(x, y, uie.DesiredSize.Width, uie.DesiredSize.Height)); rowHeight = Math.Max(rowHeight, uie.DesiredSize.Height); x = x + uie.DesiredSize.Width; } return finalSize; } }
|
|