WPF DataGrid值發生改變時改變背景顏色

Posted by Leo Yang on 2020-07-02

透過Style,當DataGrid值異動時改變背景顏色提醒使用者

XAML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<Style TargetType="DataGridCell" x:Key="Cell">
<Setter Property="Foreground" Value="Black"/>
<Style.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color"From="OrangeRed" To="Transparent" Duration="0:0:1.5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>

<DataGrid ItemsSource="{Binding DataSource}" Grid.Row="1" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding ID,NotifyOnTargetUpdated=True}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name,NotifyOnTargetUpdated=True}"/>
<DataGridTextColumn Header="Price" Binding="{Binding Price,NotifyOnTargetUpdated=True}" CellStyle="{StaticResource Cell}"/>
</DataGrid.Columns>
</DataGrid>

ViewModel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// DataSource
private List<DataModel.Data> _DataCollection = new List<DataModel.Data>();
public List<DataModel.Data> DataCollection
{
get
{
return _DataCollection;
}
set
{
_DataCollection = value;
OnPropertyChanged();
}
}

DataModel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class Data:INotifyPropertyChanged
{

private int _Price;
private int _Qty;
private int _ID;

public int Price
{
get
{
return _Price;
}
set
{
_Price = value;
OnPropertyChanged();
}
}

public int Qty
{
get
{
return _Qty;
}
set
{
_Qty = value;
OnPropertyChanged();
}
}

public int ID
{
get
{
return _ID;
}
set
{
_ID = value;
OnPropertyChanged();
}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

為什麼ObservableCollection會更新訂閱的介面,但是都沒有觸發界面更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14

ObservableCollection<T>在集合發生異動的時候資料會自動更新訂閱的介面,但是只有在"集合"更新時,集合新增或移除資料的時候才會更新介面
ex:
//Adding data and triggering UI updates
main.ObservableDataCollection.Add(new DataModel.CommonData() { ID = 11, Price = 20, Qty = 30 });

//Remove data and trigger a UI update
main.ObservableDataCollection.RemoveAt(0);

//****ObservableCollection did not trigger a UI updat****//
//Modified data but did not trigger a UI update
main.ObservableDataCollection[0].Qty = 9999;

所以上面例子裡的DataModel有繼承INotifyPropertyChanged Interface,讓訂閱ObservableCollection<T>資料集的介面,在資料集合中的"資料"異動時通知訂閱的界面更新

List<T>、ObservableCollection<T>差異

1
2
3
4
5
6
7
8
ObservableCollection<T>
在新增、移除資料到資料集合中時會發出通知,通知有訂閱的介面更新,但是異動集合中的資料不會發出通知

List<T>
除非List中的資料有通知的機制,不然新增、修改、刪除都不會發出通知
所以就算List中的資料有繼承了通知機制,List<T>也只有在資料異動的時候會更新介面,但是資料集新增、刪除資料介面還是不會更新

最好的解法就是先定義一個繼承INotifyPropertyChanged介面的類別,然後讓ObservableCollection泛型,這樣資料不論在新增、修改、刪除時都會觸發通知機制讓介面更新