I am using Binding List in my application along with ItemChanged event.
Is there any way I could know the previous values of properties in ItemChanged event. Currently I am adding a separate property named 'OldValue' to achieve this.
Is there any way to know about the deleted item in item changed event. I am not able to find any way to know which item has been deleted from the list.
If I understand correctly, you want to get info about the item which was deleted from the binding list.
I think the easiest way to do this will be creating your own binding list which derives from binding list.
Inside you'll have RemoveItem method overridden, so BEFORE removing an item from the binding list, you'll be able to fire event containing item which is going to be removed.
public class myBindingList<myInt> : BindingList<myInt> { protected override void RemoveItem(int itemIndex) { //itemIndex = index of item which is going to be removed //get item from binding list at itemIndex position myInt deletedItem = this.Items[itemIndex]; if (BeforeRemove != null) { //raise event containing item which is going to be removed BeforeRemove(deletedItem); } //remove item from list base.RemoveItem(itemIndex); } public delegate void myIntDelegate(myInt deletedItem); public event myIntDelegate BeforeRemove; }
For the sake of example, I created type myInt implementing INotifyPropertyChanged - interface is just to make dataGridView refresh after adding/deleting elements from a binding list.
public class myInt : INotifyPropertyChanged { public myInt(int myIntVal) { myIntProp = myIntVal; } private int iMyInt; public int myIntProp { get { return iMyInt; } set { iMyInt = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("myIntProp")); } } } public event PropertyChangedEventHandler PropertyChanged; }
I'm initializing binding list with ints (myInts to be precise), then I'm binding list to dataGridView (for presentation purpose) and subscribing to my BeforeRemove event.
bindingList = new myBindingList<myInt>(); bindingList.Add(new myInt(8)); bindingList.Add(new myInt(9)); bindingList.Add(new myInt(11)); bindingList.Add(new myInt(12)); dataGridView1.DataSource = bindingList; bindingList.BeforeRemove += bindingList_BeforeRemove;
If BeforeRemove event was raised I have item which was deleted
void bindingList_BeforeRemove(Form1.myInt deletedItem) { MessageBox.Show("You've just deleted item with value " + deletedItem.myIntProp.ToString()); }
Below is whole example code (drop 3 buttons and dataGridView on form) - button 1 initializes binding list, button 2 adds item to list, button 3 removes item from biding list
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace bindinglist { public partial class Form1 : Form { myBindingList<myInt> bindingList; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { bindingList = new myBindingList<myInt>(); bindingList.Add(new myInt(8)); bindingList.Add(new myInt(9)); bindingList.Add(new myInt(11)); bindingList.Add(new myInt(12)); dataGridView1.DataSource = bindingList; bindingList.BeforeRemove += bindingList_BeforeRemove; } void bindingList_BeforeRemove(Form1.myInt deletedItem) { MessageBox.Show("You've just deleted item with value " + deletedItem.myIntProp.ToString()); } private void button2_Click(object sender, EventArgs e) { bindingList.Add(new myInt(13)); } private void button3_Click(object sender, EventArgs e) { bindingList.RemoveAt(dataGridView1.SelectedRows[0].Index); } public class myInt : INotifyPropertyChanged { public myInt(int myIntVal) { myIntProp = myIntVal; } private int iMyInt; public int myIntProp { get { return iMyInt; } set { iMyInt = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("myIntProp")); } } } public event PropertyChangedEventHandler PropertyChanged; } public class myBindingList<myInt> : BindingList<myInt> { protected override void RemoveItem(int itemIndex) { myInt deletedItem = this.Items[itemIndex]; if (BeforeRemove != null) { BeforeRemove(deletedItem); } base.RemoveItem(itemIndex); } public delegate void myIntDelegate(myInt deletedItem); public event myIntDelegate BeforeRemove; } } }
ANSWER TO COMMENT
"The other part of the question is => Is there any way to know the old value of the item which is changed in the list? In ListChangedEvent does not share anything"
To see the old value of the item you can override the SetItem method
protected override void SetItem(int index, myInt item) { //here we still have old value at index myInt oldMyInt = this.Items[index]; //new value myInt newMyInt = item; if (myIntOldNew != null) { //raise event myIntOldNew(oldMyInt, newMyInt); } //update item at index position base.SetItem(index, item); }
It fires when an object at the specified index is changed, like this
bindingList[dataGridView1.SelectedRows[0].Index] = new myInt(new Random().Next());
The tricky part is, if you try to modify item's property directly
bindingList[dataGridView1.SelectedRows[0].Index].myIntProp = new Random().Next();
SetItem won't fire, it has to be a whole object replaced.
So we will need another delegate & event to handle this
public delegate void myIntDelegateChanged(myInt oldItem, myInt newItem); public event myIntDelegateChanged myIntOldNew;
Then we can subscribe to this
bindingList.myIntOldNew += bindingList_myIntOldNew;
and handle it
void bindingList_myIntOldNew(Form1.myInt oldItem, Form1.myInt newItem) { MessageBox.Show("You've just CHANGED item with value " + oldItem.myIntProp.ToString() + " to " + newItem.myIntProp.ToString()); }
Updated code (4 buttons required, 4th modifies selected item)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace bindinglist { public partial class Form1 : Form { myBindingList<myInt> bindingList; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { bindingList = new myBindingList<myInt>(); bindingList.Add(new myInt(8)); bindingList.Add(new myInt(9)); bindingList.Add(new myInt(11)); bindingList.Add(new myInt(12)); dataGridView1.DataSource = bindingList; bindingList.BeforeRemove += bindingList_BeforeRemove; bindingList.myIntOldNew += bindingList_myIntOldNew; } void bindingList_myIntOldNew(Form1.myInt oldItem, Form1.myInt newItem) { MessageBox.Show("You've just CHANGED item with value " + oldItem.myIntProp.ToString() + " to " + newItem.myIntProp.ToString()); } void bindingList_BeforeRemove(Form1.myInt deletedItem) { MessageBox.Show("You've just deleted item with value " + deletedItem.myIntProp.ToString()); } private void button2_Click(object sender, EventArgs e) { bindingList.Add(new myInt(13)); } private void button3_Click(object sender, EventArgs e) { bindingList.RemoveAt(dataGridView1.SelectedRows[0].Index); } public class myInt : INotifyPropertyChanged { public myInt(int myIntVal) { myIntProp = myIntVal; } private int iMyInt; public int myIntProp { get { return iMyInt; } set { iMyInt = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("myIntProp")); } } } public event PropertyChangedEventHandler PropertyChanged; } public class myBindingList<myInt> : BindingList<myInt> { protected override void SetItem(int index, myInt item) { myInt oldMyInt = this.Items[index]; myInt newMyInt = item; if (myIntOldNew != null) { myIntOldNew(oldMyInt, newMyInt); } base.SetItem(index, item); } protected override void RemoveItem(int itemIndex) { myInt deletedItem = this.Items[itemIndex]; if (BeforeRemove != null) { BeforeRemove(deletedItem); } base.RemoveItem(itemIndex); } public delegate void myIntDelegateChanged(myInt oldItem, myInt newItem); public event myIntDelegateChanged myIntOldNew; public delegate void myIntDelegate(myInt deletedItem); public event myIntDelegate BeforeRemove; } private void button4_Click(object sender, EventArgs e) { bindingList[dataGridView1.SelectedRows[0].Index] = new myInt(new Random().Next()); } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With