Панель обертывания с двухсторонней оберткой

Итак, у меня есть обертка, которая завернута вертикально. Элементы добавляются во время выполнения, но все эти элементы (пользовательские элементы управления) имеют разную ширину, и поскольку оболочка обернута вертикально, она складывает их вниз, а когда они покрывают вертикальное пространство, они переносятся в следующий столбец. НО мне нужно "своего рода" двустороннее обертывание, т.е. я добавил первый элемент шириной 200 пикселей, затем я добавил второй элемент шириной 50 пикселей, но когда я добавляю третий элемент размером 100 пикселей в width Я хочу, чтобы он не переходил к следующей строке, а помещал себя в это свободное место, оставленный там элемент управления 50 пикселей, в зависимости от этого элемента управления 200 пикселей вверху (это оставляет пространство 150 пикселей, а элемент управления 100 пикселей явно подходит). Конечно, когда он не подходит, он переносится на следующую строку, и все в порядке.

Вот изображения, чтобы прояснить это (не могу загрузить их сюда):

Вот что происходит: изображение 1

И вот чего я хочу: изображение 2


Извините за мой английский, это не мой основной язык. Надеюсь, вы поймете мой вопрос.


person vytaslll    schedule 02.10.2011    source источник


Ответы (2)


Вы определенно не можете использовать одну панель для этого! Вы можете использовать панель стека, где можно вставить несколько динамических панелей-оберток с горизонтальной ориентацией, чтобы иметь необходимое вам поведение "столбца".

person MaRuf    schedule 02.10.2011
comment
Проблема в том, что я должен использовать для этого одну панель: \ Я могу сделать что-то вроде Wrappanel-in-a-wrappanel, но у меня это не работает ... Я думал о кастомной wrappanel, но вот что Я спрашиваю; как написать тот, который работает в моем описанном поведении:? - person vytaslll; 02.10.2011

Хорошо, я сделал это. Просто написал настраиваемую оболочку с нужным мне поведением.

Вот:

public class TwoWayWrapPanel : Panel
{
int _rowCount = 0;

public int RowCount
{
    get { return _rowCount; }
    set { _rowCount = value; }
}

protected override Size MeasureOverride(Size availableSize)
{
    Size resultSize = new Size(0, 0);
    double columnWidth = 0;
    double usedSpace = 0;
    double nullX = 0;
    double currentX = 0;
    double currentY = 0;
    bool isFirst = true;
    int row = 0;

    foreach (UIElement child in Children)
    {
        child.Measure(availableSize);

        if (isFirst)
        {
            columnWidth = child.DesiredSize.Width;
            resultSize.Width += columnWidth;
            currentY += child.DesiredSize.Height;
            row++;
            isFirst = false;
        }
        else
        {
            if (columnWidth >= usedSpace + child.DesiredSize.Width & _rowCount > 1)
            {
                currentX = nullX + usedSpace;
                usedSpace += child.DesiredSize.Width;
            }
            else
            {
                row++;

                if (row + 1 > _rowCount | child.DesiredSize.Width > columnWidth)
                {
                    row = 0;
                    currentX = nullX + columnWidth;
                    nullX = currentX;
                    usedSpace = 0;
                    columnWidth = child.DesiredSize.Width;
                    currentY = child.DesiredSize.Height;
                    row++;
                    resultSize.Width += columnWidth;
                }
                else
                {
                    currentY += child.DesiredSize.Height;
                    currentX = nullX;
                    usedSpace = child.DesiredSize.Width;
                }
            }
        }
    }

    return resultSize;
}

protected override Size ArrangeOverride(Size finalSize)
{
    double columnWidth = 0;
    double usedSpace = 0;
    double nullX = 0;
    double currentX = 0;
    double currentY = 0;
    bool isFirst = true;
    int row = 0;

    foreach (UIElement child in Children)
    {
        //First item in the collection
        if (isFirst)
        { 
            child.Arrange(new Rect(currentX, currentY, child.DesiredSize.Width, child.DesiredSize.Height));
            columnWidth = child.DesiredSize.Width;
            currentY += child.DesiredSize.Height;
            row++;
            isFirst = false;
        }
        else
        {
            //Current item fits so place it in the same row
            if (columnWidth >= usedSpace + child.DesiredSize.Width & _rowCount > 1)
            {
                currentX = nullX + usedSpace;
                child.Arrange(new Rect(currentX, currentY, child.DesiredSize.Width, child.DesiredSize.Height));
                usedSpace += child.DesiredSize.Width;
            }
            else
            {
                row++;

                //The row limit is reached or the item width is greater than primary item width. Creating new column
                if (row + 1 > _rowCount | child.DesiredSize.Width > columnWidth)
                {
                    row = 0;
                    currentY = 0;
                    currentX = nullX + columnWidth;
                    nullX = currentX;
                    usedSpace = 0;
                    child.Arrange(new Rect(currentX, currentY, child.DesiredSize.Width, child.DesiredSize.Height));
                    columnWidth = child.DesiredSize.Width;
                    currentY += child.DesiredSize.Height;
                    row++;
                }
                //Item doesn't fit. Adding to the new row in the same column
                else
                {
                    usedSpace = 0;
                    currentY += child.DesiredSize.Height;
                    currentX = nullX;
                    child.Arrange(new Rect(currentX, currentY, child.DesiredSize.Width, child.DesiredSize.Height));
                    usedSpace += child.DesiredSize.Width;
                }
            }
        }
    }

    return finalSize;
}
}
person vytaslll    schedule 02.10.2011