gpt4 book ai didi

c# - BindingList 未更新绑定(bind)的 ListBox

转载 作者:太空狗 更新时间:2023-10-29 21:10:51 25 4
gpt4 key购买 nike

我有一个绑定(bind)到 BindingListListBoxBindingList 是在第三方应用程序引发事件时建立的。我可以看到 BindingList 被正确绑定(bind)...但没有任何内容进入 ListBox。我对我自己的一些自定义类型使用了完全相同的逻辑,它通常运行良好。

表单类

private Facade.ControlFacade _controlFacade;        
public UavControlForm()
{
InitializeComponent();
_controlFacade = new UavController.Facade.ControlFacade();
UpdateEntityListBox();
}
private void UpdateEntityListBox()
{
lsbEntities.DataSource = _controlFacade.GetEntityTally();
lsbEntities.DisplayMember = "InstanceName";
}

外观类

private Scenario _scenario;
public ControlFacade()
{
_scenario = new Scenario();
}
public BindingList<AgStkObject> GetEntityTally()
{
BindingList<AgStkObject> entityTally = _scenario.EntityTally;
return entityTally;
}

场景类

private static BindingList<IAgStkObject> _entityTally = new BindingList<AgStkObject>();
public Scenario()
{
if (UtilStk.CheckThatStkIsAvailable())
{
UtilStk.StkRoot.OnStkObjectAdded += new IAgStkObjectRootEvents_OnStkObjectAddedEventHandler(TallyScenarioObjects);
UtilStk.StkRoot.OnStkObjectDeleted += new IAgStkObjectRootEvents_OnStkObjectDeletedEventHandler(TallyScenarioObjects);
}
}
private void TallyScenarioObjects(object sender)
{
List<AgStkObject> tallyOfStkObjects = UtilStk.GetRunningTallyOfAllStkObjects();
List<string> stkObjectNames = UtilStk.GetInstanceNamesOfStkObjects(tallyOfStkObjects);

foreach (string stkObjectName in stkObjectNames)
{
if (!SearchFlightUavTallyByName(stkObjectName))
{
if (!SearchLoiterUavTallyByName(stkObjectName))
{
if (!SearchEntityTallyByName(stkObjectName))
{
int i = stkObjectNames.IndexOf(stkObjectName);
_entityTally.Add(tallyOfStkObjects[i]);
}
}
}
}
}

我可以看到第三方应用程序触发了事件 - 这会根据需要向 _entityList 添加一个实体,但没有向 lsbEntities 添加任何内容 - 为什么?

最佳答案

(如果你想看到它被修复等,请直接跳到最后一个例子)

线程和“观察者”模式(例如 winforms 上的数据绑定(bind))很少是好 friend 。您可以尝试更换您的 BindingList<T>ThreadedBindingList<T> 一起使用我在 previous answer 上使用的代码- 但线程和 UI 的这种组合并不是 winforms 数据绑定(bind)的有意用例。

列表框本身应该支持通过列表通知事件(IBindingList/IBindingListView)进行绑定(bind),只要它们来自正确的线程。 ThreadedBindingList<T>试图通过代表您进行线程切换来解决此问题。请注意,要使其正常工作,您必须创建 ThreadedBindingList<T>来自 UI 线程,之后它有一个同步上下文,即在它开始显示表单之后。


为了说明列表框确实尊重列表更改通知的观点(在处理单个线程时):

using System;
using System.ComponentModel;
using System.Windows.Forms;
class Foo
{
public int Value { get; set; }
public Foo(int value) { Value = value; }
public override string ToString() { return Value.ToString(); }
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
using(var form = new Form())
using (var lst = new ListBox())
using (var timer = new Timer())
{
var data = new BindingList<Foo>();
form.Controls.Add(lst);
lst.DataSource = data;
timer.Interval = 1000;
int i = 0;
timer.Tick += delegate
{
data.Add(new Foo(i++));
};
lst.Dock = DockStyle.Fill;
form.Shown += delegate
{
timer.Start();
};
Application.Run(form);
}
}
}

现在添加了线程/ThreadedBindingList<T> (它不适用于常规的 BindingList<T> ):

using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
class Foo
{
public int Value { get; set; }
public Foo(int value) { Value = value; }
public override string ToString() { return Value.ToString(); }
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
using(var form = new Form())
using (var lst = new ListBox())
{
form.Controls.Add(lst);
lst.Dock = DockStyle.Fill;
form.Shown += delegate
{
BindingList<Foo> data = new ThreadedBindingList<Foo>();
lst.DataSource = data;
ThreadPool.QueueUserWorkItem(delegate
{
int i = 0;
while (true)
{
data.Add(new Foo(i++));
Thread.Sleep(1000);
}
});
};
Application.Run(form);
}
}
}
public class ThreadedBindingList<T> : BindingList<T>
{
private readonly SynchronizationContext ctx;
public ThreadedBindingList()
{
ctx = SynchronizationContext.Current;
}
protected override void OnAddingNew(AddingNewEventArgs e)
{
SynchronizationContext ctx = SynchronizationContext.Current;
if (ctx == null)
{
BaseAddingNew(e);
}
else
{
ctx.Send(delegate
{
BaseAddingNew(e);
}, null);
}
}
void BaseAddingNew(AddingNewEventArgs e)
{
base.OnAddingNew(e);
}
protected override void OnListChanged(ListChangedEventArgs e)
{
if (ctx == null)
{
BaseListChanged(e);
}
else
{
ctx.Send(delegate
{
BaseListChanged(e);
}, null);
}
}
void BaseListChanged(ListChangedEventArgs e)
{
base.OnListChanged(e);
}
}

关于c# - BindingList 未更新绑定(bind)的 ListBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4823481/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com