如何将整数列表数据绑定到网格列定义

本文关键字:网格 定义 数据绑定 列表 整数 | 更新日期: 2023-09-27 18:37:20

我有一组整数:

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>

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

如何将整数列表数据绑定到网格列定义

您可以尝试如下操作:

    <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>

我正在使用一个内部带有TextBlockBorder,但如果您愿意,您可以用其他东西替换它。 重要的是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 仅包含 <UserControl> 元素内的<Grid x:Name="grid" />

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

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