Ответ 1
Если я правильно понял, вы хотите получить информацию об элементе, который был удален из списка привязки.
Я думаю, что самый простой способ сделать это - создать свой собственный список привязки, который происходит из списка привязки.
Внутри вы будете переопределять метод RemoveItem, поэтому, прежде чем удалять элемент из списка привязки, вы сможете запустить событие, содержащее элемент, который будет удален.
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;
}
Для примера я создал тип myInt, реализующий интерфейс INotifyPropertyChanged - просто обновить dataGridView после добавления/удаления элементов из списка привязки.
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;
}
Я инициализирую список привязки с ints (точнее, myInts), затем я привязываю список к dataGridView (для целей презентации) и подписываюсь на мое событие BeforeRemove.
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;
Если событие BeforeRemove было поднято, у меня есть элемент, который был удален
void bindingList_BeforeRemove(Form1.myInt deletedItem)
{
MessageBox.Show("You've just deleted item with value " + deletedItem.myIntProp.ToString());
}
Ниже приведен код всего примера (drop 3 buttons и dataGridView в форме) - кнопка 1 инициализирует список привязки, кнопка 2 добавляет элемент в список, кнопка 3 удаляет элемент из списка ставок
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;
}
}
}
СПИСОК ДЛЯ КОММЕНТАРИИ
"Другая часть вопроса = > Есть ли способ узнать старое значение элемента, который был изменен в списке? В ListChangedEvent ничего не говорится"
Чтобы увидеть старое значение элемента, вы можете переопределить метод SetItem
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);
}
Он запускается, когда объект с указанным индексом изменяется, например
bindingList[dataGridView1.SelectedRows[0].Index] = new myInt(new Random().Next());
Сложная часть, если вы попытаетесь напрямую изменить свойство элемента
bindingList[dataGridView1.SelectedRows[0].Index].myIntProp = new Random().Next();
SetItem не запускает, он должен быть заменен всем объектом.
Поэтому нам понадобится другой делегат и событие для обработки этого
public delegate void myIntDelegateChanged(myInt oldItem, myInt newItem);
public event myIntDelegateChanged myIntOldNew;
Тогда мы можем подписаться на этот
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());
}
Обновленный код (требуется 4 кнопки, 4-й изменяет выбранный элемент)
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());
}
}
}