DataGridViewComboBoxColumnをオブジェクトにバインドする方法は?
-
08-07-2019 - |
質問
DataGridViewComboBoxColumn
をFooのインスタンスにバインドしようとしていますが、グリッドに値を設定すると ArgumentException
が返されて、 StringからFooに変換します。
var data = (from item in someTable
select new { Foo = item.foo, Bar = item.Bar }).ToList();
grid.DataSource = data;
column.DataPropertyName = "Foo";
column.DataSource = (from foo in Foo select foo).ToList (); //foo is an instance of Foo
column.DisplayMember = "SomeNameField"; //Foo.SomeNameField contains a description of the instance
何か不足していますか?複雑なオブジェクトにデータバインドできますか?
更新:
TypeConverterを実装し、CanConvertFrom、CanConvertTo、ConvertTo、ConvertFromをオーバーライドしました。今私は取得しています
FormatException:DataGridViewComboBoxCellの値が無効です
アイデアはありますか
解決
可能なピースがありません。
column.DataPropertyName = "Foo";
column.DisplayMember = "SomeNameField";
column.ValueMember = "Bar"; // must do this, empty string causes it to be
// of type string, basically the display value
// probably a bug in .NET
column.DataSource = from foo in Foo select foo;
grid.DataSource = data;
更新:
実際に、あなたの質問をもう一度読んだ後、あなたはその有名なバグに直面していると思います。残念ながら、カスタムTypeDescriptor / TypeConverter / BindingSourceを使用せずにバインドされたオブジェクトを返す方法はありません。
複雑なオブジェクトにバインドするための応答。デフォルトではいいえ。私は私の現在のプロジェクトのために非常に素晴らしいものを書きました。これには、ネストされたすべてのプロパティを返すカスタムTypeDescriptor / TypeConverter / BindingSourceの作成が含まれます。別の「バグ」、「。」は使用できません。メンバーの区切りには、代わりに「:」に頼らなければなりませんでした。
他のヒント
DataGridViewComboBoxColumnは常にコンボボックスアイテムリストにすべての可能な値が含まれている必要があります。そうでない場合は、「FormatException:The DataGridViewComboBoxCell value not valid」をスローします。
1つのコンボボックス列から選択された値を取得しようとしている場合、DataGridView CellParsingイベントを処理し、選択された項目をDataGridView.EditingControlから取得して、編集された列から編集コントロールを設定できます。次に例を示します。
private void dataGridView1_CellParsing(object sender,
DataGridViewCellParsingEventArgs e) {
if (dataGridView1.CurrentCell.OwningColumn is DataGridViewComboBoxColumn) {
DataGridViewComboBoxEditingControl editingControl =
(DataGridViewComboBoxEditingControl)dataGridView1.EditingControl;
e.Value = editingControl.SelectedItem;
e.ParsingApplied = true;
}
}
セルの書式設定イベントを処理することにより、各セルでのオブジェクトの表示方法をカスタマイズすることもできます。ここに、オブジェクトまたはインターフェイスのtoStringを表示するコードを示します。
private void dataGridView1_CellFormatting(object sender,
DataGridViewCellFormattingEventArgs e) {
if (e.Value != null) {
e.Value = e.Value.ToString();
e.FormattingApplied = true;
}
}
この2つのイベントを処理すれば、ビジネスオブジェクトとそのイーザー内のデータを表示および編集して、タイプコンバーターを書き込むのに十分なはずです。この作業では、DataGridViewを設定し、列を次のようにコンボボックスにします。
var data = (from item in someTable
select new { Foo = item.foo, Bar = item.Bar }).ToList();
grid.DataSource = data;
column.DataPropertyName = "Foo";
column.DataSource = (from foo in Foo select foo).ToList ();
DisplayMemberプロパティまたはValueMemberプロパティを設定する必要はありません。コンボボックスデータソースリストにFooの可能な値がすべて含まれていることを確認してください。
ご協力をお願いします。
実際には、 DataGridViewComboBoxColumn
で複合型を使用できます。
例:
DataGridViewComboBoxColumn.DataPropertyName = "ValueMode";
DataGridViewComboBoxColumn.DisplayMember = "Label";
DataGridViewComboBoxColumn.ValueMember = "Self"; *
DataGridViewComboBoxColumn.ValueType = typeof(ValueModeItem);
自己
は:
public ValueModeItem Self
{
get
{
return this;
}
}
非常に重要-複合型の「等しい」メソッドをオーバーライドする必要があります。 私の場合:
public override bool Equals(object obj)
{
if (obj is ValueModeItem && obj != null)
{
if (...)
return true;
}
return false;
}
ValueMember
を設定せずに DataGridViewComboBoxCell
の DisplayMember
を設定できないことを発見するまで、私は常に同じ問題にぶつかりました。< br>
同様に、 DisplayMember
ではなく ValueMember
を設定することも失敗します。何も定義しないか、両方を定義する必要があります。
あなたのモデルはFooであり、ComboBoxのValueがアイテムそのものであることは確かです。これを行うための最も簡単な方法は、fooにPropertyを作成し、それ自体を返すことです。
public class Foo
{
...
public Foo This { get {return this; } }
}
その後、バインディングは次のようになります。
column.DataPropertyName = "Foo";
column.DataSource = (from foo in Foo select foo).ToList (); //foo is an instance of Foo
column.DisplayMember = "SomeNameField"; //Foo.SomeNameField contains a description of the instance
column.ValueMember = "This";
これは機能するはずです。また、セルの値は予想どおりFoo型でなければなりません。
興味深いリファレンス: DataGridViewComboBoxColumnの問題
ただし、DataGridViewComboBoxColumnはこのように機能しません。 ただし、設定しない場合はToString値が表示されます DisplayMember、見ようとすると内部的に何かがおかしい SelectedItemを設定するには、DisplayMemberをpublicに設定する必要があります クラスのプロパティ。さらに悪いことに、あなたがしない場合のデフォルトの動作 ValueMemberプロパティを設定すると、DisplayMemberが返されます。 実際のアイテム自体を取得する方法はありません。唯一の回避策は、 自分自身を返すクラスのプロパティで、そのプロパティを ValueMember。もちろん、あなたのアイテムがあなたができるものではないなら (フレームワーククラスの1つなど)を変更するには、手間をかける必要があります。 一緒にアイテムへの参照を保持するコンテナオブジェクト。