绑定到ItemSource时,WPF Autogenerated DataGrid Cell更改了事件

时间:2013-08-14 05:43:29

标签: wpf datagrid

我有一个简单的数据网格,它有自动生成的列并绑定到项目源。此项目源在某些时间间隔更新,我找不到如何为单个单元格更改触发事件。我想根据数据源的更新是否更改了单元格的先前值来更改单元格的颜色。

我查看了Highlighting cells in WPF DataGrid when the bound value changes以及http://codefornothing.wordpress.com/2009/01/25/the-wpf-datagrid-and-me/,但我仍然不确定如何实施此功能。一些示例代码对于开始正确的路径非常有帮助。

1 个答案:

答案 0 :(得分:1)

如果您绑定到DataTable,我认为这不是一条富有成效的道路。在WPF中,基于DataTable绑定DataGrid的内容进行任何类型的样式几乎是不可能的。关于StackOverflow有几个建议,但它们通常非常hacky,事件驱动(这通常是WPF中的坏消息),以及维护噩梦。

但是,如果你绑定的ItemsSource是一个ObservableCollection,其中RowViewModel是表示DataGrid单行中数据的类,那么它应该不会太糟糕。确保RowViewModel实现了INotifyPropertyChanged,并简单地使用更新的数据更新各个RowViewModel。然后,您可以添加逻辑以在RowViewModel上显示另一个属性,该属性指示特定值是否为新 - 只需在XAML中使用某些样式/触发器即可根据此新属性的值设置背景颜色。

以下是后者的示例:如果您在第一列中编辑其中一个值,则会将单元格变为红色。如果您通过数据库更新以编程方式更改ItemViewModel中的值,则会发生同样的事情。

XAML:

<Window x:Class="ShowGridUpdates.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Item1, UpdateSourceTrigger=PropertyChanged}">
                <DataGridTextColumn.CellStyle>
                    <Style TargetType="DataGridCell">
                        <Style.Setters>
                            <Setter Property="Background" Value="Blue"/>
                            <Setter Property="Foreground" Value="White"/>
                        </Style.Setters>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Item1Changed}" Value="True">
                                <Setter Property="Background" Value="Red"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </DataGridTextColumn.CellStyle>
            </DataGridTextColumn>
            <DataGridTextColumn Binding="{Binding Item2}"/>
        </DataGrid.Columns>
    </DataGrid>   
</Grid>

守则背后:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new ViewModel();
    }
}

public class ViewModel : PropertyChangedNotifier
{
    public ViewModel()
    {
        Items = new ObservableCollection<ItemViewModel>()
        {
            new ItemViewModel(){Item1="Item1FistValue", Item2="Item2FirstValue"},
            new ItemViewModel(){Item1="whocareswhatvalue", Item2="Icertainlydont"}
        };

        //just to get the initial state correct
        foreach (var item in Items)
        {
            item.Item1Changed = false;
        }
    }

    private ObservableCollection<ItemViewModel> _items;

    public ObservableCollection<ItemViewModel> Items
    {
        get
        {
            return _items;
        }
        set
        {
            _items = value;
            OnPropertyChanged("Items");
        }
    }
}

public class ItemViewModel : PropertyChangedNotifier
{
    private string _item1;
    private string _item2;

    private bool _item1Changed;

    public bool Item1Changed
    {
        get
        {
            return _item1Changed;
        }
        set
        {
            _item1Changed = value;
            OnPropertyChanged("Item1Changed");
        }
    }

    public string Item1
    {
        get
        {
            return _item1;
        }
        set
        {
            if (_item1 != value)
                Item1Changed = true;
            else
                Item1Changed = false;

            _item1 = value;
            OnPropertyChanged("Item1");
        }
    }

    public string Item2
    {
        get
        {
            return _item2;
        }
        set
        {
            _item2 = value;
            OnPropertyChanged("Item2");
        }
    }
}

public class PropertyChangedNotifier : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}