我正在尝试布局一个网格,以便它可以具有动态数量的列,并且每个数据绑定控件都会自动添加到正确的列(基于其在数据上下文中的索引)。
考虑一下保龄球框架,虽然通常总是有 10 个,但我不想在 XAML 中定义 10 列并单独添加每个框架。我正在尝试以编程方式进行。
这是我的 XAML:
<ItemsControl x:Name="BowlingPlayers" ItemsSource="{Binding Game.Players}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,0,20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}"/>
<ScrollViewer HorizontalScrollBarVisibility="Visible" Grid.Column="1">
<ItemsControl ItemsSource="{Binding Frames}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid Loaded="BowlingGrid_OnLoaded">
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Height="64" BorderBrush="White" BorderThickness="1" Loaded="BowlingFrame_OnLoaded">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Ball1}"/>
<Border Grid.Column="1" BorderBrush="White" BorderThickness="1,0,0,1">
<TextBlock Text="{Binding Ball2}"/>
</Border>
<TextBlock Grid.ColumnSpan="2" Grid.Row="1" Text="{Binding Score}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
然后在代码隐藏中:
private void BowlingGrid_OnLoaded(object sender, RoutedEventArgs e) {
var grid = (Grid)sender;
if (grid.ColumnDefinitions.Any()) return;
var player = grid.DataContext as BowlingPlayer;
if (player != null) {
// Add columns for each frame
foreach (var frame in player.Frames) {
grid.ColumnDefinitions.Add(new ColumnDefinition() {Width = new GridLength(1, GridUnitType.Star)});
}
}
}
private void BowlingFrame_OnLoaded(object sender, RoutedEventArgs e) {
var border = (Border) sender;
var frame = border.DataContext as BowlingFrame;
var presenter = VisualTreeHelper.GetParent(border);
var grid = VisualTreeHelper.GetParent(presenter) as Grid;
if (grid != null) {
var player = grid.DataContext as BowlingPlayer;
if (player != null) {
var frameIndex = player.Frames.IndexOf(frame);
Grid.SetColumn(border, frameIndex + 1);
}
}
}
这是“某种”工作,似乎所有框架都被放入第一列,而不是它们各自的列索引。
在 XAML 中没有硬编码宽度的情况下是否有另一种方法来布局?如果我使用水平 StackPanel 并为每个框架(边框)提供明确的宽度和高度,它会起作用,但我希望它可以缩放到可用宽度。
基本上,一个 CSS3 flexbox 等效布局。