Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fixed Wrap panel wpf

Tags:

wpf

wrappanel

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:

<Grid>
    <ItemsControl>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

        <ItemsControl.Items>
            <Button Content="01" Height="30" Width="70"/>
            <Button Content="02" Height="35" Width="72"/>
            <Button Content="03" Height="20" Width="74"/>
            <Button Content="04" Height="25" Width="76"/>
            <Button Content="05" Height="18" Width="78"/>
            <Button Content="06" Height="50" Width="70"/>
            <Button Content="07" Height="40" Width="72"/>
            <Button Content="08" Height="55" Width="74"/>
            <Button Content="09" Height="45" Width="76"/>
            <Button Content="10" Height="25" Width="78"/>
            <Button Content="11" Height="20" Width="80"/>
            <Button Content="12" Height="30" Width="70"/>
            <Button Content="13" Height="45" Width="72"/>
            <Button Content="14" Height="30" Width="74"/>
            <Button Content="15" Height="20" Width="76"/>
            <Button Content="16" Height="25" Width="78"/>
            <Button Content="17" Height="35" Width="80"/>
            <Button Content="18" Height="50" Width="70"/>
            <Button Content="19" Height="55" Width="72"/>
            <Button Content="20" Height="45" Width="74"/>
            <Button Content="21" Height="20" Width="76"/>
            <Button Content="22" Height="60" Width="78"/>
            <Button Content="23" Height="20" Width="80"/>
            <Button Content="24" Height="25" Width="70"/>
            <Button Content="25" Height="30" Width="72"/>
        </ItemsControl.Items>
    </ItemsControl>
</Grid>

and this is the result:

enter image description here

Actually this result is unsatisfactory for me because if you imagine the WrapPanel as grid(rows and columns) you will find that there is no columns, but there are fixed size rows. i need to make WarpPanel or some control else without columns too, look at this imaginary image:

enter image description here

notice that there is no rows and no columns. this is what i wanna make.

anybody have ideas to solve this issue?

like image 558
Heysem Katibi Avatar asked Apr 08 '13 08:04

Heysem Katibi


1 Answers

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;
    }
}
like image 117
Clemens Avatar answered Oct 27 '22 17:10

Clemens