Fixed Wrap panel wpf

前端 未结 2 2088
误落风尘
误落风尘 2021-02-07 15:11

i am working on wpf window that show list of items next each other with wrapping, i have tried to use WrapPanel in this way:


    

        
2条回答
  •  没有蜡笔的小新
    2021-02-07 15:28

    You could write your own custom Panel class. There are some tutorials on the web, simply google "wpf custom panel".

    It boils down to overriding the MeasureOverride and ArrangeOverride methods.

    public class CustomPanel : Panel
    {
        protected override Size MeasureOverride(Size availableSize)
        {
            Size panelDesiredSize = new Size();
    
            foreach (UIElement child in InternalChildren)
            {
                child.Measure(availableSize);
    
                // Use child.DesiredSize, availableSize.Width and the positions
                // and sizes of the previous children to calculate the position of
                // the current child. Then determine the resulting Panel height.
                panelDesiredSize = ...
            }
    
            return panelDesiredSize;
        }
    
        protected override Size ArrangeOverride(Size finalSize)
        {
            foreach (UIElement child in InternalChildren)
            {
                // Arrange each child according to the position calculations
                // done in MeasureOverride
                Point position = ...
                child.Arrange(new Rect(position, child.DesiredSize));
            }
    
            return finalSize;
        }
    }
    

    UPDATE: The following simple custom Panel might more or less do what you want.

    public class PackPanel : Panel
    {
        protected override Size MeasureOverride(Size availableSize)
        {
            foreach (UIElement child in InternalChildren)
            {
                child.Measure(availableSize);
            }
    
            var positions = new Point[InternalChildren.Count];
            var desiredHeight = ArrangeChildren(positions, availableSize.Width);
    
            return new Size(availableSize.Width, desiredHeight);
        }
    
        protected override Size ArrangeOverride(Size finalSize)
        {
            var positions = new Point[InternalChildren.Count];
            ArrangeChildren(positions, finalSize.Width);
    
            for (int i = 0; i < InternalChildren.Count; i++)
            {
                var child = InternalChildren[i];
                child.Arrange(new Rect(positions[i], child.DesiredSize));
            }
    
            return finalSize;
        }
    
        private double ArrangeChildren(Point[] positions, double availableWidth)
        {
            var lastRowStartIndex = -1;
            var lastRowEndIndex = 0;
            var currentWidth = 0d;
            var desiredHeight = 0d;
    
            for (int childIndex = 0; childIndex < InternalChildren.Count; childIndex++)
            {
                var child = InternalChildren[childIndex];
                var x = 0d;
                var y = 0d;
    
                if (currentWidth == 0d || currentWidth + child.DesiredSize.Width <= availableWidth)
                {
                    x = currentWidth;
                    currentWidth += child.DesiredSize.Width;
                }
                else
                {
                    currentWidth = child.DesiredSize.Width;
                    lastRowStartIndex = lastRowEndIndex;
                    lastRowEndIndex = childIndex;
                }
    
                if (lastRowStartIndex >= 0)
                {
                    int i = lastRowStartIndex;
    
                    while (i < lastRowEndIndex - 1 && positions[i + 1].X < x)
                    {
                        i++;
                    }
    
                    while (i < lastRowEndIndex && positions[i].X < x + child.DesiredSize.Width)
                    {
                        y = Math.Max(y, positions[i].Y + InternalChildren[i].DesiredSize.Height);
                        i++;
                    }
                }
    
                positions[childIndex] = new Point(x, y);
                desiredHeight = Math.Max(desiredHeight, y + child.DesiredSize.Height);
            }
    
            return desiredHeight;
        }
    }
    

提交回复
热议问题