Reputation: 71
There is a observable collection in my class and I want to be notified when the observable collection changes.
I searched on stackoverflow and found this code
private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (var item in e.OldItems)
{
//Removed items
}
}
else if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (var item in e.NewItems)
{
//Added items
}
}
else if(e.Action == NotifyCollectionChangedAction.Replace){
foreach (var item in e.NewItems)
{
}
}
}
Every thing was working fine. I get notified when something created and deleted. but I didnt get notified when an instance edited. what did I do wrong?
Edit: I changed the observable collection to binding list but nothing is happeng when I edit something.
<ListView Grid.Row="1" ItemsSource="{Binding Contacts}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text={Binding Name}></TextBox>
<TextBox Text={Binding Email}><TextBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
And my viewModel:
private BindingList<ContactViewModel> _contacts;
public IEnumerable<ContactViewModel> Contacts=>_contacts;
public ContactListing()
{
_contacts.ListChanged +=_contacts_ListChanged;
}
private void _contacts_ListChanged(object sender, ListChangedEventArgs e)
{
//Get Notified When somthing is edited
}
in the xaml I have some texboxes that when the text of them changes, The binding list or observable collection also changes(I set a breakpoint and the list was changing everytime something edited) but the ListChanged event doesnot call.
Upvotes: 0
Views: 114
Reputation: 7918
The collection element must implement INotifyPropertyChanged
. And the collection needs to be replaced with BindingList< T>. Then in the ListChanged event you will receive a notification about the change in the properties of the elements of the collection. You will also have access to the AddingNew event, which occurs BEFORE an element is added to the collection.
It is also not working for editing. Its onliy working for creating and deleting.
Here is an example showing that it works when adding elements, and when changing any property of an element.
using Simplified;
namespace Core2023.SO.Eboy
{
public class ItemInpc : BaseInpc
{
private int _value;
private string title = string.Empty;
public int Id { get; }
public string Title { get => title; set => Set(ref title, value ?? string.Empty); }
public int Value { get => _value; set => Set(ref _value, value); }
public override string? ToString()
=> $"{Id}: {Title}-{Value}";
public ItemInpc(int id)
{
Id = id;
}
public ItemInpc() : this(-1) { }
}
}
using Simplified;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace Core2023.SO.Eboy
{
public class ItemsViewModel : BaseInpc
{
private string _listChangedArgs = string.Empty;
public BindingList<ItemInpc> Items { get; }
public ItemsViewModel()
{
Items = new BindingList<ItemInpc>(
"And the collection needs to be replaced"
.Split()
.Select((title, id) => new ItemInpc(id) { Title = title, Value = id * 23 })
.ToList());
Items.AddingNew += OnAddingNew;
Items.ListChanged += OnListChanged;
}
public string ListChangedArgs { get => _listChangedArgs; set => Set(ref _listChangedArgs, value); }
private void OnAddingNew(object? sender, AddingNewEventArgs e)
{
int id = Items.Max(it => it.Id) + 1;
ItemInpc item = new ItemInpc(id);
e.NewObject = item;
}
int i = 0;
private void OnListChanged(object? sender, ListChangedEventArgs e)
{
StringBuilder builder = new StringBuilder();
builder.Append(i);
i++;
builder.AppendLine(new string('-', 40));
builder.AppendLine(e.ListChangedType.ToString());
builder.AppendLine(e.PropertyDescriptor?.Name);
builder.AppendLine(e.NewIndex.ToString());
if (e.NewIndex < 0)
builder.AppendLine($"{e.NewIndex}");
else
builder.AppendLine($"{e.NewIndex} {Items[e.NewIndex]}");
if (e.OldIndex < 0)
builder.AppendLine($"{e.OldIndex}");
else
builder.AppendLine($"{e.OldIndex} {Items[e.OldIndex]}");
builder.AppendLine(ListChangedArgs);
ListChangedArgs = builder.ToString();
}
}
}
<Window x:Class="Core2023.SO.Eboy.ItemChangedWindow"
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:Core2023.SO.Eboy"
mc:Ignorable="d"
Title="ItemChangedWindow" Height="450" Width="800">
<Window.DataContext>
<local:ItemsViewModel/>
</Window.DataContext>
<UniformGrid Columns="2">
<DataGrid ItemsSource="{Binding Items}"/>
<TextBlock Text="{Binding ListChangedArgs}"/>
</UniformGrid>
</Window>
BaseInpc class from here: https://stackoverflow.com/a/67617794/13349759 .
Upvotes: 2