2010-06-16 2 views
1

Я пытаюсь привязать данные SelectedItem ListBox к свойству. Следующий код является примером:Привязка выделенного объекта ListBox в присутствии BindingNavigator

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.

Идеи о том, как исправить это? Заранее спасибо.

EDIT: Вот архив примера проекта, включая двоичный файл отладки.

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

EDIT: Вот вспомогательная функция на основе принятого ответа:

 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)); 
      }; 
     } 
+0

Я не могу воспроизвести это. Он отлично работает, независимо от того, что я пытаюсь сделать со списком и навигатором (кроме кнопок «Новый» и «Удалить»). – Yegor

+0

Возможно, это версия .NET, которую вы используете? Я использую 3.5 ... – Reinderien

+0

Не удалось дублировать проблему с кодом, который вы указали. C# с .Net 3.5. Кнопки «Новый» и «Удалить» не работают, но список, кажется, заполняется просто отлично, используя любую комбинацию кнопок навигации. Можете ли вы перечислить какие-либо дополнительные действия, которые помогут воспроизвести ошибку, или, возможно, загрузите ваш проект в хранилище, чтобы мы могли посмотреть на это? – Caladain

ответ

3

Это происходит потому, что SelectedItem обновление происходит перед ListBox обновляется. Таким образом, на первом этапе listbox не может «принять» значение из другой записи формы, так как он не содержит такой записи, а затем не может восстановить выбор после переустановки элементов списка.

Решение (одно из) заключается в принуждении привязки SelectedItem к повторному использованию после изменения текущей записи формы. Сначала мы даем обязывающее имя:

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

Чем мы должны повторно связывания (обратите внимание BeginInvoke необходимо применять связывание после ListBox является заселен):

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

Вы также можете создать простой вспомогательный метод, который будет делать все эти трюки за один звонок.

+0

Работает отлично. СПАСИБО. – Reinderien