質問者
ComboBox の表示データに数値を割り当てたい

質問
すべての返信
-
表示する文字列とそれに対応する数値をクラスでラップし、それをItems.Addで割り当てます。以下が参考になるでしょう。
Combobox Value member foreach loop
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=831807&SiteID=1 -
じゃんぬねっと さんからの引用
わざわざラッパ クラスを作成する必要があるのでしょうか? ただの 「値 Pair」 ですよね。
たとえば C#2.0 ならば、Generic でも良いと思いますが、何か理由があるのでしょうか?C#1.1の頃からラッパクラスを作成してきたので、その流れでC#2.0でも同じようにやっていますが(ArrayListからGenericへは変更しています)、Genericを使うとラッパクラスを使わなくてもうまくいくのでしょうか? 逆に教えていただけないでしょうか?
以下、私が実際に組んでいるコードです。 (多少、省略してます)public class Kbn
{
private string _kbnnmn;
private byte _kbncd;
public Kbn(string strkbnnmn, byte bytekbncd)
{
this._kbnnmn = strkbnnmn;
this._kbncd = bytekbncd;
}
public string Kbnnmn
{
get
{
return _kbnnmn;
}
}
public byte Kbncd
{
get
{
return _kbncd;
}
}
}
public class Rtkbn
{
private List<Kbn> _arrRtkbn = new List<Kbn>();
public Rtkbn()
{
_arrRtkbn.Add(new Kbn("ほげ~", 1));
_arrRtkbn.Add(new Kbn("ほ~げ", 2));
}
//任意の位置に任意の項目を追加する。
public void Usr_insertItem(int index, string strkbnnmn, byte bytekbncd)
{
_arrRtkbn.Insert(index, (new Kbn(strkbnnmn, bytekbncd)));
}
//任意の位置の項目を削除する。
public void Usr_deleteItem(int index)
{
_arrRtkbn.RemoveAt(index);
}
public List<Kbn> ArrRtkbn
{
get
{
return _arrRtkbn;
}
}
}
-
System.Windows.Forms の ComboBox は ComboBox.DisplayMember、ValueMember なんかを使っていない場合は Item を ToString() した結果を表示しますので、値と ToString() のときに返す文字列とを設定できるクラスがあればいいような気がします。
ただ、BCL にはちょうどいいクラスはなさそうです(あるのかな?)
class ValueContainer<T> { private T value; private string text; public ValueContainer(T value, string text) { this.value = value; this.text = text; } public T Value { get { return this.value; } set { this.value = value; } } public string Text { get { return this.text; } set { this.text = value; } } public override string ToString() { return this.text; } }
こんなクラスがあればthis.comboBox1.Items.Add(new ValueContainer<int>(1, "a")); this.comboBox1.Items.Add(new ValueContainer<int>(2, "b")); this.comboBox1.Items.Add(new ValueContainer<int>(3, "c"));
こんな風にできます。
-
キーと値のペアを DataSource に指定するならば、これではダメなのでしょうか。
とても極端な例で申し訳ないのですが...
C#2.0private void button1_Click(object sender, System.EventArgs e) {
System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<int, string>> list = (
new System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<int, string>>()
);
list.Add(new System.Collections.Generic.KeyValuePair<int, string>(1, "Tarou"));
list.Add(new System.Collections.Generic.KeyValuePair<int, string>(2, "Zirou"));
list.Add(new System.Collections.Generic.KeyValuePair<int, string>(3, "Saburo"));
list.Add(new System.Collections.Generic.KeyValuePair<int, string>(4, "Busaikuro"));this.comboBox1.DisplayMember = "Value";
this.comboBox1.ValueMember = "Key";
this.comboBox1.DataSource = list;
}
わかりにくいので、エイリアス系のクラスを作ることはありますが、
この程度であればラッパークラスまでは作らないことが多いです。
私が質問の意図を取り違えているようであれば申し訳ありません。
# ああ、ソースがきれいに表示されていない... orz -
Shinichi Aoyagi さんからの引用
System.Windows.Forms の ComboBox は ComboBox.DisplayMember、ValueMember なんかを使っていない場合は Item を ToString() した結果を表示しますので、値と ToString() のときに返す文字列とを設定できるクラスがあればいいような気がします。
ItemをToString()した結果を表示しているのですね。勉強になりました。ただ、示されたコードの例で言うと、aを選択した際は1、bを選択した際は2などと取得するにはどのような方法があるのでしょうか?
SelectedValueはnullでした。試しにComboBox.ValueMemberに"Value"なんて指定してみたのですが、やはりダメでした。Shinichi Aoyagi さんからの引用
ただ、BCL にはちょうどいいクラスはなさそうです(あるのかな?)
じゃんぬさんが示されているKeyValuePairでしょうか? -
じゃんぬねっと さんからの引用
キーと値のペアを DataSource に指定するならば、これではダメなのでしょうか。
とても極端な例で申し訳ないのですが...
いえいえOKです。KeyValuePairですが、言われてみればどこかで見たような気がしますが、いずれにしても完全に頭にありませんでした。ありがとうございます。基本的にはKeyValuePairは私が示したコードにおけるKbnクラスに相当します。値ペアをcomboboxに割り当てるためにKeyValuePairというgeneric構造体でラップするか、Kbnクラスでラップするかの違いであり、考え方自体は同じです。じゃんぬさんが示されたコードをKbnクラスで書き直すと以下のようになります。
List<Kbn> list = new List<Kbn>();
list.Add(new Kbn("Tarou", 1));
list.Add(new Kbn("Zirou", 2));
list.Add(new Kbn("Saburo", 3));
list.Add(new Kbn("Busaikuro", 4));this.comboBox1.DisplayMember = "Value";
this.comboBox1.ValueMember = "Key";
this.comboBox1.DataSource = list;私が兼田さんへの回答で示した参考URLにも同じ考え方が載っています。
Combobox Value member foreach loop
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=831807&SiteID=1私が上で掲載したコードは、上のコードを使いやすいようにクラス化したものです。なぜそのようにしているかは釈迦に説法になりますが、このコンボボックスはいたるところで使用する、場合によっては最初に空白の項目を設けたいなどの理由によります。このコードを載せたのが余計話をややこしくしたかもしれませんね。すみません。
結論から言えば、じゃんぬさんが言われるようにKbnというラッパークラスをわざわざ作る必要はないということですね。C#2.0ではKeyValuePairジェネリック構造体が用意されているので、それを使えということですね。
一つかしこくなりました。ご教示、ありがとうございました。
-
trapemiya さん、返信ありがとうございます。
trapemiya さんからの引用 私が上で掲載したコードは、上のコードを使いやすいようにクラス化したものです。なぜそのようにしているかは釈迦に説法になりますが、このコンボボックスはいたるところで使用する、場合によっては最初に空白の項目を設けたいなどの理由によります。このコードを載せたのが余計話をややこしくしたかもしれませんね。すみません。
そういうことでしたか。こちらこそ申し訳ありませんでした。
文章にばかり着目していたので、"しなければならない" かのように受け止めてしまいました。
(釈迦に説法だなんてとんでもないです。私なんてまだまだで... orz)
少し触れられていらっしゃるように、ComboBox のために用意するデータの多くは、生のデータのままということは業務アプリケーションでは少ないかもしれません。
私の場合はデータベースからマスタ データを取得してくるパターンが多いので型付 DataSet を指定しています。
空白が必要な場合は、それ用に GetData メソッドのオーバーロードを用意して DBNull.Value で入れています。
C#public HogeDataTable GetData() {}
public HogeDataTable GetData(bool hasNullData) {}
先ほどのジェネリックを使った方法が望ましいという意図ではないということを誤解のないように書いておきます。
何だか "クチゴタエ" みたいな感じになってしまって、申し訳ありませんでした。 -
じゃんぬねっと さん
> キーと値のペアを DataSource に指定するならば、これではダメなのでしょうか。
KeyValuePair は思いつきませんでした。というか、
> this.comboBox1.DisplayMember = "Value";
> this.comboBox1.ValueMember = "Key";
としてやればいいことを思いつきませんでした。
なるほどです。
trapemiya さん
> ただ、示されたコードの例で言うと、aを選択した際は1、bを選択した際は2などと
> 取得するにはどのような方法があるのでしょうか?
Items に格納されていますので、キャストしてやればアクセス可能です。
((ValueContainer<int>)comboBox1.SelectedItem).Key
または
((ValueContainer<int>)comboBox1.Items[comboBox1.SelectedIndex]).Key
などなど。
-
Shinichi Aoyagi さんからの引用 Items に格納されていますので、キャストしてやればアクセス可能です。
((ValueContainer<int>)comboBox1.SelectedItem).Key
または
((ValueContainer<int>)comboBox1.Items[comboBox1.SelectedIndex]).Key
などなど。
そうかぁ。ComboBoxのItemにはオブジェクトが保存されているんだから、キャストしてそのオブジェクトを取り出せばいいんだ。あ~、どうして思いつかなかったんだろう。どういう風にオブジェクトが組み合って動いているかを、しっかりと把握することが基本ですね。ありがとうございました。