用“那种”双向包裹的包裹面板

时间:2011-10-02 09:28:17

标签: wpf wrapping wrappanel

所以我有一个垂直包裹的包装纸。这些项目是在运行时添加的,但是所有这些项目(用户控件)都有不同的宽度,并且因为wrappanel是垂直包装的,所以它们将它们堆叠起来,当它们覆盖垂直空间时,它们会包裹到下一列。但我需要的是“有点”双向包装,即我添加了宽度为200px的第一个项目,然后我添加了第二个项目,其宽度为50px,但是当我添加第三个项目,如100px in宽度我希望它不要去下一行,但是将自己置于那个50px控件留在那里的自由点,这取决于顶部的200px控件(留下150px空间和100px控件明显适合)。当然,当它不适合时,它会包裹到下一行,这一切都没问题。

这是一张图片来澄清这一点(这里不能上传'):

这就是发生的事情: image 1

这就是我想要的: image 2


对不起我的英语,这不是我的主要语言。我希望你能理解我的问题。

2 个答案:

答案 0 :(得分:0)

你绝对不能使用单个面板来实现这一目标!您可以使用stackpanel在哪里插入多个动态包装带水平方向,以获得所需的“列”行为

答案 1 :(得分:0)

好吧,我做到了。刚刚用我想要的行为写了一个自定义的包装。

这是:

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