Reputation: 1953
I have DataGrid with form and I would like to notify another get property. Here is my example:
ViewModel
public ObservableCollection<Data> Data
{
get => _data;
set {
_data = value;
OnPropertyChanged(nameof(Data));
}
}
public int Summary => Data.Sum(data => data.Number);
XAML
<DataGrid ItemsSource="{Binding Data}">
...
<TextBox Title="{Binding Number, UpdateSourceTrigger=PropertyChanged"/>
...
</DataGrid>
<StackPanel>
<Label Content="Summary: "/>
<TextBlock Text="{Binding Summary}"/>
</StackPanel>
When I write number to datagrid, Summary is still 0. How to notify Summary property, when I change value in collection? Thanks
Upvotes: 0
Views: 1823
Reputation: 1671
Perhaps it is easier to use a BindingList
. It has an event ListChanged
that is raised if
PropertyChanged
eventIt will give you information what kind of change was detected (ListChangedType
) and where in the list the change happend (NewIndex
and OldIndex
). This solution implies, that your Data
class also implements INotifyPropertyChanged
This would imply the following changes in your viewmodel
// if you do not change the list object, there is no need to raise PropertyChanged in setter
public BindingList<Data> Data { get; set; } = new BindingList<Data>();
// constructor
public ViewModel(){
// Update property Summary if our list changes.
List.ListChanged += (sender, arg) => OnPropertyChanged(nameof(Summary));
}
Upvotes: 1
Reputation: 1937
Check this: https://www.codeproject.com/Tips/694370/How-to-Listen-to-Property-Chang
What you need is a notification whenever any item changes in the Collection.
Update:
Say Data that will appear in the Grid is:
public class Data
{
public string Name { get; set; }
private int _Salary;
public int Salary
{
get
{
return _Salary;
}
set
{
_Salary = value;
SalaryChanged?.Invoke();
}
}
public Action SalaryChanged { get; set; }
}
Instead of ObservableCollection - use this:
public class ObsCollection : ObservableCollection<Data>
{
private Action SalaryChanged;
public ObsCollection(Action NotifyPropertyChanged)
{
SalaryChanged = NotifyPropertyChanged;
}
protected override void InsertItem(int index, Data item)
{
item.SalaryChanged = SalaryChanged;
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
base.RemoveItem(index);
SalaryChanged?.Invoke();
}
protected override void ClearItems()
{
base.ClearItems();
SalaryChanged?.Invoke();
}
}
Finally - In the View Model
public class MainWindowVM : INotifyPropertyChanged
{
private ObsCollection _Data = null;
public ObsCollection Data
{
get
{
return _Data;
}
set
{
_Data = value;
}
}
public int TotalSalary
{
get
{
return _Data.Sum(d => d.Salary);
}
}
public MainWindowVM()
{
_Data = new ObsCollection(NotifyTotalSalaryChanged);
LoadData();
}
public void LoadData()
{
_Data.Add(new Data { Name = "Test1", Salary = 1000 });
_Data.Add(new Data { Name = "Test2", Salary = 2000 });
_Data.Add(new Data { Name = "Test3", Salary = 3000 });
Notify("Data");
}
private void NotifyTotalSalaryChanged()
{
Notify("TotalSalary");
}
#region Property Changed Stuff
public event PropertyChangedEventHandler PropertyChanged;
public void Notify(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
============================================= Xaml is merely:
<Window x:Class="CstomObserve.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CstomObserve"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainWindowVM/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid Grid.Row="0" ItemsSource="{Binding Data, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Grid.Row="1" Text="{Binding TotalSalary, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Window>
Upvotes: 2