代码之家  ›  专栏  ›  技术社区  ›  devios1

在WPF中构建可逆堆叠面板

  •  9
  • devios1  · 技术社区  · 14 年前

    我想建立一个习惯 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 );
    }
    

    同时定义和注册 回复顺序 并打电话 UpdateLayout 如果它改变了。

    3 回复  |  直到 7 年前
        1
  •  12
  •   ggarber    14 年前

    可以重新实现frameworkelement.arrangeoverride并调用所有子级。必要时按与通常相反的顺序排列。

    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。

        2
  •  3
  •   Quartermeister    14 年前

    MeasureOverride ArrangeOverride

    实际上,您的度量逻辑可能与stackpanel相同,因此您可能只能够覆盖arrangeoverride。请注意,stackpanel有一些逻辑来处理滚动,如果您自己写的话,可能需要复制它。您可能希望直接从面板继承,而不尝试支持滚动。

    Custom Panel Elements 在面板上的msdn页面中,或在编写自定义面板(如 WPF Tutorial - Creating A Custom Panel Control Creating Custom Panels In WPF .

        3
  •  0
  •   vines helsinki    7 年前

    这是另一种变体。它是建立在 StackPanel reference 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;
        }
    }