WPFとSilverlightは一体何が違うのか? 2つをまとめて習得する方法とは? 1粒で2度おいしい最新UIフレームワークの習得術。
powered by Insider.NET
「WPFとSilverlightは一体何が違うのか?」
このような質問を受けるならば、筆者は誤解を恐れずに「WPFとSilverlightは同じである」といいたい。
プラットフォーム全体としてWPFとSilverlightを比較した場合、Windows OS専用とマルチプラットフォーム、デスクトップ・アプリケーションとWebアプリケーションといった具合に、その性質は大きく異なっている。しかしながら、UIフレームワークというスコープで見た場合、2つは“同じ”なのである。
それでもさすがにまったく同じというわけにはいかない。Silverlightはランタイムのサイズを4MBytes台に抑えるという至上命令があったため、WPFと比べると機能が削られているという違いが存在する。しかしながら、どちらも共通のデザインの基に作られた、マイクロソフトによる最も新しく最も洗練されたUIフレームワークなのである。
WPFとSilverlightが“同じ”であることは、開発者にとっては大きなメリットだ。1つのUIフレームワークを学べば、WPFとSilverlightの2つのテクノロジを会得したことになるのだから、学ばない手はない。
しかしながら、新しいテクノロジを学ぶ際に必ず付いて回るのは「まず何から手を付けたらよいのか?」という問題ではないだろうか。本連載では、筆者が「WPF/SilverlightのUIフレームワークに入門するなら、まずはこれから」と考える内容を3回にわたってお送りする予定だ。
なお、本連載ではWPFとSilverlight共通のUIフレームワークを「WPF UIフレームワーク」と表記する。
WPF UIフレームワークを見ていくと、多くの部分でXAMLありきの設計となっていることに気付くはずだ。しかしながら、WPF UIフレームワークを理解するうえでXAMLという言語そのものに対する知識はあまり重要ではない。
XAMLに関する詳細な情報は「連載:XAMLの基礎知識」を読んでいただくことにして、ここではWPF UIフレームワーク入門に際して最低限必要なXAMLの言語構文を説明する。
●インスタンス化とプロパティ値の設定
XAML(Extensible Application Markup Language)は、.NETにおけるクラスのインスタンス化を宣言的に記述するXMLベースの言語である。基本的には、要素でクラスのインスタンスを、属性でプロパティ値を記述する。従って、下記のXAMLとC#/VB(Visual Basic)のコードは同じ意味を表すことになる。
<TextBox Text="あいうえお"/>
TextBox TextBox1 = new TextBox();
TextBox1.Text = "あいうえお";
Dim TextBox1 As New TextBox()
TextBox1.Text = "あいうえお"
【コラム】WPF UIフレームワークにおけるクラスのコンストラクタ
XAMLではコンストラクタに引数を渡す方法が用意されていない。そのため、WPF UIフレームワークのクラスのほとんどは、XAMLで使用されることを考慮して、パラメータなしのコンストラクタを持っている。
ただし、上記の例でも、C#とVBではクラスのインスタンス化の際にオブジェクト名が必要であるのに対し、XAMLでは必要ないといった違いが存在する。
XAMLとC#/VBの根本的な違いとして、XAMLはメソッドを実行できず、フロー(=順序を伴う処理)を記述できないことが挙げられる。一方、XAMLではプロパティ値を文字列で設定するという性質上、値の自動変換が行われるという特徴がある。
先ほどと同様、下記のXAMLとC#/VBのコードは同じ意味を表す。
<Border Background="#FFF1F4FB"/>
Border Border1 = new Border();
Border1.Background = new SolidColorBrush(
Color.FromArgb(255, 241, 244, 251));
Dim Border1 As New Border()
Border1.Background = New SolidColorBrush( _
Color.FromArgb(255, 241, 244, 251))
当然ながら、文字列からの変換だけで、すべてのプロパティ値をサポートすることはできない。文字列で表現できないプロパティ値は、属性ではなく子要素として記述する方法を取る。
例えば、画像をブラシとして使用するImageBrushを利用する場合、下記のようにBackgroundプロパティを<Border>要素の子要素として宣言する。
<Border>
<Border.Background>
<ImageBrush ImageSource="grapecity.jpg"/>
</Border.Background>
</Border>
Border Border1 = new Border();
ImageBrush ImageBrush1 = new ImageBrush();
ImageBrush1.ImageSource =
new BitmapImage(new Uri(@"grapecity.jpg"));
Border1.Background = ImageBrush1;
Dim Border1 As New Border()
Dim ImageBrush1 As New ImageBrush()
ImageBrush1.ImageSource = _
New BitmapImage(New Uri("grapecity.jpg"))
Border1.Background = ImageBrush1
上記のXAMLコードのように、子要素としてプロパティ値の設定を行う記述方法を「プロパティ要素構文」、要素の属性としてプロパティ値の設定を行う記述方法を「プロパティ属性構文」という。
●イベント・ハンドラの登録
属性構文はイベント・ハンドラを登録する役割も持っている。下記のXAMLとC#/VBのコードはすべて同じ意味を表す。
<Button Click="Button_Click"/>
Button Button1 = new Button();
Button1.Click += new RoutedEventHandler(Button_Click);
Dim Button1 As New Button()
AddHandler Button1.Click, AddressOf Button_Click
●名前空間
WPFおよびSilverlightで使用されるXAMLコードでは、たいていの場合、下記のような記述が最上位の要素に含まれている。
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
XMLでは、要素名や属性名の衝突を避けるために、各要素が属する名前空間(=XML名前空間)を「xmlns」という属性を使って指定できる。XAMLでは、このxmlns属性を使って各要素のプレフィックスに「WPF名前空間」と「XAML名前空間」の2つのXML名前空間を割り当てる。これは、C#におけるusingディレクティブ、VBにおけるImportsステートメントを思い浮かべると理解しやすいだろう。
1行目の宣言では、WPF UIフレームワークの「WPF名前空間」を既定の名前空間(プレフィックスなし)として割り当てている。「http://schemas.microsoft.com/winfx/2006/xaml/presentation」という文字列で指定されるWPF名前空間と、WPF UIフレームワークで利用される一般的なCLR名前空間(=.NETクラス・ライブラリ内の名前空間)は、そのクラス・ライブラリにおいてXmlnsDefinitionというアセンブリ属性で結ばれている。
例えばWPFの「PresentationFramework.dll」のアセンブリ属性をツールなどで見てみると、XmlnsDefinition属性の宣言により、上記URIのWPF名前空間に、System.Windows.ControlsやSystem.Windows.Dataなど複数のCLR名前空間がマッピングされていることを確認できる。これにより、System.Windows.ControlsやSystem.Windows.DataといったCLR名前空間に属するクラスを、そのまま要素として宣言できるのである。
2行目の宣言では、「XAML名前空間」を「x:」プレフィックス付きのXML名前空間として割り当てている。これにより、「x:」という文字列を要素名/属性名の前に付け加えることで、XAML名前空間に属するその要素/属性にアクセスできる。
このXAML名前空間には、WPF UIフレームワークには直接依存しない共通的な「XAMLの言語機能」が宣言されている(※WPF UIフレームワークはXAMLを言語として使用する1つの実装形態にすぎないが、複数の実装があるとして、それらの実装間で共通的にアクセス可能にすべき言語機能はこのXAML名前空間にまとめられている。具体的には、オブジェクトを一意に識別するための「x:Name属性」や、クラスを複数のファイルに分割する、つまり部分クラスのための「x:Class属性」などは、XAML名前空間で宣言されている)。XAML名前空間は、CLR名前空間のSystem.Windows.Markupに該当するが、XAMLの言語機能は必ずしもクラスや構造体とマッピングしているわけではない。
前述のXmlnsDefinition属性を使ってXML名前空間のURIにCLR名前空間をマッピングする方法のほかに、XML名前空間のURIに直接アセンブリのCLR名前空間を指定して両者を結び付ける方法も用意されている。ただし、この方法は1つのプレフィックスに対して1つの名前空間しか割り当てることができない。この方法では、下記の定義済みトークンを使用する。
トークン | 区切り文字 | 値 |
---|---|---|
clr-namespace | :(コロン) | インポートするアセンブリ内のCLR名前空間 |
assembly | =(等号) | アセンブリの名前 |
定義済みトークン |
例えば、ClassLibrary1.dllというアセンブリのClassLibrary1というCLR名前空間を、「my:」プレフィックス付きのXML名前空間として割り当てる宣言は下記のようになる。
xmlns:my="clr-namespace:ClassLibrary1;assembly=ClassLibrary1"
これでClass1というクラスがClassLibrary1名前空間にあった場合、下記のようにインスタンス化を宣言できる。
<my:Class1/>
ほかにもXAMLにおける暗黙のルールや振る舞いはいくつか存在するが、本稿での説明はここまでとする。
続いて、WPF UIフレームワークで最初に押さえておくべきレイアウト(Panel)について説明しよう。
Copyright© Digital Advantage Corp. All Rights Reserved.