0

我正在尝试布局一个网格,以便它可以具有动态数量的列,并且每个数据绑定控件都会自动添加到正确的列(基于其在数据上下文中的索引)。

考虑一下保龄球框架,虽然通常总是有 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 等效布局。

4

1 回答 1

0

我在这里找到了 WPF 的等效演示UniformGrid

http://www.jeff.wilcox.name/2009/01/uniform-grid/

切换到那个之后,它确实按预期工作!现在不需要使用任何自定义代码。

于 2013-10-13T18:42:03.700 回答