如何根据要显示的项目数更改UWP中窗口的布局?

时间:2016-11-07 14:08:27

标签: layout uwp

在我的UWP项目中,我想根据要显示的元素数量拆分窗口。例如,当我只有一个元素时,该元素的显示区域将占据整个窗口。窗口将分成2个窗口,当我有2个元素时,它会上下放置。当我有4个元素时,窗口将分成2 * 2个窗口。有没有人有任何想法可以实现这样的目的?

2 个答案:

答案 0 :(得分:0)

创建一个包含4个Grid容器作为内容的RelativePanel

<RelativePanel>
        <Grid x:Name="TopLeftGrid" Background="Blue" Height="200" Width="200"></Grid>
        <Grid x:Name="BottomLeftGrid" RelativePanel.Below="TopLeftGrid" Background="Green" Height="200" Width="200"></Grid>
        <Grid x:Name="TopRightGrid" RelativePanel.RightOf="TopLeftGrid" Background="Gray" Height="200" Width="200"></Grid>
        <Grid x:Name="BottomRightGrid" RelativePanel.Below="TopRightGrid" RelativePanel.RightOf="BottomLeftGrid" Background="Red" Height="200" Width="200">
        </Grid>
</RelativePanel>

“相对”面板可以轻松创建自适应布局。

现在使用GridValueConverter的可见性绑定到元素数量,Visibility.Visible将返回Visibility.Collapsed public object Convert(object value, Type targetType, object parameter, string language) { // value is here the number of element, you can create for each grid a value converter or // specify a parameter (like name of the grid) // Casting to integer int elements = (int) value; // This could be a possible if statement for the BottomLeftGrid which should only be visible // if you are having 3 elements or more if (elements >= 3) { return Visibility.Visible; } else { // Not more than 2 elements => BottomLeftGrid not visible return Visibility.Collapsed; } } ,具体取决于您的元素数量。< / p>

ValueConverter看起来像这样:

Width

您还可以使用值转换器将Height的{​​{1}}和Grids绑定到元素数量。

补充说明:

  • 当元素数量发生变化时,您需要实现INotifyPropertyChanged界面让ui知道更新
  • 使用MVVM模式CodeProject MVVM Pattern

答案 1 :(得分:0)

  

在我的UWP项目中,我想根据要显示的元素数量拆分窗口。

实现此目标的最佳方法是创建自己的自定义面板。有关创建自定义面板的详细信息:Custom Panel Overview

我创建了一个简单的自定义面板,您可以修改代码以便根据您的详细要求进行调整:

public class AdaptivePanel:Panel
{
    private int rows;
    private int cols;

    protected override Size MeasureOverride(Size availableSize)
    {
        int i = 0;
        int childrenCount = Children.Count;
        //calculate the row count /column count of the panel
        rows = (int)Math.Ceiling(Math.Sqrt((double)childrenCount));
        cols = rows;
        double elementWidth,elementHeight = 0;
        elementWidth = availableSize.Width / cols;
        //for stackpanel height is infinity, take it into consideration
        if (!double.IsInfinity(availableSize.Height))
        {
            elementHeight = availableSize.Height / rows;
        }
        else
        {
            elementHeight = elementWidth;
        }

        foreach (FrameworkElement child in Children)
        {
            //mesure the children
            child.Measure(new Size(elementWidth, elementHeight));
        }

        return new Size(availableSize.Width,double.IsInfinity(availableSize.Height)?availableSize.Width:availableSize.Height);
    }

    protected override Size ArrangeOverride(Size finalSize)
    {

        // Get total number of children
        int count = Children.Count;
        int index = 0;
        UIElement child=null;
        //arrange the elements in the panel
        for(int i=0;i<rows;i++)
        {
            for (int j = 0; j < cols; j++)
            {
                if (index >= count)
                {
                    break;
                }
                child = Children[index];
                double boxLength = finalSize.Width / cols;
                //colNumber=j, rowNumber=i
                double x = finalSize.Width / cols * j;
                double y = finalSize.Height / rows * i;
                //if the element is bigger than the box then use the normal anchorPoint otherwise let it be in the middle of the box.
                double elementX=x, elementY=y;
                if (child.DesiredSize.Width < boxLength)
                {
                    elementX = x + (boxLength - child.DesiredSize.Width) / 2;
                }
                if (child.DesiredSize.Height < boxLength)
                {
                    elementY = y + (boxLength - child.DesiredSize.Height) / 2;
                }

                Point anchorPoint = new Point(elementX, elementY);
                Children[index].Arrange(new Rect(anchorPoint,child.DesiredSize));
                index++;
            }
        }


        return finalSize;
}

用法:

<Page
...
xmlns:panels="using:AdaptivePanelSample.Panels"
mc:Ignorable="d">
<panels:AdaptivePanel x:Name="myPanel">
    <Rectangle Width="200" Height="200" Fill="Aqua"/>
    <Rectangle Width="200" Height="200" Fill="Aqua"/>
    <Rectangle Width="200" Height="200" Fill="Aqua"/>
</panels:AdaptivePanel>
</page>

这是完整的演示:AdaptivePanelSample