我有一个简单的数据网格,它具有自动生成的列并绑定到项目源。此项目源会定期更新,我找不到如何为单个单元格更改触发事件。我想根据对数据源的更新是否更改了单元格的先前值来更改单元格的颜色。
当绑定值更改时,我查看了 WPF DataGrid 中的突出显示单元格以及http://codefornothing.wordpress.com/2009/01/25/the-wpf-datagrid-and-me/但我仍然不确定如何着手实施这一点。一些示例代码对于开始正确的道路非常有帮助。
我有一个简单的数据网格,它具有自动生成的列并绑定到项目源。此项目源会定期更新,我找不到如何为单个单元格更改触发事件。我想根据对数据源的更新是否更改了单元格的先前值来更改单元格的颜色。
当绑定值更改时,我查看了 WPF DataGrid 中的突出显示单元格以及http://codefornothing.wordpress.com/2009/01/25/the-wpf-datagrid-and-me/但我仍然不确定如何着手实施这一点。一些示例代码对于开始正确的道路非常有帮助。
如果您要绑定到 DataTable,我认为这不会是一条有效的路径。在 WPF 中几乎不可能基于 DataTable 绑定的 DataGrid 的内容进行任何类型的样式设置。关于 StackOverflow 有几个建议,但它们通常非常老套、事件驱动(这在 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));
}
}
}