wul*_*pro 6 c# data-binding winforms
我有一个ListBox必然的BindingList.在BindingList第三方应用程序引发事件时构建.我可以看到BindingList正确绑定...但没有任何进入ListBox.我使用了与我自己的一些自定义类型完全相同的逻辑,它通常工作得很好.
表格类
private Facade.ControlFacade _controlFacade;
public UavControlForm()
{
InitializeComponent();
_controlFacade = new UavController.Facade.ControlFacade();
UpdateEntityListBox();
}
private void UpdateEntityListBox()
{
lsbEntities.DataSource = _controlFacade.GetEntityTally();
lsbEntities.DisplayMember = "InstanceName";
}
Run Code Online (Sandbox Code Playgroud)
门面课
private Scenario _scenario;
public ControlFacade()
{
_scenario = new Scenario();
}
public BindingList<AgStkObject> GetEntityTally()
{
BindingList<AgStkObject> entityTally = _scenario.EntityTally;
return entityTally;
}
Run Code Online (Sandbox Code Playgroud)
场景类
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]);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我可以看到来自第三方应用程序的事件触发 - 这会_entityList根据需要添加一个实体,但是没有添加任何内容lsbEntities- 为什么?
Mar*_*ell 11
(如果你想看到它固定等,请跳到最后一个例子)
线程和"观察者"模式(例如winforms上的数据绑定)很少是好朋友.您可以尝试BindingList<T>使用ThreadedBindingList<T>我在之前的答案中使用的代码替换您的用法- 但线程和UI的这种组合不是winforms数据绑定的故意用例.
列表框本身应该支持通过列表通知事件(IBindingList/ IBindingListView)进行绑定,只要它们到达正确的线程即可.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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在增加了线程/ 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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5129 次 |
| 最近记录: |