分享

WPF布局

 牛人的尾巴 2016-06-23
复制代码
// 自定义一个从左至右排列、从上往下换行的面板,并且提供一个附加属性可以指示在哪个子元素前换行
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));

            // 当行宽超过了可用空间的宽度或者子元素设置了换行的附加属性时换行
            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)
        {
            // 如果该子元素将要超出边界或者设置了换行,则换一行从头显示
            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;
    }
}
复制代码

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多