简体   繁体   English

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

[英]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. 我有一个Cell类,具有一个名为Color的属性,并且制作了一个Cell对象列表列表,打算将其用作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. 统一网格中的单元格应根据对象的Color属性更改颜色,但是,无论我如何编写xaml代码,它都不会改变。 I also tried putting the cells in ObservableCollections but it doesn't work, it just shows up as GameOfLife.Cell in the Window. 我还尝试将单元格放置在ObservableCollections中,但是它不起作用,它只是在窗口中显示为GameOfLife.Cell。

I have this xaml code: 我有这个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>

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. 单元格的隐式状态为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,将具有UniformGrid作为其ItemsPanel的单个ItemsControl(例如,使用Border或Grid可视化单元格)会更简单:

<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. 请注意,Cell类实现INotifyPropertyChanged接口以通知其属性更改。 Unless you want to change the grid size dynamically, you don't need to use an ObservableCollection of Cell object. 除非要动态更改网格大小,否则不需要使用Cell对象的ObservableCollection。 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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