6.6 選択コントロール
6.6.1 リストボックス
リストボックスやコンボボックス、メニュー、ステータスバー、ツリーなど、複数の項目を保有するコントロールは System.Windows.Controls.ItemsControl クラスから派生しています。ItemsControl クラスは、任意の数の、任意の型の項目を管理する機能を提供します。項目となるオブジェクトは、ItemsControl クラスに自由に追加したり、削除することができます。
ItemsControl から派生するコントロールのうち、項目を選択することができるコントロールのために System.Windows.Controls.Primitives.Selector クラスが用意されています。リストボックスのように項目を選択することができるコントロールは Selector を継承しています。複数の項目を表示するようなコントロールの機能は、すべて ItemsControl クラスと Selectro クラスから提供されます。
リストボックスを表示するには Selector を継承する System.Windows.Controls.ListBox クラスを利用します。
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Media.Visual System.Windows.UIElement System.Windows.FrameworkElement System.Windows.Controls.Control System.Windows.Controls.ItemsControl System.Windows.Controls.Primitives.Selector System.Windows.Controls.ListBox
[LocalizabilityAttribute(LocalizationCategory.ListBox)] [StyleTypedPropertyAttribute(Property="ItemContainerStyle", StyleTargetType=typeof(ListBoxItem))] public class ListBox : Selector
このクラスのコンストラクタは、パラメータを受け取りません。
public ListBox ()
生成した ListBox オブジェクトに項目を表示するには Items プロパティが返すコレクションオブジェクトに項目となるオブジェクトを追加しなければなりません。
[BindableAttribute(true)] public ItemCollection Items { get; }
Items プロパティが返す ItemCollection オブジェクトは、項目となる任意のオブジェクトの配列を管理するコレクションです。このコレクションは Object 型の項目を管理するため、どのような型でも追加することができます。一般的なオブジェクトを追加した場合、オブジェクトの ToString() メソッドが返す文字列表現を表示するテキスト項目となります。
using System; using System.Windows; using System.Windows.Controls; class Test { [STAThread] public static void Main() { ListBox listBox = new ListBox(); listBox.Items.Add("宇宙人"); listBox.Items.Add("未来人"); listBox.Items.Add("超能力者"); listBox.Margin = new Thickness(10); Window wnd = new Window(); wnd.Content = listBox; Application app = new Application(); app.Run(wnd); } }
コード1は、ListBox クラスのインスタンスを生成し、ListBox オブジェクトの項目として文字列を追加しています。項目はオブジェクトの文字列表現をテキストとして表示するため、文字列を項目とした場合、文字列がそのまま項目となります。
ItemControls に UIElement を継承するプレゼンテーション可能なオブジェクトを設定した場合、項目として描画要素がそのまま表示されます。よって、項目として図形や別のコントロール、またはイメージや動画、その組み合わせを表示させることができます。
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Shapes; using System.Windows.Media; class Test { [STAThread] public static void Main() { Ellipse ellipse = new Ellipse(); ellipse.Fill = Brushes.Red; ellipse.Width = 200; ellipse.Height = 50; TextBlock textBlock = new TextBlock(); textBlock.Text = "Go my way!"; textBlock.FontSize = 30; Button button = new Button(); button.Content = "Here we go!!"; ListBox listBox = new ListBox(); listBox.Items.Add(ellipse); listBox.Items.Add(textBlock); listBox.Items.Add(button); listBox.Margin = new Thickness(10); Window wnd = new Window(); wnd.Content = listBox; Application app = new Application(); app.Run(wnd); } }
コード2は、リストボックスの項目に楕円形、テキスト、ボタンコントロールなどを表示しています。
6.6.2 項目の選択
Selector を継承するクラスは、項目を選択することができます。選択されている項目は、SelectedIndex プロパティによる項目のインデックスを用いる方法と、SelectedItem プロパティによる、Object 型のオブジェクトを直接用いる 2 つの方法で設定・取得することができます。
[LocalizabilityAttribute(LocalizationCategory.NeverLocalize)] [BindableAttribute(true)] public int SelectedIndex { get; set; }
[BindableAttribute(true)] public Object SelectedItem { get; set; }
SelectedIndex は、選択項目のインデックスを設定・取得し、SelectedItem はオブジェクトを直接設定・取得します。項目が選択されていない場合、SelectedIndex は -1 を返し、SelectedItem は null を返します。
選択されている項目が変更されると SelectionChanged イベントが発生します。選択の変更を常に監視したい場合は、対象のコントロールの SelectionChanged イベントにデリゲートを登録します。
public event SelectionChangedEventHandler SelectionChanged
SelectionChanged イベントには System.Windows.Controls.SelectionChangedEventHandler デリゲート型のオブジェクトを追加することができます。
public delegate void SelectionChangedEventHandler ( Object sender, SelectionChangedEventArgs e )
SelectionChangedEventHandler デリゲートの第 2 パラメータは、イベント発生時に選択されている項目の情報などを格納する System.Windows.Controls.ScrollChangedEventArgs クラスのオブジェクトです。
System.Object System.EventArgs System.Windows.RoutedEventArgs System.Windows.Controls.SelectionChangedEventArgs
public class SelectionChangedEventArgs : RoutedEventArgs
このクラスのオブジェクトは、イベント発生時の選択項目のリストを返す AddedItems プロパティを提供しています。
public IList AddedItems { get; }
戻り値の IList オブジェクトは、イベントの対象となっている選択コントロールが現在選択している項目の配列です。通常、イベントハンドラから直接 ListBox オブジェクトを参照できる場合は使う必要は無いでしょう。ListBox から直接選択項目を取得することができます。
using System; using System.Windows; using System.Windows.Controls; class Test : Window { [STAThread] public static void Main() { Window wnd = new Test(); Application app = new Application(); app.Run(wnd); } Label label; ListBox listBox; public Test() { label = new Label(); label.Content = "リストから項目を選択してください"; listBox = new ListBox(); listBox.Items.Add("たいやき"); listBox.Items.Add("あんまん"); listBox.Items.Add("カレー"); listBox.SelectionChanged += listBoxSelectionChanged; StackPanel panel = new StackPanel(); panel.Children.Add(label); panel.Children.Add(listBox); Content = panel; } private void listBoxSelectionChanged(Object sender, SelectionChangedEventArgs e) { Object item = listBox.SelectedItem; if (item != null) label.Content = item.ToString() + "は、命の源だよぉ~"; } }
コード3は、リストボックスの項目を選択すると、上部のラベルに表示されるテキストが変更するというプログラムです。リストボックスの項目を選択すると SelectionChanged イベントが発生します。このイベントが発生すると、登録されている listBoxSelectionChanged() メソッドが呼び出され、現在リストボックスに選択されている項目を使ってラベルの文字列を変更します。
6.6.3 コンボボックス
コンボボックスは、リストボックスと同様に Selector クラスを継承する任意の数の項目を表示し、選択することができるコントロールです。このコントロールを表示するには System.Windows.Controls.ComboBox クラスを使います。
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Media.Visual System.Windows.UIElement System.Windows.FrameworkElement System.Windows.Controls.Control System.Windows.Controls.ItemsControl System.Windows.Controls.Primitives.Selector System.Windows.Controls.ComboBox
[StyleTypedPropertyAttribute(Property="ItemContainerStyle", StyleTargetType=typeof(ComboBoxItem))] [TemplatePartAttribute(Name="PART_Popup", Type=typeof(Popup))] [LocalizabilityAttribute(LocalizationCategory.ComboBox)] [TemplatePartAttribute(Name="PART_EditableTextBox", Type=typeof(TextBox))] public class ComboBox : Selector
このクラスのコンストラクタは、パラメータを受け取りません。
public ComboBox ()
項目の追加や、選択されている項目の制御については ItemsControl クラスや Selector クラスのプロパティなどを利用するので ListBox クラスと同じです。
using System; using System.Windows; using System.Windows.Controls; class Test { [STAThread] public static void Main() { ComboBox comboBox = new ComboBox(); comboBox.Items.Add("宇宙人"); comboBox.Items.Add("未来人"); comboBox.Items.Add("超能力者"); StackPanel panel = new StackPanel(); panel.Children.Add(comboBox); Window wnd = new Window(); wnd.Content = panel; Application app = new Application(); app.Run(wnd); } }
コード4は、コード1とほとんど同じコードです。このプログラムでは、ListBox の代わりに ComboBox クラスのインスタンスを生成し、項目となるオブジェクトを追加しています。リストボックスとは異なり、コンボボックスはドロップダウンリストを表示して項目を選択します。
6.6.4 タブコントロール
タブコントロールは、タブを選択することで画面に表示するコンテンツを切り替えるコントロールです。パネルではありませんが、性質的にはパネルのように他のコントロールの親として機能します。多くのコントロールを配置しなければならないより複雑なアプリケーションには必須のコントロールです。
タブコントロールを表示するには System.Windows.Controls.TabControl クラスを使います。TabControl クラスは、任意の数のタブを保有し、選択されているタブに応じて表示するコンテンツを決定するという動作を行うため Selector を継承しています。表示される個々のタブは ItemsControl における項目に該当し、項目は選択することができます。
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Media.Visual System.Windows.UIElement System.Windows.FrameworkElement System.Windows.Controls.Control System.Windows.Controls.ItemsControl System.Windows.Controls.Primitives.Selector System.Windows.Controls.TabControl
[TemplatePartAttribute(Name="PART_SelectedContentHost", Type=typeof(ContentPresenter))] [StyleTypedPropertyAttribute(Property="ItemContainerStyle", StyleTargetType=typeof(TabItem))] public class TabControl : Selector
TabControl クラスのコンストラクタは、パラメータを受け取りません。
public TabControl ()
基本的な利用方法はリストボックスと同じです。Items プロパティからタブとなる項目を自由に追加したり、削除することができます。
using System; using System.Windows; using System.Windows.Controls; class Test { [STAThread] public static void Main() { TabControl tabControl = new TabControl(); tabControl.Items.Add("宇宙人"); tabControl.Items.Add("未来人"); tabControl.Items.Add("超能力者"); Window wnd = new Window(); wnd.Content = tabControl; Application app = new Application(); app.Run(wnd); } }
コード5は、文字列型のオブジェクトを 3 つ、TabControl オブジェクトの項目として追加しています。実行結果を見ると、確かにオブジェクトの文字列表現がタブ上にテキストとして表示されていることが確認できます。しかし、タブに表示されているテキストは、そのままタブのコンテンツとしても利用されています。多くの場合、これは望まれない動作でしょう。
通常、タブはタブが選択されたときに表示するコントロールやフォームを説明するためのテキストを表示します。そのため、タブに表示するオブジェクトと、タブが選択されたときに、タブコントロール全体に表示するコンテンツのオブジェクトを分離する必要があります。
タブコントロールの項目に、より詳細に設定を行いたい場合は System.Windows.Controls.TabItem クラスを用います。他のオブジェクトとは異なり、TabControl クラスの項目として TabItem オブジェクトを追加すると、TabControl はタブ上に表示するべきオブジェクトと、コンテンツに表示するオブジェクトを個別に認識できます。
System.Object System.Windows.Threading.DispatcherObject System.Windows.DependencyObject System.Windows.Media.Visual System.Windows.UIElement System.Windows.FrameworkElement System.Windows.Controls.Control System.Windows.Controls.ContentControl System.Windows.Controls.HeaderedContentControl System.Windows.Controls.TabItem
public class TabItem : HeaderedContentControl
TabItem クラスのコンストラクタは、パラメータを受け取りません。
public TabItem ()
この TabItem が項目としてタブ上に表示するオブジェクトは Header プロパティに設定してください。
[LocalizabilityAttribute(LocalizationCategory.Label)] [BindableAttribute(true)] public Object Header { get; set; }
Header プロパティに設定されているオブジェクトは、タブコントロールのタブに表示するオブジェクトとして利用されます。この項目が選択されたときに、タブコントロールのコンテンツとして表示するオブジェクトは TabItem オブジェクトの Content プロパティに設定します。
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Shapes; using System.Windows.Media; class Test { [STAThread] public static void Main() { Ellipse ellipse = new Ellipse(); ellipse.Fill = Brushes.Blue; ellipse.Width = 400; ellipse.Height = 200; Rectangle rect = new Rectangle(); rect.Fill = Brushes.Black; rect.Width = 40; rect.Height = 20; Button button = new Button(); button.Content = "ごきげんよう"; TabItem item1 = new TabItem(); item1.Header = "楕円形"; item1.Content = ellipse; TabItem item2 = new TabItem(); item2.Header = rect; item2.Content = button; TabControl tabControl = new TabControl(); tabControl.Items.Add(item1); tabControl.Items.Add(item2); Window wnd = new Window(); wnd.Content = tabControl; Application app = new Application(); app.Run(wnd); } }
コード6を実行すると「楕円形」というテキストと、黒い長方形を描画する 2 つのタブが表示されます。「楕円形」 というテキストを表示するタブは、Header プロパティに文字列を、Content プロパティに青い楕円形を設定している TabItem オブジェクトによるものです。Header プロパティに設定したオブジェクトがタブ上に表示され、Content プロパティに設定したオブジェクトが、タブ選択時にコンテンツとして表示されていることが確認できます。