Emulates Windows 8 Start Menu Tile Layout Engine

前端 未结 2 1742
谎友^
谎友^ 2021-02-01 08:14

So anyone out there knows of sample code or control that perfectly emulates the Windows 8 Start Menu Tile Layout Engine?

It should support mixed Square and Rectangle Til

相关标签:
2条回答
  • 2021-02-01 08:25

    These are the two different libraries I evaluated for my project to create a Windows 8 like startpage in WPF:

    1. Telerik RadTileList (paid)
    2. mahapps.metro (open source)
    0 讨论(0)
  • 2021-02-01 08:43

    I've looked around myself and couldn't find anything to do what I/we want. I knew that to get this behavior we'd need some sort of custom panel object, so I set about creating one...

    What it boils down to, is the tiles need to be arranged vertically, with double-width tiles taking up a whole row in that column, and normal width tiles to pair up. When it reaches the bottom of the container, it needs to create a new column and follow the same pattern.

    Here's my implementation:

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

    Screenshot of the control in action: enter image description here

    Disclaimers:

    • The MeasureOverride only works by chance, and isn't setup correctly.
    • If you want the nice MetroTile layout, then stick to uniform sizes i.e 100x100 and 200x100
    • I haven't fully tested it, but I will be implementing it into my fake-Metro app, so if you want to see any future changes, just holler.
    • If you want the proper GridView tiling behavior, then we'd have to create a brand new control (to support dragging items around etc).

    I hope this helps.

    0 讨论(0)
提交回复
热议问题