Windows Phone:在数据绑定项控件中动态添加列

时间:2013-10-13 18:18:32

标签: c# xaml windows-phone-7 windows-phone-8 windows-phone

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

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

1 个答案:

答案 0 :(得分:0)

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

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

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