1

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

アイテムを選択して先に進み、アイテムを選択してから終了すると、期待どおりに機能します。しかし、ナビゲーターを使用して外側の 2 つのオブジェクトを切り替えると、選択した項目が誤った値で上書きされているように見えます。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));
            };
        }
4

1 に答える 1

3

これは、リストボックスが更新される前に SelectedItem の更新が発生するために発生します。したがって、最初の段階のリストボックスでは、そのようなレコードが含まれていないため、別のフォームレコードからの値を「受け入れる」ことができず、リストボックスアイテムが再入力された後に選択を復元できません。

解決策 (の 1 つ) は、現在のフォーム レコードが変更された後に SelectedItem バインディングを強制的に再適用することです。まず、バインディングに名前を付けます。

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

バインディングを再適用する必要があるよりも (リストボックスが再設定された後にバインディングを適用するには、BeginInvoke が不可欠であることに注意してください):

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

このすべてのトリックを 1 回の呼び出しで実行する単純なヘルパー メソッドを作成することもできます。

于 2010-06-27T04:30:56.907 に答える