Чтобы привязка данных в WinForms (например, к DataGridView) работала так, как вы надеетесь, и добавляла / удаляла строки по мере изменения коллекции, вы должны использовать BindingList (или DataTable) вместо Список c. Проблема в том, что почти никто не имеет первого инстинкта для кодирования с BindingList вместо List в своих библиотеках.
BindingList реализует два события, которых нет в List, и это должно быть различием в привязке данных действие (также свойство для подавления второго события):
AddingNew
ListChanged
RaiseListChangedEvents
Аналогично, в DataTable есть два события, которые, вероятно, включают аналогичную функциональность:
RowDeleted
TableNewRow
EDIT : Как указало полезное SO-сообщество здесь и в другой статье , список можно преобразовать (может быть, более точно инкапсулировать?), Вызвав правильный конструктор BindingList:
BindingList<MyType> MyBL = new BindingList<MyType>();
MyList.ForEach(x => MyBL.Add(x));
My Ситуация немного сложнее, как показано в коде ниже. РЕДАКТИРОВАТЬ Добавлен материал INotifyPropertyChanged, который должен существовать в реальной библиотеке.
public class RealString : INotifyPropertyChanged
{
private int _KnotCount = 0;
private List<KnotSpace> _KnotSpacings = new List<KnotSpace>();
public RealString()
{
KnotSpacings.Add(new KnotSpace());
}
public int KnotCount
{
get { return _KnotCount; }
set
{
int requiredSpacings = 0;
_KnotCount = value;
// Always one more space than knots
requiredSpacings = _KnotCount + 1;
if (requiredSpacings < KnotSpacings.Count)
{
while (requiredSpacings < KnotSpacings.Count)
{
KnotSpacings.Add(new KnotSpace());
}
}
else if (requiredSpacings > KnotSpacings.Count)
{
while (requiredSpacings > KnotSpacings.Count)
{
KnotSpacings.Remove(KnotSpacings.Last());
}
}
this.OnPropertyChanged(this, "KnotCount");
}
}
public List<KnotSpace> KnotSpacings { get => _KnotSpacings; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(object sender, string PropertyName)
{
if (this.PropertyChanged == null) return;
this.PropertyChanged(sender, new PropertyChangedEventArgs(PropertyName));
}
}
public class KnotSpace
{
private double _Spacing = 10;
public double Spacing { get => _Spacing; set => _Spacing = value; }
}
Элементы в списке отображаются в пользовательском интерфейсе, а свойства элементов в списке изменяются в пользовательский интерфейс, но пользовательский интерфейс не добавляет / удаляет вещи напрямую из списка, за исключением изменения свойства KnotCount. Обтекание свойства KnotSpacings в BindingList не приводит к обновлению BindingList при обновлении KnotSpacings путем изменения свойства KnotCount.
EDIT ОК, дополнительные пояснения ...
BindingList BL = new BindingList<KnotSpace>(MyRealString.KnotSpacings);
DataGridView1.AutoGenerateColumns = true;
DataGridView1.DataSource = BL;
NumericUpDown1.DataBindings.Add("Value", MyRealString, "KnotCount", false, DataSourceUpdateMode.OnPropertyChanged);
BindingList не более успешно отслеживает изменения в базовом свойстве List (KnotSpacings), чем элементы управления Windows. Таким образом, данные, привязывающие элементы управления к BindingList, не достигают sh. BindingList прекрасно работает, если пользовательский интерфейс добавляет / удаляет элементы из BindingList, поскольку он выполняет те же операции в базовом списке. Но тогда мне нужно будет повторить действие добавления / удаления и логики c библиотеки в моем пользовательском интерфейсе, и это серьезное изменение в ожидании.
РЕДАКТИРОВАТЬ Основные изменения, внесенные в мой оригинал пост пытается: (1) уточнить проблему. (2) Distin guish это не дублирующий вопрос (хотя один из нескольких вопросов был дублирующим). (3) Признать полезные усилия других, которые были бы потеряны, если бы я удалил сообщение.