c# – BindingList不更新绑定的ListBox

前端之家收集整理的这篇文章主要介绍了c# – BindingList不更新绑定的ListBox前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个绑定到BindingList的ListBox. BindingList是在第三方应用程序引发事件时构建的.我可以看到绑定列表正确绑定…但没有任何内容进入ListBox.我使用了与我自己的一些自定义类型完全相同的逻辑,它通常工作得很好.

表格类

  1. private Facade.ControlFacade _controlFacade;
  2. public UavControlForm()
  3. {
  4. InitializeComponent();
  5. _controlFacade = new UavController.Facade.ControlFacade();
  6. UpdateEntityListBox();
  7. }
  8. private void UpdateEntityListBox()
  9. {
  10. lsbEntities.DataSource = _controlFacade.GetEntityTally();
  11. lsbEntities.DisplayMember = "InstanceName";
  12. }

门面课

  1. private Scenario _scenario;
  2. public ControlFacade()
  3. {
  4. _scenario = new Scenario();
  5. }
  6. public BindingList<AgStkObject> GetEntityTally()
  7. {
  8. BindingList<AgStkObject> entityTally = _scenario.EntityTally;
  9. return entityTally;
  10. }

场景类

  1. private static BindingList<IAgStkObject> _entityTally = new BindingList<AgStkObject>();
  2. public Scenario()
  3. {
  4. if (UtilStk.CheckThatStkIsAvailable())
  5. {
  6. UtilStk.StkRoot.OnStkObjectAdded += new IAgStkObjectRootEvents_OnStkObjectAddedEventHandler(TallyScenarioObjects);
  7. UtilStk.StkRoot.OnStkObjectDeleted += new IAgStkObjectRootEvents_OnStkObjectDeletedEventHandler(TallyScenarioObjects);
  8. }
  9. }
  10. private void TallyScenarioObjects(object sender)
  11. {
  12. List<AgStkObject> tallyOfStkObjects = UtilStk.GetRunningTallyOfAllStkObjects();
  13. List<string> stkObjectNames = UtilStk.GetInstanceNamesOfStkObjects(tallyOfStkObjects);
  14.  
  15. foreach (string stkObjectName in stkObjectNames)
  16. {
  17. if (!SearchFlightUavTallyByName(stkObjectName))
  18. {
  19. if (!SearchLoiterUavTallyByName(stkObjectName))
  20. {
  21. if (!SearchEntityTallyByName(stkObjectName))
  22. {
  23. int i = stkObjectNames.IndexOf(stkObjectName);
  24. _entityTally.Add(tallyOfStkObjects[i]);
  25. }
  26. }
  27. }
  28. }
  29. }

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

@R_404_323@

(如果你想看到它固定等,请跳到最后一个例子)

线程和“观察者”模式(例如winforms上的数据绑定)很少是好朋友.您可以尝试替换BindingList< T>与ThreadedBindingList< T>的使用我在previous answer上使用的代码 – 但这种线程和UI的组合并不是winforms数据绑定的故意用例.

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

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

  1. using System;
  2. using System.ComponentModel;
  3. using System.Windows.Forms;
  4. class Foo
  5. {
  6. public int Value { get; set; }
  7. public Foo(int value) { Value = value; }
  8. public override string ToString() { return Value.ToString(); }
  9. }
  10. static class Program
  11. {
  12. [STAThread]
  13. static void Main()
  14. {
  15. Application.EnableVisualStyles();
  16. using(var form = new Form())
  17. using (var lst = new ListBox())
  18. using (var timer = new Timer())
  19. {
  20. var data = new BindingList<Foo>();
  21. form.Controls.Add(lst);
  22. lst.DataSource = data;
  23. timer.Interval = 1000;
  24. int i = 0;
  25. timer.Tick += delegate
  26. {
  27. data.Add(new Foo(i++));
  28. };
  29. lst.Dock = DockStyle.Fill;
  30. form.Shown += delegate
  31. {
  32. timer.Start();
  33. };
  34. Application.Run(form);
  35. }
  36. }
  37. }

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

  1. using System;
  2. using System.ComponentModel;
  3. using System.Threading;
  4. using System.Windows.Forms;
  5. class Foo
  6. {
  7. public int Value { get; set; }
  8. public Foo(int value) { Value = value; }
  9. public override string ToString() { return Value.ToString(); }
  10. }
  11. static class Program
  12. {
  13. [STAThread]
  14. static void Main()
  15. {
  16. Application.EnableVisualStyles();
  17. using(var form = new Form())
  18. using (var lst = new ListBox())
  19. {
  20. form.Controls.Add(lst);
  21. lst.Dock = DockStyle.Fill;
  22. form.Shown += delegate
  23. {
  24. BindingList<Foo> data = new ThreadedBindingList<Foo>();
  25. lst.DataSource = data;
  26. ThreadPool.QueueUserWorkItem(delegate
  27. {
  28. int i = 0;
  29. while (true)
  30. {
  31. data.Add(new Foo(i++));
  32. Thread.Sleep(1000);
  33. }
  34. });
  35. };
  36. Application.Run(form);
  37. }
  38. }
  39. }
  40. public class ThreadedBindingList<T> : BindingList<T>
  41. {
  42. private readonly SynchronizationContext ctx;
  43. public ThreadedBindingList()
  44. {
  45. ctx = SynchronizationContext.Current;
  46. }
  47. protected override void OnAddingNew(AddingNewEventArgs e)
  48. {
  49. SynchronizationContext ctx = SynchronizationContext.Current;
  50. if (ctx == null)
  51. {
  52. BaseAddingNew(e);
  53. }
  54. else
  55. {
  56. ctx.Send(delegate
  57. {
  58. BaseAddingNew(e);
  59. },null);
  60. }
  61. }
  62. void BaseAddingNew(AddingNewEventArgs e)
  63. {
  64. base.OnAddingNew(e);
  65. }
  66. protected override void OnListChanged(ListChangedEventArgs e)
  67. {
  68. if (ctx == null)
  69. {
  70. BaseListChanged(e);
  71. }
  72. else
  73. {
  74. ctx.Send(delegate
  75. {
  76. BaseListChanged(e);
  77. },null);
  78. }
  79. }
  80. void BaseListChanged(ListChangedEventArgs e)
  81. {
  82. base.OnListChanged(e);
  83. }
  84. }

猜你在找的C#相关文章