Фиксированная панель Wrap wpf

я работаю над окном wpf, которое показывает список элементов рядом друг с другом с оберткой, я пытался использовать WrapPanel таким образом:

<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>

и это результат:

введите здесь описание изображения

На самом деле этот результат неудовлетворителен для меня, потому что если вы представите WrapPanel как сетку (строки и столбцы), вы обнаружите, что столбцов нет, но есть строки фиксированного размера. мне нужно сделать WarpPanel или еще какой-то элемент управления без столбцов, посмотрите на это воображаемое изображение:

введите здесь описание изображения

обратите внимание, что нет ни строк, ни столбцов. это то, что я хочу сделать.

у кого-нибудь есть идеи по решению этой проблемы?


person Heysem Katibi    schedule 08.04.2013    source источник
comment
я не могу увидеть ни одного изображения..   -  person Bathineni    schedule 08.04.2013
comment
Как уже писал Клеменс, вам нужно будет написать свою собственную панель с какой-то упаковкой. Это может быть хорошей статьей начать.   -  person dowhilefor    schedule 08.04.2013


Ответы (2)


Вы можете написать свой собственный класс Panel. В Интернете есть несколько руководств, просто погуглите «пользовательская панель wpf».

Это сводится к переопределению MeasureOverride и ArrangeOverride.

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;
    }
}

ОБНОВЛЕНИЕ: следующая простая пользовательская панель может более или менее делать то, что вы хотите.

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;
    }
}
person Clemens    schedule 08.04.2013
comment
извините, но там десятки must-check случаев, а способ проверки очень сложный :( это единственный способ сделать нужную панель? - person Heysem Katibi; 08.04.2013
comment
Не уверен, что именно вы имеете в виду под случаями обязательной проверки, но расчет, необходимый для размещения дочерних элементов, должен быть где-то выполнен. Если вы не можете найти существующий класс Panel с желаемым поведением (а я сомневаюсь, что сможете), вам придется сделать это самостоятельно. - person Clemens; 08.04.2013

Вы можете использовать Canvas:

Или используйте сетку и установите поле каждой кнопки в соответствии с требованиями.

     <Canvas >
        <Button Content="s" Width="50" Canvas.Left="17" Canvas.Top="20" />
        <Button Canvas.Left="73" Canvas.Top="32" Content="s" Width="60" Height="42" />
        <Button Canvas.Left="139" Canvas.Top="10" Content="s" Height="42" Width="60" />
     </Canvas>

      <Grid >
            <Button Content="01" Height="30" Width="70" Margin="20,12,414,268" />
            <Button Content="02" Height="35" Width="72" Margin="426,148,6,128" />
            <Button Content="03" Height="20" Width="74" Margin="190,122,240,170" />
            <Button Content="04" Height="25" Width="76" Margin="386,26,40,260" />
            <Button Content="05" Height="18" Width="78" Margin="376,202,48,92" />
            <Button Content="06" Height="50" Width="70" Margin="385,64,48,196" />
            <Button Content="07" Height="40" Width="72" Margin="162,202,269,68" />
            <Button Content="08" Height="55" Width="74" Margin="20,154,408,102" />
            <Button Content="09" Height="45" Width="76" Margin="21,95,406,171" />
            <Button Content="10" Height="25" Width="78" Margin="44,47,382,239" />
            <Button Content="11" Height="20" Width="80" Margin="386,120,38,170" />
            <Button Content="12" Height="30" Width="70" Margin="95,13,338,268" />
            <Button Content="13" Height="45" Width="72" Margin="290,6,140,260" />
            <Button Content="14" Height="30" Width="74" Margin="210,38,220,244" />
            <Button Content="15" Height="20" Width="76" Margin="128,48,299,242" />
            <Button Content="16" Height="25" Width="78" Margin="265,189,160,97" />
            <Button Content="17" Height="35" Width="80" Margin="176,154,246,122" />
            <Button Content="18" Height="50" Width="70" Margin="100,146,333,116" />
            <Button Content="19" Height="55" Width="72" Margin="270,121,160,135" />
            <Button Content="20" Height="45" Width="74" Margin="348,148,81,118" />
            <Button Content="21" Height="20" Width="76" Margin="94,78,332,212" />
            <Button Content="22" Height="60" Width="78" Margin="270,60,155,192" />
            <Button Content="23" Height="20" Width="80" Margin="176,74,247,216" />
            <Button Content="24" Height="25" Width="70" Margin="194,95,238,191" />
            <Button Content="25" Height="30" Width="72" Margin="117,104,314,177" />

    </Grid>
person YOusaFZai    schedule 08.04.2013