WisdomSoft - for your serial experiences.

6.6 選択コントロール

複数の項目を表示し、ユーザーが選択できるコントロールを紹介します。複数の項目を表示するコントロールは ItemsControl クラスから派生しています。リストボックス、コンボボックス、タブなどが代表的な選択コントロールです。

6.6.1 リストボックス

リストボックスやコンボボックス、メニュー、ステータスバー、ツリーなど、複数の項目を保有するコントロールは System.Windows.Controls.ItemsControl クラスから派生しています。ItemsControl クラスは、任意の数の、任意の型の項目を管理する機能を提供します。項目となるオブジェクトは、ItemsControl クラスに自由に追加したり、削除することができます。

ItemsControl から派生するコントロールのうち、項目を選択することができるコントロールのために System.Windows.Controls.Primitives.Selector クラスが用意されています。リストボックスのように項目を選択することができるコントロールは Selector を継承しています。複数の項目を表示するようなコントロールの機能は、すべて ItemsControl クラスと Selectro クラスから提供されます。

リストボックスを表示するには Selector を継承する System.Windows.Controls.ListBox クラスを利用します。

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

このクラスのコンストラクタは、パラメータを受け取りません。

ListBox クラスのコンストラクタ
public ListBox ()

生成した ListBox オブジェクトに項目を表示するには Items プロパティが返すコレクションオブジェクトに項目となるオブジェクトを追加しなければなりません。

ItemsControl クラス Items プロパティ
[BindableAttribute(true)] 
public ItemCollection Items { get; }

Items プロパティが返す ItemCollection オブジェクトは、項目となる任意のオブジェクトの配列を管理するコレクションです。このコレクションは Object 型の項目を管理するため、どのような型でも追加することができます。一般的なオブジェクトを追加した場合、オブジェクトの ToString() メソッドが返す文字列表現を表示するテキスト項目となります。

コード1
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 実行結果

コード1は、ListBox クラスのインスタンスを生成し、ListBox オブジェクトの項目として文字列を追加しています。項目はオブジェクトの文字列表現をテキストとして表示するため、文字列を項目とした場合、文字列がそのまま項目となります。

ItemControls に UIElement を継承するプレゼンテーション可能なオブジェクトを設定した場合、項目として描画要素がそのまま表示されます。よって、項目として図形や別のコントロール、またはイメージや動画、その組み合わせを表示させることができます。

コード2
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 実行結果

コード2は、リストボックスの項目に楕円形、テキスト、ボタンコントロールなどを表示しています。

6.6.2 項目の選択

Selector を継承するクラスは、項目を選択することができます。選択されている項目は、SelectedIndex プロパティによる項目のインデックスを用いる方法と、SelectedItem プロパティによる、Object 型のオブジェクトを直接用いる 2 つの方法で設定・取得することができます。

Selector クラス SelectedIndex プロパティ
[LocalizabilityAttribute(LocalizationCategory.NeverLocalize)] 
[BindableAttribute(true)] 
public int SelectedIndex { get; set; }
Selector クラス SelectedItem プロパティ
[BindableAttribute(true)] 
public Object SelectedItem { get; set; }

SelectedIndex は、選択項目のインデックスを設定・取得し、SelectedItem はオブジェクトを直接設定・取得します。項目が選択されていない場合、SelectedIndex は -1 を返し、SelectedItem は null を返します。

選択されている項目が変更されると SelectionChanged イベントが発生します。選択の変更を常に監視したい場合は、対象のコントロールの SelectionChanged イベントにデリゲートを登録します。

Selector クラス SelectionChanged イベント
public event SelectionChangedEventHandler SelectionChanged

SelectionChanged イベントには System.Windows.Controls.SelectionChangedEventHandler デリゲート型のオブジェクトを追加することができます。

System.Windows.Controls.SelectionChangedEventHandler デリゲート
public delegate void SelectionChangedEventHandler (
    Object sender,
    SelectionChangedEventArgs e
)

SelectionChangedEventHandler デリゲートの第 2 パラメータは、イベント発生時に選択されている項目の情報などを格納する System.Windows.Controls.ScrollChangedEventArgs クラスのオブジェクトです。

System.Windows.Controls.ScrollChangedEventArgs クラス
System.Object 
   System.EventArgs 
     System.Windows.RoutedEventArgs 
      System.Windows.Controls.SelectionChangedEventArgs
public class SelectionChangedEventArgs : RoutedEventArgs

このクラスのオブジェクトは、イベント発生時の選択項目のリストを返す AddedItems プロパティを提供しています。

SelectionChangedEventArgs クラス AddedItems プロパティ
public IList AddedItems { get; }

戻り値の IList オブジェクトは、イベントの対象となっている選択コントロールが現在選択している項目の配列です。通常、イベントハンドラから直接 ListBox オブジェクトを参照できる場合は使う必要は無いでしょう。ListBox から直接選択項目を取得することができます。  

コード3
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 実行結果

コード3は、リストボックスの項目を選択すると、上部のラベルに表示されるテキストが変更するというプログラムです。リストボックスの項目を選択すると SelectionChanged イベントが発生します。このイベントが発生すると、登録されている listBoxSelectionChanged() メソッドが呼び出され、現在リストボックスに選択されている項目を使ってラベルの文字列を変更します。

6.6.3 コンボボックス

コンボボックスは、リストボックスと同様に Selector クラスを継承する任意の数の項目を表示し、選択することができるコントロールです。このコントロールを表示するには System.Windows.Controls.ComboBox クラスを使います。

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

このクラスのコンストラクタは、パラメータを受け取りません。

ComboBox クラスのコンストラクタ
public ComboBox ()

項目の追加や、選択されている項目の制御については ItemsControl クラスや Selector クラスのプロパティなどを利用するので ListBox クラスと同じです。

コード4
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 実行結果

コード4は、コード1とほとんど同じコードです。このプログラムでは、ListBox の代わりに ComboBox クラスのインスタンスを生成し、項目となるオブジェクトを追加しています。リストボックスとは異なり、コンボボックスはドロップダウンリストを表示して項目を選択します。

6.6.4 タブコントロール

タブコントロールは、タブを選択することで画面に表示するコンテンツを切り替えるコントロールです。パネルではありませんが、性質的にはパネルのように他のコントロールの親として機能します。多くのコントロールを配置しなければならないより複雑なアプリケーションには必須のコントロールです。

タブコントロールを表示するには System.Windows.Controls.TabControl クラスを使います。TabControl クラスは、任意の数のタブを保有し、選択されているタブに応じて表示するコンテンツを決定するという動作を行うため Selector を継承しています。表示される個々のタブは ItemsControl における項目に該当し、項目は選択することができます。

System.Windows.Controls.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.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 クラスのコンストラクタは、パラメータを受け取りません。

TabControl クラスのコンストラクタ
public TabControl ()

基本的な利用方法はリストボックスと同じです。Items プロパティからタブとなる項目を自由に追加したり、削除することができます。

コード5
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 実行結果

コード5は、文字列型のオブジェクトを 3 つ、TabControl オブジェクトの項目として追加しています。実行結果を見ると、確かにオブジェクトの文字列表現がタブ上にテキストとして表示されていることが確認できます。しかし、タブに表示されているテキストは、そのままタブのコンテンツとしても利用されています。多くの場合、これは望まれない動作でしょう。

通常、タブはタブが選択されたときに表示するコントロールやフォームを説明するためのテキストを表示します。そのため、タブに表示するオブジェクトと、タブが選択されたときに、タブコントロール全体に表示するコンテンツのオブジェクトを分離する必要があります。

タブコントロールの項目に、より詳細に設定を行いたい場合は System.Windows.Controls.TabItem クラスを用います。他のオブジェクトとは異なり、TabControl クラスの項目として TabItem オブジェクトを追加すると、TabControl はタブ上に表示するべきオブジェクトと、コンテンツに表示するオブジェクトを個別に認識できます。

System.Windows.Controls.TabItem クラス
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 クラスのコンストラクタは、パラメータを受け取りません。

TabItem クラスのコンストラクタ
public TabItem ()

この TabItem が項目としてタブ上に表示するオブジェクトは Header プロパティに設定してください。

HeaderedContentControl クラス Header プロパティ
[LocalizabilityAttribute(LocalizationCategory.Label)] 
[BindableAttribute(true)] 
public Object Header { get; set; }

Header プロパティに設定されているオブジェクトは、タブコントロールのタブに表示するオブジェクトとして利用されます。この項目が選択されたときに、タブコントロールのコンテンツとして表示するオブジェクトは TabItem オブジェクトの Content プロパティに設定します。

コード6
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 実行結果

コード6を実行すると「楕円形」というテキストと、黒い長方形を描画する 2 つのタブが表示されます。「楕円形」 というテキストを表示するタブは、Header プロパティに文字列を、Content プロパティに青い楕円形を設定している TabItem オブジェクトによるものです。Header プロパティに設定したオブジェクトがタブ上に表示され、Content プロパティに設定したオブジェクトが、タブ選択時にコンテンツとして表示されていることが確認できます。