在WPF中构建可逆的StackPanel

9
我想创建一个自定义的StackPanel,其中包含一个ReverseOrder属性,我可以在声明时将其设置为true,使得StackPanel中元素的顺序与正常情况下相反(例如从底部到顶部或从右到左)。它需要能够动态反转。
我考虑从StackPanel派生出一个新类,但我需要知道要重写哪些方法。 最终解决方案:
protected override System.Windows.Size ArrangeOverride( System.Windows.Size arrangeSize ) {
    double x = 0;
    double y = 0;

    IEnumerable<UIElement> children = ReverseOrder ? InternalChildren.Cast<UIElement>().Reverse<UIElement>() : InternalChildren.Cast<UIElement>();
    foreach ( UIElement child in children ) {
        var size = child.DesiredSize;
        child.Arrange( new Rect( new Point( x, y ), size ) );

        if ( Orientation == Orientation.Horizontal )
            x += size.Width;
        else
            y += size.Height;
    }

    if ( Orientation == Orientation.Horizontal )
        return new Size( x, arrangeSize.Height );
    else
        return new Size( arrangeSize.Width, y );
}

另外定义并注册ReverseOrder,如果它发生变化,请调用UpdateLayout
3个回答

12

当必要时,您可以重新实现FrameworkElement.ArrangeOverride并以与通常相反的顺序调用所有child.Arrange。

http://msdn.microsoft.com/en-us/library/system.windows.uielement.arrange.aspx

类似于以下内容(未经测试):

    double x = 0;
    double y = 0;

    var children = ReverseOrder ? InternalChildren.Reverse() : InternalChildren;
    foreach (UIElement child in children)
    {
        var size = child.DesiredSize;
        child.Arrange(new Rect(new Point(x, y), size));

        if (Orientation == Horizontal)
            x += size.Width;
        else
            y += size.Height;
    }

在更改ReverseOrder属性后,请确保调用UpdateLayout。


太完美了!谢谢 - 我甚至不用考虑它! ;) - devios1
1
反转UI元素会产生什么影响? 相对于之前,在ArrangeOverride中实际发生了什么? - eran otzap

3

MeasureOverrideArrangeOverride

实际上,你的测量逻辑可能与 StackPanel 相同,因此你可能只需要重写 ArrangeOverride。请注意,StackPanel 有一些处理滚动的逻辑,如果你自己编写它,则可能需要重复这些逻辑。你可能希望直接从 Panel 继承,而不是尝试支持滚动。

请参阅 MSDN 页面上有关面板的 Custom Panel Elements 或有关编写自定义面板的各种博客文章,例如 WPF Tutorial - Creating A Custom Panel Control 或者 Creating Custom Panels In WPF


0

这是另一种变体。它基于StackPanelreference source,并且能够处理项对齐。

public class ReversibleStackPanel : StackPanel
{
    public bool ReverseOrder
    {
        get => (bool)GetValue(ReverseOrderProperty);
        set => SetValue(ReverseOrderProperty, value);
    }

    public static readonly DependencyProperty ReverseOrderProperty =
        DependencyProperty.Register(nameof(ReverseOrder), typeof(bool), typeof(ReversibleStackPanel), new PropertyMetadata(false));


    protected override Size ArrangeOverride(Size arrangeSize)
    {
        bool fHorizontal = (Orientation == Orientation.Horizontal);
        var  rcChild = new Rect(arrangeSize);
        double previousChildSize = 0.0;

        var children = ReverseOrder ? InternalChildren.Cast<UIElement>().Reverse() : InternalChildren.Cast<UIElement>();
        foreach (UIElement child in children)
        {
            if (child == null)
                continue;

            if (fHorizontal)
            {
                rcChild.X += previousChildSize;
                previousChildSize = child.DesiredSize.Width;
                rcChild.Width = previousChildSize;
                rcChild.Height = Math.Max(arrangeSize.Height, child.DesiredSize.Height);
            }
            else
            {
                rcChild.Y += previousChildSize;
                previousChildSize = child.DesiredSize.Height;
                rcChild.Height = previousChildSize;
                rcChild.Width = Math.Max(arrangeSize.Width, child.DesiredSize.Width);
            }

            child.Arrange(rcChild);
        }

        return arrangeSize;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接