模拟Windows 8开始菜单平铺布局引擎

the*_*ker 14 c# wpf wpf-controls microsoft-metro

那么那里的任何人都知道完全模拟Windows 8开始菜单平铺布局引擎的示例代码或控件?

它应该支持混合的Square和Rectangle Tiles,并正确地重新打包矩形块上方或下方的方块.

注意:如果ALL TILES为Square,则WrapPanel有效.但是一旦你混合了占地2平方的空间的瓷砖,布局就会中断,并且与Windows 8开始菜单不一致

我期待扩展WPF Panel的代码.


免责声明:是的我已经在互联网上搜索过,我发现的最接近的是CodeProject示例,但只有在所有磁贴都是相同大小的方块时才有效.

mor*_*are 15

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

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

这是我的实现:

    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;
    }
}
Run Code Online (Sandbox Code Playgroud)

操作中的控件的屏幕截图: 在此输入图像描述

免责声明:

  • MeasureOverride只是偶然使用,并且设置不正确.
  • 如果你想要漂亮的MetroTile布局,那么坚持统一尺寸,即100x100和200x100
  • 我还没有完全测试它,但我会将它实现到我的假地铁应用程序中,所以如果你想看到任何未来的变化,那就大声说.
  • 如果你想要正确的GridView平铺行为,那么我们必须创建一个全新的控件(以支持拖动项目等).

我希望这有帮助.