我环顾四周,找不到任何可以做我/我们想做的事情。我知道要获得这种行为,我们需要某种自定义面板对象,所以我开始创建一个...
归结为,瓷砖需要垂直排列,双倍宽度的瓷砖占据该列的一整行,正常宽度的瓷砖配对。当它到达容器的底部时,它需要创建一个新列并遵循相同的模式。
这是我的实现:
public class MetroTilePanel : Panel
{
protected override Size ArrangeOverride(System.Windows.Size finalSize)
{
double x = 0, y = 0, colWidth = 0, rowHeight = 0;
int col = 0;
colWidth = Children.Cast<UIElement>().Select(c => c.DesiredSize.Width).Max();
foreach (UIElement child in Children)
{
rowHeight = Math.Max(rowHeight, child.DesiredSize.Height);
if (x + child.DesiredSize.Width > (colWidth * (col + 1)))
{
// New row
y += rowHeight;
x = (colWidth * (col));
rowHeight = child.DesiredSize.Height;
}
if (y + rowHeight > finalSize.Height)
{
// New column
col++;
x = (colWidth * (col));
y = 0;
}
child.Arrange(new Rect(x, y, child.DesiredSize.Width, child.DesiredSize.Height));
x += child.DesiredSize.Width;
}
return finalSize;
}
protected override Size MeasureOverride(Size availableSize)
{
double x = 0, y = 0, colWidth = 0;
foreach (UIElement child in Children)
{
child.Measure(availableSize);
if (x + child.DesiredSize.Height > availableSize.Height)
{
x += colWidth;
y = 0;
colWidth = 0;
}
y += child.DesiredSize.Height;
if (child.DesiredSize.Width > colWidth)
{
colWidth = child.DesiredSize.Width;
}
}
x += colWidth;
var resultSize = new Size();
resultSize.Width = double.IsPositiveInfinity(availableSize.Width) ? x : availableSize.Width;
resultSize.Height = double.IsPositiveInfinity(availableSize.Height) ? y : availableSize.Height;
return resultSize;
}
}
正在运行的控件的屏幕截图:
免责声明:
- MeasureOverride 只是偶然起作用,并且设置不正确。
- 如果您想要漂亮的 MetroTile 布局,请坚持统一尺寸,即 100x100 和 200x100
- 我还没有完全测试它,但我会在我的假 Metro 应用程序中实现它,所以如果你想看到未来的任何变化,请大声疾呼。
- 如果您想要正确的 GridView 平铺行为,那么我们必须创建一个全新的控件(以支持拖动项目等)。
我希望这有帮助。