Im trying to access ui controls on the main thread from a backgroundworker thread. I know this is a well known issue but i cannot find any information on how to access a datagridview in particular from the backgrounder thread. I know the code to make a list box is:
private delegate void AddListBoxItemDelegate(object item);
private void AddListBoxItem(object item)
{
开发者_如何学C //Check to see if the control is on another thread
if (this.listBox1.InvokeRequired)
this.listBox1.Invoke(new AddListBoxItemDelegate(this.AddListBoxItem), item);
else
this.listBox1.Items.Add(item);
}
How does one make datagridview controls work? Also the above method only works for one listbox(listBox1), is there a way to make a method that works for all listbox controls in the main ui?
Thanks
The Invoke
method on the DataGridView
works in the same manner as the ListBox
.
Below is an example where the DataGridView
was originally bound to a BindingList<items>
and we create a new list and bind to that. This should be equivalent to your requirement of getting the DataTable
from your call to Oracle and setting this as the DataSource
.
private delegate void SetDGVValueDelegate(BindingList<Something> items);
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// Some call to your data access infrastructure that returns the list of itmes
// or in your case a datatable goes here, in my code I just create it in memory.
BindingList<Something> items = new BindingList<Something>();
items.Add(new Something() { Name = "does" });
items.Add(new Something() { Name = "this" });
items.Add(new Something() { Name = "work?" });
SetDGVValue(BindingList<Something> items)
}
private void SetDGVValue(BindingList<Something> items)
{
if (dataGridView1.InvokeRequired)
{
dataGridView1.Invoke(new SetDGVValueDelegate(SetDGVValue), items);
}
else
{
dataGridView1.DataSource = items;
}
}
In my test code that successfully worked with the DataGridView
, setting that datasource to the one generated in the DoWork eventhandler.
You can also use the RunWorkerCompleted
callback since it is marshalled to the UI thread. An example is below:
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
dataGridView1[0, 0].Value = "Will this work?";
}
As for your second part to the question, there are several ways to achieve this. The most obvious is to pass in the ListBox you want to work on when you call the BackGroundWork, like so:
backgroundWorker1.RunWorkerAsync(this.listBox2);
Then you can cast the arguments object within the DoWork eventhandler:
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
ListBox l = e.Argument as ListBox;
// And now l is whichever listbox you passed in
// be careful to call invoke on it though, since you still have thread issues!
}
精彩评论