我有一个包含可变数量控件的包装面板。
我希望方向是垂直的(因为其中的对象将具有固定宽度但可变高度)。
但我遇到的问题是,当存在滚动条时,高度是无限的,因此项目永远不会包裹在第二列上。滚动条是必要的,因为通常会有更多的对象,而不是可以放在一个屏幕上。 我可以通过设置固定高度来阻止这种情况,但这不是一个可接受的解决方案,因为每个选择的合理固定高度会有所不同。
基本上我想要一个WrapPanel
,其高度根据面板的宽度和其中包含的项目数量动态变化。
举例说明:
如果面板宽度足以显示3列,它将:
| 1 5 9 |
| 2 6 - |
| 3 7 - |高度= 4
| 4 8 - |
但是如果用户将窗口的大小更改为只能容纳2列的位置,则高度会增加:
| 1 6 |
| 2 7 |
| 3 8 |高度= 5
| 4 9 |
| 5 - |
另外,我不确定这是多么可行,但我理想情况下喜欢物品的顺序,但保持方向垂直,所以他们会被命令:
| 1 2 3 |
| 4 5 6 |
| 7 8 9 |
有人能告诉我如何开始这个吗?我假设可以使用WrapPanel
的自定义实现,但我有点困惑如何开始。
谢谢,
答案 0 :(得分:3)
使用以下代码管理以实现我所需的功能:
public class InvertedWrapPanel : WrapPanel
{
private int itemsPerRow = 0;
protected override Size MeasureOverride(Size availableSize)
{
if (Orientation == Orientation.Horizontal)
{
return base.MeasureOverride(availableSize);
}
else //Orientation is vertical
{
double w = availableSize.Width;
double maxChildWidth = 0;
foreach (UIElement child in Children)
{
//Get the current childs desired size parameters
child.Measure(availableSize);
//Store off the maximum child width
if (child.DesiredSize.Width > maxChildWidth)
maxChildWidth = child.DesiredSize.Width;
}
//See how many items we can fit in a row
itemsPerRow = Convert.ToInt32(Math.Floor(w / maxChildWidth));
return base.MeasureOverride(availableSize);
}
}
protected override Size ArrangeOverride(Size finalSize)
{
if (Orientation == Orientation.Horizontal)
{
return base.ArrangeOverride(finalSize);
}
else //Orientation is vertical
{
double currentX = 0;
double currentY = 0;
int col = 0;
double lastX = 0;
double lastWidth = 0;
//Arrays to store differing column heights
double[] lastY = new double[itemsPerRow];
double[] lastHeight = new double[itemsPerRow];
double[] colHeights = new double[itemsPerRow];
foreach (UIElement child in Children)
{
//If we've reached the end of a row
if (col >= itemsPerRow)
{
col = 0;
currentX = 0; //reset the x-coordinate for first column
}
else
currentX = lastX + lastWidth; //Increase the x-coordinate
//Increase the y-coordinates for the current column
currentY = lastY[col] + lastHeight[col];
//Draw the element
child.Arrange(new Rect(currentX, currentY, child.DesiredSize.Width, child.DesiredSize.Height));
//Store off the current child's parameters
lastX = currentX;
lastWidth = child.DesiredSize.Width;
lastY[col] = currentY;
lastHeight[col] = child.DesiredSize.Height;
colHeights[col] += child.DesiredSize.Height;
col++;
}
//Set the height of the panel to the max column height.
//Otherwise scroll bar will set height to infinity.
double maxHeight = 0;
foreach (double d in colHeights)
{
if (d > maxHeight)
maxHeight = d;
}
base.Height = maxHeight;
return finalSize;
}
}