如何将对象的属性绑定到WPF控件?

时间:2019-03-17 11:50:14

标签: c# wpf

我有一个Cell类,具有一个名为Color的属性,并且制作了一个Cell对象列表列表,打算将其用作UniformGrid的绑定源。统一网格中的单元格应根据对象的Color属性更改颜色,但是,无论我如何编写xaml代码,它都不会改变。我还尝试将这些单元格放置在ObservableCollections中,但是它不起作用,它只是在窗口中显示为GameOfLife.Cell。

我有这个xaml代码:

<DataTemplate x:Key="Line">
        <ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource CellTemplate}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </DataTemplate>

    <DataTemplate x:Key="CellTemplate">
        <DataGridCell Content="{Binding}" Background="{Binding Color}"></DataGridCell>
    </DataTemplate>

</Window.Resources>
<UniformGrid Background="Red">
    <ItemsControl x:Name="Cells" ItemTemplate="{DynamicResource Line}"/>
</UniformGrid>

这是我尝试绑定单元格对象的方式:

public MainWindow()
        {
            InitializeComponent();
            ObservableCollection<ObservableCollection<Cell>> cells = new ObservableCollection<ObservableCollection<Cell>>();

            cells.Add(new ObservableCollection<Cell> { new Cell(State.Alive), new Cell(), new Cell(State.Alive) });
            cells.Add(new ObservableCollection<Cell> { new Cell(State.Alive), new Cell(), new Cell() });
            cells.Add(new ObservableCollection<Cell> { new Cell(), new Cell(State.Alive), new Cell() });

            Cells.ItemsSource = cells;
        }

单元格的隐式状态为State.Dead。

我想知道的是为什么它不起作用以及如何使其起作用。

1 个答案:

答案 0 :(得分:2)

拥有一个带有UniformGrid作为其ItemsPanel的单个ItemsControl,而不是嵌套的ItemsControl,会更加简单。边框或网格以可视化单元格:

<ItemsControl ItemsSource="{Binding Cells}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="10"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border>
                <Border.Background>
                    <SolidColorBrush Color="{Binding Color}"/>
                </Border.Background>
                <!-- optional child element here -->
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

视图模型如下所示。请注意,Cell类实现INotifyPropertyChanged接口以通知其属性更改。除非要动态更改网格大小,否则不需要使用Cell对象的ObservableCollection。一个简单的列表就足够了。

public enum CellState
{
    Dead, Active
}

public class Cell : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private CellState state;
    public CellState State
    {
        get { return state; }
        set
        {
            state = value;
            NotifyPropertyChanged("State");
            NotifyPropertyChanged("Color");
        }
    }

    public Color Color
    {
        get { return state == CellState.Dead ? Colors.Red : Colors.Green; }
    }
}

public class ViewModel
{
    public List<Cell> Cells { get; } = new List<Cell>();
}

并这样初始化:

public MainWindow()
{
    InitializeComponent();

    var vm = new ViewModel();

    for (int i = 0; i < 100; i++)
    {
        vm.Cells.Add(new Cell { State = i % 3 == 0 ? CellState.Dead : CellState.Active });
    }

    DataContext = vm;
}