DataRowをComboBoxの値メンバーとして設定
質問
DataTableを使用してXMLファイルからComboBoxにアイテムを入力しています。現在、1つの列がComboBoxのディスプレイメンバーであり、別の列が値メンバーであるように設定しています。ただし、selectedItemパラメーターを設定する必要があり、値メンバーが一意でない可能性があるため、これは常に機能するとは限りません。
テーブルに値メンバーの重複があるかどうかわからないため、ComboBoxの値メンバーとしてDataRow全体を配置し、ComboBox.SelectedITem =(DataRow)を使用することを考えましたsome_data_row;を選択します。常に正しいComboBoxオブジェクトが選択されます。
これをどのように達成しますか?これを行うより良い方法はありますか?私は提案を受け入れますが、表示メンバーと価値メンバーの両方に到達できることが非常に重要です。
ご協力ありがとうございます!
編集:以前は十分に明確ではなかったかもしれませんが、ここでこれが最善のアプローチであるかどうかを尋ねている間、私はこれを行う方法方法も尋ねています。 valuememberパラメーターを設定しない場合、SelectedItemはDataRowViewタイプです... selectedValueパラメーターを使用してComboBoxから項目を選択し、値メンバーを明示的に設定せずにそれを実行しようとすると、例外がスローされます。
解決 2
まず、アダム・ロビンソンに感謝します。あなたの答えは正しかったと確信していますが、それは私が聞きたかったことではありませんでした。別の方法で問題を解決しましたが、他の誰かに役立つかもしれないと思うので、ここに投稿しています。
やったことは、新しいクラスを作成したことです。私の場合は、プロパティDataRowを持つListObjectという名前を付けました(後でわかるように、他の型でも動作します。私のアイテム値プロパティとして)。また、メソッドをオーバーライドします:
- String ToString()
- bool Equals(object obj)
- int GetHashCode()-私の場合は必要ありませんが、Visual Studio
オーバーライドする必要があることを警告します。
アイデアは、ComboBox.Itemsコレクションを自分のクラスのオブジェクトで埋め、カスタム文字列を表示できるというものでした(このように解決しなかった場合、スタックオーバーフローに関する次の質問は、おそらく読み取り時にDisplayMembersをカスタマイズすることですDataRowからのアイテム)と1つのクラスのアイテム(私の場合はDataRow)のみを比較します。
コードはここにあり、素晴らしい動作をします(少なくとも私がそれでやりたかったことには)。
public class ListObject
{
public DataRow element;
public String DisplayObject = null;
public ListObject(DataRow dr)
{
element = dr;
}
public ListObject(DataRow dr, String dspObject)
{
element = dr;
DisplayObject = dspObject;
}
public override String ToString()
{
if (DisplayObject == null) throw new Exception("DisplayObject property was not set.");
return element[DisplayObject].ToString();
}
public override bool Equals(object obj)
{
if (obj.GetType() == typeof(ListObject))
return Equals(((ListObject)obj).element, this.element);
else return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
ComboBoxにforeachステートメントを入力するだけでよいので、私の場合はうまくいきます:
dtUsers.ReadXml(Program.Settings.xmlInputUsers);
foreach(DataRow dr in dtUsers.Rows)
{
cmbUser.Items.Add(new ListObject(dr, "Name"));
}
そして、選択したいDataRowを取得したら、これを行うだけです:
cmbUser.SelectedItem = new ListObject(dlg.SelectedDataRow);
DataMeのみが比較され、ComboBox.Itemsコレクションを入力したときから表示パラメーターが設定されるため、DisplayMemberなどについて心配する必要はありません。また、toStringメソッドはオーバーライドされるため、出力を実際にカスタマイズできます。
このクラスの作成は、 ComboBox.SelectedItem Property のmsdn記事(SelectedItemプロパティはIndexOfメソッドを使用して機能する)が原因でのみ可能でした。このメソッドはEqualsメソッドを使用して同等性を判断します。
他のヒント
ListBox
を DataTable
にバインドすると、実際には DataTable <を表す
DataView
にバインドされます/ code>( DataTable
は IListSource
を実装し、 DataView
を返します)。 SelectedItem
を DataRow
インスタンスに直接設定することはできません。 DataRowView
インスタンスに設定する必要があります。残念ながら、 DataRow
から DataRowView
を取得する簡単な方法はありません。
DataRowView
を介してすべての対話を行う方がよいでしょう。これにより、 SelectedItem
を明示的に設定できます。
SelectedValue
プロパティは使用できません。これには SelectedItem
を使用する必要があります。
これは、DataTableをコンボボックスに取得する最も簡単な方法です
private void load() {
DataTable dt = // get data from DB
comboBox1.ValueMember = null; // allows you to get all fields in the obj to combobox
comboBox1.DisplayMember = "ccType";//label displayed from dt
comboBox1.DataSource = dt;
}
//to test
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
DataRowView current = (DataRowView)comboBox1.SelectedValue;
string drs = current.Row["ID"].ToString();
}