C#なら簡単 コンボボックスをつかって設定を反映させる
comboBox-event
コンボボックスとは文字入力と項目の選択の両方を受け付けることができる入力領域のことです。文字入力のためのテキストボックスと項目を選択するリストボックスを組み合わせたものであるためこのような名前がつけられています。
コンボボックスをつかってなにかを設定してこれを反映するアプリを作ってみることにします。
コンボボックス関連のイベント
コンボボックス関連のイベントはたくさんありますが、重要なものは
DropDownイベント
DropDownClosedイベント
SelectedIndexChangedイベント
SelectedValueChangedイベント
SelectionChangeCommittedイベント
コンボボックスの右側にある▼の部分をクリックすると項目が書かれたリストが表示されます。このときに発生するのがDropDownイベントです。項目を選択するためにクリックするとリストが閉じますが、このときに発生するのがDropDownClosedイベントです。
項目を選択するためには項目をクリックする方法と上下のキーを押下する方法があります。項目をクリックするとリストは閉じてしまいますが、上下のキーを押下する場合は選択された項目が変化するだけでリストが直ちに閉じることはありません。SelectedIndexChangedイベントとSelectedValueChangedイベントは選択された項目が変化したときに発生します。またSelectionChangeCommittedイベントは選択が確定したときに発生します。
もし何が選択されたのかを知るのであればSelectionChangeCommittedイベントが発生したときにどの項目が選択されたかを調べればよいでしょう。途中でどの項目が選択されたかではなく最終的にどれが選択されたのかを知りたいのであればSelectionChangeCommittedイベントが発生したときにどの項目が選択されたかを調べるとよいでしょう。
また最初からそのコンボボックスにどんな項目を表示させるのかが決まっている場合は、デザイナやそのコンボボックスが存在するフォームのコンストラクタで設定してしまってそのままでよいかもしれませんが、アプリケーションの状態によって異なる項目を表示させたい場合もあるかもしれません。そのときはDropDownイベントが発生したときに全項目をいったんクリアして表示すべき項目を挿入するとよいでしょう。
イベントの実験
では実際にコンボボックスがあるアプリケーションを作成してみて、どのイベントがどのタイミングで発生するのかを確認することにします。
イベントが発生したらイベントの名前とどの項目が選択されているかを調べてRichTextBoxにそれらを文字列として表示させます。
そしてこのときにStringBuilderオブジェクトを使います。文字列を連結するときは + でつなげばいいのですが、何回も文字列の連結処理をしたいときはStringBuilderオブジェクトをつかったほうが処理速度が速いです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
public partial class Form1 : Form { StringBuilder _sb = new StringBuilder(); public Form1() { InitializeComponent(); // 項目は全部で「1」「2」「3」「4」「5」の5個。 comboBox1.Items.Add("1"); comboBox1.Items.Add("2"); comboBox1.Items.Add("3"); comboBox1.Items.Add("4"); comboBox1.Items.Add("5"); comboBox1.Click += ComboBox1_Click; // クリックされたとき comboBox1.DropDown += ComboBox1_DropDown; comboBox1.DropDownClosed += ComboBox1_DropDownClosed; comboBox1.SelectedIndexChanged += ComboBox1_SelectedIndexChanged; comboBox1.SelectedValueChanged += ComboBox1_SelectedValueChanged; comboBox1.SelectionChangeCommitted += ComboBox1_SelectionChangeCommitted; } string GetSelectedText() { if (comboBox1.SelectedItem != null) return comboBox1.SelectedItem.ToString(); else return "None"; // なにも選択されていない場合は「None」を返す } private void ComboBox1_Click(object? sender, EventArgs e) { string str = "Click " + GetSelectedText() + "\n"; _sb.Append(str); richTextBox1.Text = _sb.ToString(); } private void ComboBox1_DropDown(object? sender, EventArgs e) { string str = "DropDown " + GetSelectedText() + "\n"; _sb.Append(str); richTextBox1.Text = _sb.ToString(); } private void ComboBox1_DropDownClosed(object? sender, EventArgs e) { string str = "DropDownClosed " + GetSelectedText() + "\n"; _sb.Append(str); richTextBox1.Text = _sb.ToString(); } private void ComboBox1_SelectedIndexChanged(object? sender, EventArgs e) { string str = "SelectedIndexChanged " + GetSelectedText() + "\n"; _sb.Append(str); richTextBox1.Text = _sb.ToString(); } private void ComboBox1_SelectedValueChanged(object? sender, EventArgs e) { string str = "SelectedValueChanged " + GetSelectedText() + "\n"; _sb.Append(str); richTextBox1.Text = _sb.ToString(); } private void ComboBox1_SelectionChangeCommitted(object? sender, EventArgs e) { string str = "SelectionChangeCommitted " + GetSelectedText() + "\n"; _sb.Append(str); richTextBox1.Text = _sb.ToString(); } // RichTextBoxがいっぱいになったとき内容をクリアできるようにしたい private void ButtonClear_Click(object sender, EventArgs e) { _sb.Clear(); richTextBox1.Text = _sb.ToString(); } } |
これで実際に動作させてみると・・・
どれも選択されていない状態で▼をクリックして「3」を選択(クリック)した場合は以下のような結果になりました。Clickイベントはマウスボタンが押されても離されないと発生しないので、最初に発生するイベントはDropDownイベントです。そのあとSelectionChangeCommittedイベントが発生し(この段階で「3」が選択されたことになっている)、DropDownClosedイベント、そのあとSelectedValueChangedイベントとSelectedIndexChangedイベントとなっています。
1 2 3 4 5 6 |
DropDown None Click None SelectionChangeCommitted 3 DropDownClosed 3 SelectedValueChanged 3 SelectedIndexChanged 3 |
どれも選択されていない状態で▼をクリックして上下のキーを押下して項目を選択し、「3」が選択されているときにエンターキーを押下した場合は以下のようになります。エンターキーを押下したときにSelectionChangeCommittedイベントが発生しています。またエンターキーを押下するかわりにコンボボックスとは関係のない部分をクリックした場合はSelectionChangeCommittedイベントは発生しません。
1 2 3 4 5 6 7 8 9 10 |
DropDown None Click None SelectedValueChanged 1 SelectedIndexChanged 1 SelectedValueChanged 2 SelectedIndexChanged 2 SelectedValueChanged 3 SelectedIndexChanged 3 SelectionChangeCommitted 3 DropDownClosed 3 |
それからTabキーを押すことでコンボボックスにフォーカスを当てることもできます。この状態で上下のキーを押下すると選択されているコンボボックスの選択項目を切り替えることができます。この場合は選択されている項目が変更するたびにSelectionChangeCommittedイベントが発生します。
1 2 3 4 5 6 |
SelectionChangeCommitted 1 SelectedValueChanged 1 SelectedIndexChanged 1 SelectionChangeCommitted 2 SelectedValueChanged 2 SelectedIndexChanged 2 |
またコンボボックスのテキストボックスの部分には自分で文字列を入力することができます。そのあと▼をクリックした場合はその文字列が項目内に存在する場合はそれが自動で選択されます。存在しない場合はどれも選択されません。
簡単なテストアプリ
SelectionChangeCommittedイベントがあったときだけ選択の変更が有効になるコンボボックスをつくります。有効な選択変更がおこなわれた場合、これをフォームのタイトルバーに表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
public partial class Form1 : Form { // SelectionChangeCommittedイベントは発生したか? bool _isSelectionChangeCommitted = false; string _oldText = ""; public Form1() { InitializeComponent(); comboBox1.Items.Add("1"); comboBox1.Items.Add("2"); comboBox1.Items.Add("3"); comboBox1.Items.Add("4"); comboBox1.Items.Add("5"); comboBox1.DropDown += ComboBox1_DropDown; comboBox1.DropDownClosed += ComboBox1_DropDownClosed; comboBox1.SelectionChangeCommitted += ComboBox1_SelectionChangeCommitted; } string GetSelectedText() { if (comboBox1.SelectedItem != null) return comboBox1.SelectedItem.ToString(); else return ""; // なにも選択されていない場合は空文字列を返す } private void ComboBox1_DropDown(object? sender, EventArgs e) { // いったんフラグをクリアするとともにこの段階で選択されている項目を保存 _isSelectionChangeCommitted = false; _oldText = GetSelectedText(); } private void ComboBox1_SelectionChangeCommitted(object? sender, EventArgs e) { // SelectionChangeCommittedイベントが発生したらフラグをセットするとともにタイトルバーの文字列を変更 _isSelectionChangeCommitted = true; Text = GetSelectedText(); } private void ComboBox1_DropDownClosed(object? sender, EventArgs e) { // SelectionChangeCommittedイベントなしにDropDownClosedイベントが発生したら // 選択されている項目をバックアップしておいたものと置き換える if (!_isSelectionChangeCommitted) { comboBox1.SelectedItem = _oldText; if (_oldText == "") comboBox1.SelectedIndex = -1; } } } |