Updating a listbox binded list in a cross-thread in c#

自闭症网瘾萝莉.ら 提交于 2019-12-11 16:46:30

问题


My question if kind of a two parter. First of all, i have a list of student id's that is constantly added to and removed from within the program. How can i have it so that only the current items in the list are displayed in the listbox. So for example, if i have three id's and i add one, the listbox shows 4 automatically and similarly if i take one item away from the list, the listbox shrinks by 1 entry automatically.

Secondly, all this adding and subtracting to the student id list is done with a backgroundworker_do work thread. So how can i get the above functionality while working outside the ui thread and being in the worker thread? Sample code will be much appreciated

Thanks in Advance!


回答1:


For the first part, you can use an ObservableCollection instead of a List. For the second part, as you know, you cannot update UI elements from backgroundworker thread so you need to marshall the updating logic back to UI thread. This can be achieved by using Control.Invoke() / Control.BeginInvoke(). There are plenty of examples out there for both topics so I'll just let you figure the details out.

EDIT:

For winforms, you can look into BindingList<T>. Here's a quick example I created.

say you have

    class Car
    {
        public string CarName { get; set; }

        public override string ToString()
        {
            return CarName;
        }
    }

you can create a BindingList like this

    BindingList<Car> carList = new BindingList<Car>();

    private void Form1_Load(object sender, EventArgs e)
    {
        carList.Add(new Car{CarName = "Foo"});
        listBox1.DataSource = carList;
    }

add one item to the list and set it as the datasource for the listbox.

Updating the list from the UI thread is simple (note adding to the list automatically adds the item to listbox.

    private void btnUIThread_Click(object sender, EventArgs e)
    {
        carList.Add(new Car{CarName = "BarFromUIThread"});
    }

Here's how you can add (or remove) items from a background worker.

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" });
}



回答2:


i don't completely understand the first part, what do you mean with current items?

For the second part, you have to invoke the updating of your listbox. Like this:

void updateListbox()
{
        if (listbox.Dispatcher.Thread != Thread.CurrentThread)
        {
            //invoke this function, because another thread is calling this function
            listbox.Dispatcher.Invoke(new Action(updateListbox));
        }
        else
        {
            //update listbox
        }
}



回答3:


The accepted answer is good but BindingList does not have Sort method so i was forced to use list and find out simple solution

In Windows Froms

In cross thread i just used

// this = from on which listbox control is created.
this.Invoke(new Action(() => { SomeBindingSource.ResetBindings(false); }));

and VOILA



来源:https://stackoverflow.com/questions/6411338/updating-a-listbox-binded-list-in-a-cross-thread-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!