Хотя вы этого не писали, но я думаю, причина в том, что элементы, которые вы добавляете в свой источник данных, добавляются в коллекцию, которая не реализует интерфейс IBindingList. Вы, вероятно, используете простой список для хранения ваших прочитанных данных.
Если ваш 'DataSourceimplements this interface, then after adding an item to your collection an event is raised. The class that holds the
DataSource, whether it is a
DataGridViewor a
BindingSource` получите уведомление об изменениях в списке и обновите их содержимое соответствующим образом.
Решением будет хранение ваших элементов в объекте класса System.ComponentModel.BindingList<T>
.
Предположим, предметы, которые вы хотите показать, относятся к классу MyReadData
.
class MyForm : Form
{
public MyForm()
{
InitializeComponents();
this.myReadItems = new BindingList<MyReadData>();
this.MyBindingSource.DataSource = this.myReadItems;
// if not already done in InitializeComponents
this.MyDataGridView.DataSource = this.MyBindingSource;
}
private readonly BindingList<MyReadData> myReadItems;
// whenever needed, start the BackGroundWorker.
private void OnButtonReadFile_Click(object send, EventArgs e)
{
// create and start the backgroundworker
BackGroundWorkdr worker = ...
MyBackGroundWorkerParams params = ...
worker.RunWorkerAsync(params);
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
// I am certain the sender is my BackGroundWorker:
BackgroundWorker worker = (BackGroundWorker)sender;
MyBackGroundWorkerParams params = (MyBackGroundWorkerParams)e.Argument;
// do some work using the params
while (readData != null)
{
// some data read.
// dont't add the data to the list, just report the data that must been added to the list:
// someCalculations...
int percentProgress = ...
MyReadData dataToAddToGrid = ...
worker.ReportProgress(percentProgress, dataToAddToGrid);
}
private void bw_progressChanged(object sender, ProgressChangedEventArgs e)
{
// no need to call invoke, this is already the context of your forms thread
Debug.Assert(!This.InvokeReguired);
MyReadData dataToAdddToGrid = (MyReadData)e.UserState;
this.myReadItems.Add(dataToAddToGrid);
}
}
Основное отличие состоит в том, что вы не должны позволять вашему BackgroundWorker
добавлять данные в список отображаемых данных. Задача BackGroundWorker - прочитать данные и сообщить всем, кому интересно, какие данные были прочитаны.
Поскольку задача MyForm
- отображать считанные данные, пусть MyForm
решает, какие считанные данные отображать и в каком формате. Это расширяет возможности повторного использования как MyForm
, так и MyBackGroundWorker
: MyForm
может отображать то, что было извлечено другим способом, а MyBackGroundWorker
можно использовать для информирования других, а не MyForm
, для уведомления о прочитанных данных.
Кроме того, контекст отображения обработчика события изменения хода выполнения является контекстом MyForm, поэтому вызов не требуется.
Вы также можете назначить IBindingList непосредственно DataGridView без использования BindingSource. Единственная причина сохранить BindingSource - это если вам нужен доступ к элементу Current
или если вы хотите, чтобы ваш DataGridView мог свободно заполнять DataGridView другими элементами, кроме содержимого вашего BindingList.
Наконец: наиболее важной частью решения было то, что элементы были добавлены в IBindingList.
System.Components.BindingList<T>
- это класс с ограниченной функциональностью. Если вы хотите упорядочить строки в вашем DataGridView
, или показать только элементы, соответствующие некоторому предикату, или объединить элементы из нескольких источников в один DataGridView, рассмотрите возможность использования Equin.ApplicationFramework.BindingListView
using Equin.ApplicationFramework;
public MyForm()
{
InitializeComponents();
this.myReadItems = new BindingListView<MyReadData>(this.components);
this.MyBindingSource.DataSource = this.myReadItems;
this.MyDataGridView.DataSource = this.MyBindingSource;
}
private readonly BindingListView<MyReadData> myReadItems;
private void bw_progressChanged(object sender, ProgressChangedEventArgs e)
{
MyReadData dataToAdddToGrid = (MyReadData)e.UserState;
this.myReadItems.Add(dataToAddToGrid);
// finished updating the list, DataGridView can be updated:
this.myReadItems.Refresh();
// this Refresh function allows you to change several items in the list
// without unnecessary intermediate updates of your BindingSource and DataGridView
}
Presto, вот и все: бесплатная сортировка или ваши столбцы, щелкнув заголовок столбца. Рассмотрите возможность изучения их примера проекта, чтобы увидеть, как работает фильтрация и как использовать несколько источников.
// Show only Brummies
this.myReadData.ApplyFilter(person => person.Address.City == "Birmingham");
// Remove the filter, show everyone again
this.myReadData.RemoveFilter();
01.09.2017