如何将整数列表数据绑定到Grid ColumnDefinitions

时间:2012-06-16 11:26:25

标签: c# silverlight windows-phone-7 data-binding

我有一组整数:

public ObservableCollection<int> Scores = new ObservableCollection<int> {
    10, 30, 50
};

我希望在绑定时产生类似于以下XAML的内容:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="10"/>
        <ColumnDefinition Width="30"/>
        <ColumnDefinition Width="50"/>
    </Grid.ColumnDefinitions>

    <TextBlock Grid.Column="0">10</TextBlock>
    <TextBlock Grid.Column="1">30</TextBlock>
    <TextBlock Grid.Column="2">50</TextBlock>
</Grid>

如何编写数据绑定来执行此操作?

1 个答案:

答案 0 :(得分:0)

您可以尝试以下内容:

    <ItemsControl ItemsSource="{Binding Path=Scores}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Border BorderBrush="Black" BorderThickness="1"
                        Background="Yellow" Width="{Binding}">
                    <TextBlock Text="{Binding}" />
                </Border>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

我正在使用Border,其中包含TextBlock,但如果您愿意,可以将其替换为其他内容。重要的是Width绑定。

另请注意,Scores必须是属性。在上面的代码中,您创建了一个公共字段,但绑定仅适用于属性,而不适用于字段。

编辑:如果您想使用Grid,可以尝试使用以下用户控件。此用户控件具有网格宽度的依赖项属性,并在每次集合更改时重新创建网格。

using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;

namespace YourNamespace
{
    public partial class BindableGrid : UserControl
    {
        public static readonly DependencyProperty WidthsProperty =
            DependencyProperty.Register("Widths",
                                        typeof(ObservableCollection<int>),
                                        typeof(BindableGrid),
                                        new PropertyMetadata(Widths_Changed));

        public BindableGrid()
        {
            InitializeComponent();
        }

        public ObservableCollection<int> Widths
        {
            get { return (ObservableCollection<int>)GetValue(WidthsProperty); }
            set { SetValue(WidthsProperty, value); }
        }

        private static void Widths_Changed(DependencyObject obj,
                                           DependencyPropertyChangedEventArgs e)
        {
            var grid = obj as BindableGrid;
            if (grid != null)
            {
                grid.OnWidthsChanged(e.OldValue as ObservableCollection<int>);
            }
        }

        private void OnWidthsChanged(ObservableCollection<int> oldValue)
        {
            if (oldValue != null)
            {
                oldValue.CollectionChanged -= Widths_CollectionChanged;
            }

            if (Widths != null)
            {
                Widths.CollectionChanged += Widths_CollectionChanged;
            }

            RecreateGrid();
        }

        private void Widths_CollectionChanged(object sender,
                                              NotifyCollectionChangedEventArgs e)
        {
            // We'll just clear and recreate the entire grid each time
            // the collection changes.
            // Alternatively, you could use e.Action to determine what the
            // actual change was and apply that (e.g. add or delete a
            // single column definition). 
            RecreateGrid();
        }

        private void RecreateGrid()
        {
            // Recreate the column definitions.
            grid.ColumnDefinitions.Clear();
            foreach (int width in Widths)
            {
                // Use new GridLength(1, GridUnitType.Star) for a "*" column.
                var coldef = new ColumnDefinition() { Width = new GridLength(width) };
                grid.ColumnDefinitions.Add(coldef);
            }

            // Now recreate the content of the grid.
            grid.Children.Clear();
            for (int i = 0; i < Widths.Count; ++i)
            {
                int width = Widths[i];
                var textblock = new TextBlock() { Text = width.ToString() };
                Grid.SetColumn(textblock, i);
                grid.Children.Add(textblock);
            }
        }
    }
}

UserControl的XAML仅在<Grid x:Name="grid" />元素中包含<UserControl>

然后,您可以在XAML中使用它,假设您已将somePrefix绑定到命名空间YourNamespace

    <somePrefix:BindableGrid Widths="{Binding Path=Scores}" />