繁体   English   中英

C#/ WPF-均匀拉伸嵌套ItemsControl中的按钮以填充整个空间

[英]C#/WPF - Equally stretch buttons in nested ItemsControl to fill in entire space

首先,我有一个ItemsControl ,旨在显示几组内容; 每个组中都有另一个ItemsControl ,旨在在其中显示服务器Button

我的.xaml:

<Window x:Class="CX11TestSolution.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="768"
    Width="1024">
<ItemsControl ItemsSource="{Binding HahaList}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Label Content="{Binding Name}" />
                <ItemsControl Grid.Row="1"
                              ItemsSource="{Binding ItemList}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <UniformGrid Columns="5" />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Button Content="{Binding Name}" />
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="1" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

我的.xaml.cs:

public partial class MainWindow : Window
{
    public IEnumerable<SomeClass> HahaList { get; }
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        HahaList = new List<SomeClass>()
        {
            new SomeClass("Group 1", new List<SomeClass>() {
                new SomeClass("11"),
                new SomeClass("12"),
                new SomeClass("13"),
                new SomeClass("14"),
                new SomeClass("15"),
                new SomeClass("16"),
            }),
            new SomeClass("Group 2", new List<SomeClass>() {
                new SomeClass("21"),
                new SomeClass("22"),
                new SomeClass("23"),
                new SomeClass("24"),
            }),
            new SomeClass("Group 3", new List<SomeClass>() {
                new SomeClass("31"),
                new SomeClass("32"),
                new SomeClass("33"),
            }),
            new SomeClass("Group 4", new List<SomeClass>() {
                new SomeClass("41"),
                new SomeClass("42"),
            }),
            new SomeClass("Group 5", new List<SomeClass>() {
                new SomeClass("52"),
            }),
        };
    }
}

public class SomeClass
{
    public string Name { get; }
    public IEnumerable<SomeClass> ItemList { get; }
    public SomeClass(string name, IEnumerable<SomeClass> list)
    {
        Name = name;
        ItemList = list;
    }
    public SomeClass(string name)
    {
        Name = name;
    }
}

结果: 结果

所以我的问题是,我如何平等地拉伸按钮的高度,以便它们可以填充整个区域?

事实上,我试图设置ItemsPanelItemsControlUniformGrid具有Columns的1,和它的工作时按钮的每个组中的数量不超过5,当其超过5,第六按钮将跳到下一行,因此缩小第一行以使每个组具有相同的高度。 在此处输入图片说明 先感谢您。

我将使用网格手动执行此操作。 您知道最多有5列,因此可以很容易地精确计算出包含所有内容的网格所需的列数和行数。 使用附加行为,以便您可以在运行时动态设置网格的行和列,还需要一个标志来指定每行是“自动”(标题)还是“ 1 *”(等距)。 最后,将字段添加到SomeClass中以获取Grid列和行号,并将其绑定到XAML中。

可能有一种在纯XAML或自定义布局类中执行此操作的方法,但是我上面描述的方法只需要10分钟左右的时间即可编写代码,并且易于测试和调试,因此您可能会节省很多时间从长远来看头痛。

更新:

我刚刚实现了执行此操作的方法,它要求您将其添加到主视图模型中:

    public int RowCount { get; set; }
    public int ColumnCount {get; set; }     
    public string StarCount { get; set; }
    public string StarRows { get; set; }
    public string StarColumns { get; set; }
    public List<Tuple<SomeClass, bool>> AllItems { get; set; } // second parameter indicates whether it's a header


    private void UpdateGridLayout()
    {
        this.AllItems = new List<Tuple<SomeClass, bool>>();

        this.ColumnCount = 5;
        this.RowCount = HahaList.Sum(x => 1 + (x.ItemList.Count() + this.ColumnCount - 1) / this.ColumnCount);
        int row = 0;
        this.StarColumns = String.Join(",", Enumerable.Range(0, this.ColumnCount).Select(i => i.ToString())); // all columns
        this.StarRows = null;
        foreach (var section in this.HahaList)
        {
            this.AllItems.Add(new Tuple<SomeClass, bool>(section, true));
            section.Row = row;
            section.Column = 0;
            section.ColumnSpan = this.ColumnCount;

            row++;
            if (StarRows != null)
                StarRows += ",";
            StarRows += row.ToString();
            int column = 0;             
            foreach (var item in section.ItemList)
            {
                this.AllItems.Add(new Tuple<SomeClass, bool>(item, false));
                item.Row = row;
                item.Column = column++;
                item.ColumnSpan = 1;
                if (column >= this.ColumnCount)
                {                       
                    column = 0;
                    row++;
                    if (StarRows != null)
                        StarRows += ",";
                    StarRows += row.ToString();
                }

            }
            row++;
        }
        return;
    }

设置HahaList之后,需要调用UpdateGridLayout,如果您希望它支持动态更改,那么显然您必须全部经过并添加INPC。 此代码中的一个显着区别是添加了“ AllItems”属性,该属性同时具有标头和叶节点,以及一个标志,指示每个类型是哪种类型(我自己会使用不同的类,因此您不必这样做)。

SomeClass还需要一些额外的属性:

    public int Row { get; set; }
    public int Column { get; set; }
    public int ColumnSpan { get; set; }

这是XAML:

<ItemsControl ItemsSource="{Binding AllItems}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid local:GridHelpers.RowCount="{Binding RowCount}"
                  local:GridHelpers.ColumnCount="{Binding ColumnCount}"
                  local:GridHelpers.StarRows="{Binding StarRows}"
                  local:GridHelpers.StarColumns="{Binding StarColumns}"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Grid.Row" Value="{Binding Item1.Row}" />
            <Setter Property="Grid.Column" Value="{Binding Item1.Column}" />
            <Setter Property="Grid.ColumnSpan" Value="{Binding Item1.ColumnSpan}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ContentControl>
                <ContentControl.Style>
                    <Style TargetType="ContentControl">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate>
                                    <Label Content="{Binding Item1.Name}" />
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Item2}" Value="false">
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate>
                                            <Button Content="{Binding Item1.Name}" />
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentControl.Style>
            </ContentControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

XAML使用一个名为GridHelpers的类,该类可帮助创建动态行和列,您可以从Rachael Lim的Blog中获取源代码。

结果:

在此处输入图片说明

这是可以使用Viewbox地方,但有副作用。

更改按钮上的MinWidth即可获得所需的“标签与按钮”比率,因为当窗口缩小时设计会受到影响,但在尺寸增加时效果会很好。

使用者介面范例

<Viewbox Stretch="Fill">
    <ItemsControl ItemsSource="{Binding HahaList}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Label Content="{Binding Name}"/>
                    <ItemsControl Grid.Row="1"
                          ItemsSource="{Binding ItemList}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <UniformGrid Columns="5"/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Button Content="{Binding Name}" MinWidth="75"/>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</Viewbox>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM