在BindingNavigator存在的情况下绑定ListBox的SelectedItem

时间:2010-06-16 21:57:18

标签: c# .net winforms bindingsource

我正在尝试将ListBox的SelectedItem数据绑定到属性。以下代码是一个示例:

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace BindingFailure
{
 static class Program
 {
  class OuterObject
  {
   public string selected { get; set; }
   public List<string> strings { get; set; }
  }

  public static void Main()
  {
   List<OuterObject> objs = new List<OuterObject>()
   {
    new OuterObject(), new OuterObject()
   };
   objs[0].strings = new List<string> { "one", "two", "three" };
   objs[1].strings = new List<string> { "four", "five", "six" };

   Form form = new Form();

   BindingSource obs = new BindingSource(objs, null),
    ibs = new BindingSource(obs, "strings");
   BindingNavigator nav = new BindingNavigator(obs);
   ListBox lbox = new ListBox();
   lbox.DataSource = ibs;
   lbox.DataBindings.Add(new Binding("SelectedItem", obs, "selected"));

   form.Controls.Add(nav);
   form.Controls.Add(lbox);
   lbox.Location = new System.Drawing.Point(30, 30);

   Application.Run(form);
  }
 }
}

如果您只是选择一个项目,向前移动,选择一个项目然后退出,它将按预期工作。但是如果使用导航器在两个外部对象之间来回切换,则所选项目似乎会被错误的值覆盖。似乎每次BindingNavigator移动到一个元素时,ListBox都会被告知移动到其集合中的第一个项目,从而覆盖绑定到其SelectedItem的变量中的任何值。

关于如何解决这个问题的想法?提前谢谢。

编辑:这是示例项目的存档,包括调试二进制文件。

http://www.mediafire.com/?dzmqmz0mynj

编辑:这是基于接受的答案的辅助函数:

        public static void Bind(ListControl list, BindingSource outersource, string dataMember)
        {
            Binding bindSel = new Binding("SelectedItem", outersource, dataMember);
            list.DataBindings.Add(bindSel);

            outersource.CurrentChanged += delegate
            {
                list.BeginInvoke(new MethodInvoker(bindSel.ReadValue));
            };
        }

1 个答案:

答案 0 :(得分:3)

这是因为SelectedItem更新发生在列表框更新之前。因此,在第一阶段,列表框不能“接受”来自不同表单记录的值,因为它不包含此类记录,然后在重新填充列表框项目后无法恢复选择。

解决方案(其中之一)是在更改当前表单记录后强制SelectedItem绑定重新应用。首先,我们给绑定命名:

//lbox.DataBindings.Add(new Binding("SelectedIndex", obs, "Index"));
var selItemBinding = new Binding("SelectedItem", obs, "selected");
lbox.DataBindings.Add(selItemBinding);

我们必须重新应用绑定(注意重新填充listbox后,通知BeginInvoke对于应用绑定至关重要):

obs.CurrentChanged += delegate
{
    form.BeginInvoke(new MethodInvoker(selItemBinding.ReadValue));
};

你也可以创建一个简单的帮助方法,在一次调用中完成所有这些技巧。