c# - 如何使包含 ItemsControl 的 WPF 网格具有相同大小的列

标签 c# .net wpf

还有类似的问题herehere ,但我已经尝试了它们中的所有方法,但它们并没有解决我的问题。

我想在 WPF(布局)网格中的屏幕上显示复选框网格。这些复选框具有可变长度的文本。我希望所有列的宽度相同,并且它们都显示文本而不被截断。也就是说,我需要它们都具有最长文本的宽度。我希望屏幕本身的大小适合内容。也就是说,宽度要足以显示所有复选框。

复选框列表会根据其他因素而变化,因此我使用 ItemsControl 来显示它们。代码的简化版本如下。

如果运行此命令,带有“长文本”的列(即第二列)比带有较短文本的列宽得多。为了使它们具有相同的宽度,我尝试使用 SharedSizeGroup,还尝试在列加载事件中设置 MaxWidth = ActualWidth,这是其他地方建议的解决方案,但这些不起作用。

我确信这个问题一定有一个简单的答案,这似乎是使用布局控件要做的相当基本的事情。请问我做错了什么?

XAML:

<Window x:Class="GridColsEqualSize.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" SizeToContent="WidthAndHeight" FontSize="25">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" /> <!-- In the real project second row is for OK/Cancel buttons -->
        </Grid.RowDefinitions>
        <ItemsControl ItemsSource="{Binding CheckBoxItems}"  Grid.Row="0" Grid.Column="0">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <!--Whatever I do I can't get the screen to resize and the cols to have the same width-->
                            <ColumnDefinition Width="Auto" SharedSizeGroup="A" />
                            <ColumnDefinition Width="Auto" SharedSizeGroup="A" />
                            <ColumnDefinition Width="Auto" SharedSizeGroup="A" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                    </Grid>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <CheckBox Content="{Binding Text}" IsChecked="{Binding Enabled}"                            
                                  Margin="0,0,10,0"></CheckBox>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Style.Setters>
                        <Setter Property="Grid.Row" Value="{Binding GridRow}" />
                        <Setter Property="Grid.Column" Value="{Binding GridColumn}" />
                    </Style.Setters>
                </Style>
            </ItemsControl.ItemContainerStyle>
        </ItemsControl>
    </Grid>
</Window>

C#:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            CheckBoxItems = new List<CheckBoxItem>
            {
                new CheckBoxItem("A", true),
                new CheckBoxItem("B"),
                new CheckBoxItem("C", true),
                new CheckBoxItem("D"),
                new CheckBoxItem("E", true),
                new CheckBoxItem("F"),
                new CheckBoxItem("G"),
                new CheckBoxItem("Long text", true),
                new CheckBoxItem("")

            };
            SetCheckBoxItemRowsAndColumns();
        }

        public List<CheckBoxItem> CheckBoxItems { get; set; }

        private void SetCheckBoxItemRowsAndColumns()
        {
            int currentColumn = 0;
            int currentRow = 0;
            foreach (CheckBoxItem checkBoxItem in CheckBoxItems)
            {
                checkBoxItem.GridColumn = currentColumn;
                checkBoxItem.GridRow = currentRow;
                if (currentColumn != 2)
                {
                    currentColumn++;
                }
                else
                {
                    currentRow++;
                    currentColumn = 0;
                }
            }
        }

        public class CheckBoxItem
        {
            public CheckBoxItem(string text, bool enabled = false)
            {
                Text = text;
                Enabled = enabled;
            }

            public string Text { get; set; }
            public bool Enabled { get; set; }
            public int GridRow { get; set; }
            public int GridColumn { get; set; }
        }

        private void FrameworkContentElement_OnLoaded(object sender, RoutedEventArgs e)
        {
            ((ColumnDefinition)sender).MaxWidth = ((ColumnDefinition)sender).ActualWidth;
        }
    }

最佳答案

一切都很好:)您已经选择了正确的解决方案“SharedSizeGroup”

您只需将 Grid.IsSharedSizeScope="True"添加到您的 ItemsControl 中:

    ...
    </Grid.RowDefinitions>
    <ItemsControl Grid.IsSharedSizeScope="True" ItemsSource="{Binding CheckBoxItems}"  Grid.Row="0" Grid.Column="0" >
        <ItemsControl.ItemsPanel>
    ...

关于c# - 如何使包含 ItemsControl 的 WPF 网格具有相同大小的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28828492/

相关文章:

c# - 如何以编程方式获取特定服务器标识

c# - FluentValidation DI 将值传递给子验证器

c# - C# await 关键字是否会导致函数调用阻塞?

c# - 如何将 MenuItem 从一个 ContextMenu 复制到另一个 ContextMenu

c# - WPF:如何为内容更改创建路由事件?

c# - WPF UI不刷新

c# - 如何正确实现 TAP 方法?

c# - 为什么Reflector无法显示字节数组?这是由于某些技术限制吗?

c# - 限制 .NET 进程可以使用的最大 RAM 量?

wpf - 如何确定 View Model 中定义的属性是否绑定(bind)到 UI 中的任何控件?