最初に、通常のバインディング (テキスト ボックスの Text などの標準プロパティを使用) について少しお話ししたいと思います。ここでのサンプル グリッドには 2 行しかありません (簡単にするため)。2 つの列 (ID と名前)、DataGridView (myGrid)、および TextBox (myTextBox) を持つ 2 つの行 (myDataTable) のテーブルがあるとします。データをバインドするコードは次のとおりです。
myGrid.DataSource = myDataTable;
myTextBox.DataBindings.Add("Text", myDataTable, "Name");
データをバインドした後、グリッドで選択が変更されると、情報はコントロール TextBox に自動的に更新されます。たとえば、2 つの行は次のとおりです。
ID | Name
1 .NET
2 Java
最初、グリッド内の選択はインデックス 0 で、myTextBox のテキストは「.NET」で、選択を次の位置 (インデックス 1) に移動します。myTextBox のテキストは「Java」で、何度も何度も移動し、前後に移動します。私が期待するように、それは正常に動作します。しかし、List というカスタム プロパティを持つコントロールができました。これは List のタイプであり、読み取り専用です。それをテーブルの列 (Name など) にバインドしたいのですが、同じバインド ルールを実行しますが、カスタム プロパティの型が私の Name 列が文字列のタイプである間にリストします。バインディングコードは次のとおりです。
Binding bind = new Binding("List", myDataTable, "Name"){
ControlUpdateMode = ControlUpdateMode.Never //Because my List property is readonly
};
//formating string data before updating to the datasource
bind.Parse += (s,e) => {
List<string> data = (List<string>) e.Value;
if(data.Count == 0) e.Value = DBNull.Value;
else e.Value = string.Join(",",data.ToArray());//format as comma separated string
};
myCustomControl.DataBindings.Add(bind);
この場合、myDataTable には現在、次のように列 Name にデータがないとします。
ID | Name
1 <DBNull.Value> <--- current index
2 <DBNull.Value>
デモを実行した後、グリッドの現在の選択インデックスは 0 です。たとえば、次のように更新して、myCustomControl プロパティ リスト (参照ではなくアイテム) の値を変更してみます。
myCustomControl.List.Add(".NET");
myCustomControl.List.Add("Java");
次に、グリッド内の選択を次の位置 (インデックス 1) に移動すると、次のように、値 ".NET,Java" が列 Name の行 0 のデータソースに更新されます。
ID | Name
1 .NET,Java
2 <----- current index
選択をインデックス 0 に戻すと、行 1 の列 Name の値も次のように「.NET,Java」に更新されます。
ID | Name
1 .NET,Java <----- current index
2 .NET,Java
これは私が望むものではありません。つまり、コントロール myCustomControl を介して値を更新する必要があります。ここに私が欲しいものがあります:
ID | Name
1 .NET,Java <----- current index
2
インデックス 1 からインデックス 0 に戻る時点で、List プロパティの値はまだ 2 つの項目 (「.NET」と「Java」) を持つリストであるため、移動後にこれが更新されることがわかります。行 1 の列 Name のセル。行 0 の列 Name のセルに更新された後、List プロパティの値をリセットして、選択範囲がインデックス 1 のときに既に空になるようにする方法を見つけています。Parse イベント ハンドラーを次のように変更しようとしましたが、良い揺れはありません。
bind.Parse += (s,e) => {
List<string> data = (List<string>) e.Value;
if(data.Count == 0) e.Value = DBNull.Value;
else e.Value = string.Join(",",data.ToArray());//format as comma separated string
//I think at here, the value has been already updated to the datasource
//and I can perform the reset
myCustomControl.List.Clear();
};
ただし、値がデータソースに更新される前にクリアされるように見えるため、データソースに更新される値はありません (「.NET、Java」ではなく、DBNull.Value です)。
次に、これも試しました:
bind.BindingComplete += (s,e) => {
if(e.BindingCompleteContext == BindingCompleteContext.DataSourceUpdate)
myCustomControl.List.Clear();
};
データがデータソースに更新されているかどうかを確認する必要があると思いました。リストをクリアできます。また、クリアする前に true としてマークし、クリア後に false にリセットするフラグをいくつか試しました。このフラグを使用して bind.Parse の流れを制御しますが、何もしませんでした。
この問題を解決するアイデアはありますか? あなたの助けは非常に高く評価されます! ありがとうございました。