的BindingList没有更新绑定列表框 [英] BindingList not updating bound ListBox
问题描述
我有一个绑定到一个ListBox
的BindingList
。在的BindingList
建成时,第三方应用程序引发的事件。我可以看到的BindingList
被正确绑定...但没有进入的ListBox
。我已经使用了相同的逻辑,与一些我自己的自定义类型,它通常工作得很好。
I have a ListBox
that is bound to a BindingList
. The BindingList
is built up when a third party application raises an event. I can see the BindingList
being bound correctly... but nothing enters the ListBox
. I have used the exact same logic with some of my own custom types and it usually works very well.
Form类
private Facade.ControlFacade _controlFacade;
public UavControlForm()
{
InitializeComponent();
_controlFacade = new UavController.Facade.ControlFacade();
UpdateEntityListBox();
}
private void UpdateEntityListBox()
{
lsbEntities.DataSource = _controlFacade.GetEntityTally();
lsbEntities.DisplayMember = "InstanceName";
}
Facade类
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
,但noothing被添加到 lsbEntities
- 为什么
I can see the event fire from the third-party application - this adds an entity to _entityList
as desired, but noothing is added to lsbEntities
- why?
推荐答案
如果你想看到它固定的(直接跳到最后一个例子吗?等)
(jump right to the last example if you want to see it fixed etc)
主题和观察员的模式(如数据绑定的WinForms上)很少好朋友。你可以尝试更换你的的BindingList< T>
用法与 ThreadedBindingList< T>
代码,我在用的以前的答案 - 但是线程和用户界面的组合是不是的WinForms的有意用例数据 - 结合。
Threads and "observer" patterns (such as the data-binding on winforms) are rarely good friends. You could try replacing your BindingList<T>
usage with the ThreadedBindingList<T>
code I used on a previous answer - but this combination of threads and UI is not an intentional use-case of winforms data-binding.
列表框的本身的应该支持通过名单通知事件绑定( IBindingList的
/ IBindingListView
),只要他们到达形成正确的线程。 ThreadedBindingList< T>
试图通过线程切换代表您解决此问题。请注意,这个工作您必须创建 ThreadedBindingList< T>
从UI线程,的之后的它有一个同步上下文,即它已经开始展示的形式了。
The listbox itself should support binding via list notification events (IBindingList
/ IBindingListView
), as long as they arrive form the right thread. ThreadedBindingList<T>
attempts to fix this by thread-switching on your behalf. Note that for this to work you must create the ThreadedBindingList<T>
from the UI thread, after it has a sync-context, i.e. after it has started displaying forms.
要说明的ListBox的点确实有关列表更改通知(使用一个线程打交道时):
To illustrate the point that listbox does respect list-change notifications (when dealing with a single thread):
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);
}
}
这篇关于的BindingList没有更新绑定列表框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!