WisdomSoft - for your serial experiences.

2.7 統合されたUI要素

WPF で描画されるすべての図形やコントロールは UIElement クラスを基底としています。UIElement クラスで抽象化された描画可能な要素は、組み合わせに制限が少なく自由な表現力を生み出します。

2.7.1 描画要素

これまでの Windows アプリケーション開発では、高度な描画機能を実装しようと考えた場合は、必ず同じ障害にたどり着きました。それは、デバイスコンテキストとコントロールがまったく異なるオブジェクトとして扱われていたことです。

古くは Win32 API における HWND 型のハンドルと HDC 型のハンドルにまでさかのぼります。.NET Framework 2.0 までの Windows Forms アプリケーションもまた、古い Win32 API の HWDN や HDC をラッピングしているだけの API だったため、設計上これらの問題は残されたままでした。

コントロールと描画処理はまったく異なる次元であったために、コントロールと描画のプロセスは、それぞれ異なるロジックで管理しなければなりませんでした。しかし、WPF では、コントロールも描画オブジェクトも、全ては System.Windows.UIElement クラスに統合されています。

System.Windows.UIElement クラス
System.Object 
   System.Windows.Threading.DispatcherObject 
     System.Windows.DependencyObject 
       System.Windows.Media.Visual 
        System.Windows.UIElement
public class UIElement : Visual, IAnimatable, IInputElement

コントロールであれ、図形であれ、最終的に視覚的な形でプレゼンテーションされることを目的とするオブジェクトは、UIElement クラスをルートクラスとして派生しています。よって、あらゆる視覚的なオブジェクトを UIElement 型として統合して操作することができます。

ContentControl クラスの Content プロパティには、文字列以外にこの UIElement 型のオブジェクトを設定することができました。よって、あらゆるプレゼンテーション可能なオブジェクトはコントロールのコンテンツとして視覚化することができます。ラベル、ボタン、チェックボックスなどは、任意の UIElement を表示することができますし、同時にそれ自身もまた UIElement であることから、別のコントロールのコンテンツになることもできます。

さらに、WPF では描画要素も全て UIElement として統合されています。矩形、楕円、線などは、直接コントロール上に描画されるのではなく、これらもまた UIElement オブジェクトとしてインスタンス化し、コンテンツとして設定することができます。これは、コントロールや図形などの描画要素を自由に組み合わせることができることを意味しています。

例えば、ゲームアプリケーションのようなものを開発しようとした場合、従来の API では、様々な描画要素を抽象するレイヤを表すクラスを作成し、レイヤの重ね合わせを管理しながら、独特な形のメッセージウィンドウや、キャラクターアイコン、感情アイコン、背景、演出などを組み合わせるという方法がありました。

開発シナリオにもよりますが、恐らく WPF では、そうした高度な描画の設計を最初から行う必要はないでしょう。演出や画面管理のロジックは自分で構築する必要がありますが、基本的な設計と描画関連のオブジェクトは WPF 基底のクラスを流用し、そのまま統合することができるため、より容易に高度なゲームアプリケーションを開発することができるはずです。

例えば、次のようなコードを実行してみましょう。各種コントロールや図形要素に関しては今後解説するので、この場では WPF を利用することでこうしたことが実現できるということだけを感じ取ってください。この場では、コードの内容を深く理解する必要はありません。

コード1
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Shapes;

class Test {
	[STAThread]
	public static void Main() {
		CheckBox checkBox = new CheckBox();
		checkBox.Content = "巻きますか?";
		checkBox.FontSize = 20;

		Ellipse ellipse = new Ellipse();
		ellipse.Width = 200;
		ellipse.Height = 100;
		ellipse.Fill = Brushes.Red;

		Label label = new Label();
		label.FontSize = 30;
		label.Content = "I'm never junk !";

		StackPanel panel = new StackPanel();
		panel.Children.Add(checkBox);
		panel.Children.Add(ellipse);
		panel.Children.Add(label);

		Button button = new Button();
		button.Content = panel;

		Canvas canvas = new Canvas();
		canvas.Children.Add(button);

		Window wnd = new Window();
		wnd.Content = canvas;

		Application app = new Application();
		app.Run(wnd);
	}
}
実行結果
コード1 実行結果

コード1を実行すると、ウィンドウ上にボタンが 1 つ表示されます。このボタンは、内部のコンテンツにチェックボックス、赤い楕円、ラベルが含まれています。つまり、ボタンの中にさらに異なるコンテンツが含まれています。楕円のような図形要素とチェックボックスのようなコントロールも、すべて UIElement をルートとしているため、問題なくコンテンツとなることができます。

もちろん、レイアウトも自由です。文字列、イメージ、図形、コントロールなどを自由に組み合わせたり、重ね合わせることができ、従来の API のようなレイアウト上の制限というものがほとんどありません。こうした高い柔軟性は、全ての描画要素が UIElement に統合されているためです。