在 C# 中的跨线程中更新列表框绑定列表

发布于 2024-11-16 18:09:24 字数 255 浏览 3 评论 0原文

我的问题是否是两人合作。首先,我有一个学生 ID 列表,该列表会在程序中不断添加和删除。我怎样才能让列表框中仅显示列表中的当前项目。例如,如果我有 3 个 id,然后添加 1 个,列表框会自动显示 4,同样,如果我从列表中删除一项,列表框会自动缩小 1 个条目。

其次,所有对学生 ID 列表的添加和减去都是通过 backgroundworker_do 工作线程完成的。那么,在 ui 线程之外和工作线程中工作时,如何获得上述功能呢?示例代码将不胜感激

提前致谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

冬天的雪花 2024-11-23 18:09:25

对于第一部分,您可以使用 ObservableCollection 而不是 List。对于第二部分,如您所知,您无法从后台工作线程更新 UI 元素,因此您需要将更新逻辑编组回 UI 线程。这可以通过使用 Control.Invoke()< 来实现/a> / Control.BeginInvoke()。这两个主题都有很多示例,因此我将让您了解详细信息。

编辑:

对于winforms,您可以查看 BindingList。这是我创建的一个简单示例。

假设

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

将一项添加到列表中并将其设置为列表框的数据源。

从 UI 线程更新列表很简单(请注意,添加到列表会自动将项目添加到列表框中。

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

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" });
}
摇划花蜜的午后 2024-11-23 18:09:25

我不完全理解第一部分,当前项目是什么意思?

对于第二部分,您必须调用列表框的更新。像这样:

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
        }
}

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
        }
}
笑饮青盏花 2024-11-23 18:09:25

接受的答案很好,但 BindingList 没有排序方法,所以我被迫使用列表并找出简单的解决方案

在 Windows Froms 中

在跨线程中我刚刚使用了

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

VOILA

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文