简体   繁体   中英

How do I bind the properties of an object to a WPF control?

I have a Cell class, with a property called Color, and I make a List of Lists of Cell objects that I plan to use as the binding source for a UniformGrid. The cells in the uniform grid should change color based on the object's Color property, however, no matter how I write the xaml code it doesn't change. I also tried putting the cells in ObservableCollections but it doesn't work, it just shows up as GameOfLife.Cell in the Window.

I have this xaml code:

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

And this is how I tried to bind the cell objects:

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

The implicit state of a cell is State.Dead.

What I want to know is why it doesn't work and how to make it work.

Instead of nested ItemsControls it would be simpler to have a single ItemsControl with a UniformGrid as its ItemsPanel, and eg a Border or a Grid to visualize the cell:

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

The view model could look like shown below. Note that the Cell class implements the INotifyPropertyChanged interface to notify about changes of its properties. Unless you want to change the grid size dynamically, you don't need to use an ObservableCollection of Cell object. A plain List is sufficient.

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>();
}

and initialized like this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM