15

因此,任何人都知道完美模拟 Windows 8 开始菜单磁贴布局引擎的示例代码或控件吗?

它应该支持混合的方形和矩形瓷砖,并正确地重新包装矩形瓷砖上方或下方的方形瓷砖。

注意:如果所有瓷砖都是方形的,则 WrapPanel 有效。但是,一旦您混合了跨越 2 平方空间的图块,布局就会中断,并且与 Windows 8 开始菜单不一致

我期待扩展 WPF 面板的代码。


免责声明:是的,我在 Internet 上搜索过,我发现最接近的是 CodeProject 示例,但只有在所有图块都是相同大小的正方形时才有效。

4

2 回答 2

16

我环顾四周,找不到任何可以做我/我们想做的事情。我知道要获得这种行为,我们需要某种自定义面板对象,所以我开始创建一个...

归结为,瓷砖需要垂直排列,双倍宽度的瓷砖占据该列的一整行,正常宽度的瓷砖配对。当它到达容器的底部时,它需要创建一个新列并遵循相同的模式。

这是我的实现:

    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 平铺行为,那么我们必须创建一个全新的控件(以支持拖动项目等)。

我希望这有帮助。

于 2012-07-11T12:14:17.857 回答
0

这些是我为我的项目评估的两个不同的库,用于在 WPF 中创建类似 Windows 8 的起始页:

  1. Telerik RadTileList(付费)
  2. mahapps.metro(开源)
于 2014-12-09T09:20:45.343 回答