【发布时间】:2015-05-03 21:48:37
【问题描述】:
与here 和here 有类似的问题,但我已经尝试了它们中的所有方法,但它们并没有解决我的问题。
我想在屏幕上的 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;
}
}
【问题讨论】:
-
您是否尝试使用 UniformGrid 代替? UniformGrid 安排了一个网格,其中所有单元格和行的大小都相同。
-
使用 UniformGrid 将为您节省
GridRow和GridColumn视图模型属性,并使ItemContainerStyle多余。 ItemsPanelTemplate 只是<UniformGrid Columns="3"/>。也不需要您的SetCheckBoxItemRowsAndColumns方法。少了很多 XAML 和代码。所以我不同意 SharedSizeScope 是“正确的解决方案”。 -
在实际代码中(与此处的简化示例相反),复选框是分组的。每个组出现在一行中,或者如果复选框的数量多于网格中的列数,则换行到下一行。所以第一行可以有两个复选框,下一个是六个,依此类推。这是上面代码的一个相当简单的扩展,但我认为你不能使用 UniformGrid 来做到这一点。