Для первой части вы можете использовать ObservableCollection
вместо List
.Во второй части, как вы знаете, вы не можете обновить элементы пользовательского интерфейса из потока backgroundworker, поэтому вам необходимо перенаправить логику обновления обратно в поток пользовательского интерфейса.Это может быть достигнуто с помощью Control.Invoke()
/ Control.BeginInvoke()
.Существует множество примеров для обеих тем, поэтому я просто позволю вам разобраться в деталях.
РЕДАКТИРОВАТЬ:
Для winforms вы можете заглянуть в BindingList<T>
.Вот краткий пример, который я создал.
скажем, у вас есть
class Car
{
public string CarName { get; set; }
public override string ToString()
{
return CarName;
}
}
, вы можете создать BindingList
вот так
BindingList<Car> carList = new BindingList<Car>();
private void Form1_Load(object sender, EventArgs e)
{
carList.Add(new Car{CarName = "Foo"});
listBox1.DataSource = carList;
}
добавить один элемент в список иустановите его как источник данных для списка.
Обновление списка из потока пользовательского интерфейса очень просто (обратите внимание, что добавление в список автоматически добавляет элемент в список.
private void btnUIThread_Click(object sender, EventArgs e)
{
carList.Add(new Car{CarName = "BarFromUIThread"});
}
Вот как вы можете это сделатьдобавить (или удалить) элементы из фонового рабочего.
private void btnBackgroundworker_Click(object sender, EventArgs e)
{
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += bg_DoWork;
bg.RunWorkerAsync();
}
private delegate void UpdateUIDelegate();
void bg_DoWork(object sender, DoWorkEventArgs e)
{
listBox1.Invoke(new UpdateUIDelegate(UpdateListBox));
}
private void UpdateListBox()
{
carList.Add(new Car { CarName = "BarFromBackgroundWorkerThread" });
}