はじめに
Windows Vistaに合わせて導入された.NET Framework 3.0の新コンポーネントであるWPF/WCF/WFは、より豊かなUIや、通信機能の標準化、汎用的なワークフローのサポートなど、さまざまな機能を提供しました。しかし、Visual Studio 2005でのサポートは限定的なものであり、これらのフレームワークをより生かせる開発環境の登場が待望されていました。
Visual Studio 2008では、ついに.NET Framework 3.5がサポートされ、WPF/WCF/WFについても、統合開発環境を活かしたサポートが行われるようになりました。
Visual Studio 2008入門シリーズでは、本記事から数回分を用い、Visual Studio 2008でのWPF/WCF/WFサポートについて解説していきます。
対象読者
- VS 2008に興味がある方
- WPF/XAMLに興味がある方(&Visual Studioでのサポートを待望していた方)
必要な環境
シリーズ第1回を参考に、Visual Studio 2008のインストールを行ってください。
Visual Studio 2008とWPF/WCF/WF
Visual Studio 2008は.NET Framework 3.5をサポートする統合開発環境です。Visual Studio 2005が.NET Framework 2.0をサポートしていた時点から、.NET Frameworkは2回のメジャーバージョンアップを経ています。
.NET Framework 3.5の新機能であるLINQについては第3回で、ASP.NET AJAXについては第4回で扱いましたので、ここでは一つ戻って、.NET Framework 3.0で導入されたフレームワーク群について少し見ておきましょう。
.NET Framework 3.0はWindows Vistaと同時期にリリースされ、Vistaで追加されたさまざまな機能の土台となっています。
その実体は、.NET Framework 2.0をベースとし、WPF(Windows Presentation Foundation)、WCF(Windows Communication Foundation)、WF(Windows Workflow Foundation)、WCS(Windows CardSpace)を追加したものです。
それぞれのコンポーネントは、次のような機能を持っています。
コンポーネント名 | 略称 | 機能 |
Windows Presentation Foundation | WPF | 3DグラフィックをサポートしたUIフレームワーク |
Windows Communication Foundation | WCF | さまざまな通信方式を統一的に扱うための通信フレームワーク |
Windows Workflow Foundation | WF | Windows向けの共通ワークフローフレームワーク |
Windows CardSpace | WCS | ユーザーのデジタルIDを統一的に管理するためのフレームワーク |
.NET Framework 3.0はWindows Vistaに含まれているほか、Windows XP / Windows Server 2003にもランタイムが提供され、.NET Framework開発の新たな標準となりました。
しかし、開発環境という面では、前述の通りVisual Studio 2005は.NET Framework 2.0対応で、.NET Framework 3.0については、拡張ソフトウェアであるVisual Studio 2005 Extensions for WPF/WCF/WFの追加によって対応する、という状況でした。
なお、Visual Studio 2005 ExtensionsによるWPF/WCF/WF開発については、以前の記事を参照してください。
Visual Studio 2008の登場により、ついにWPF/WCF/WFを標準サポートした開発環境を利用することができます。
Visual Studio 2008では、.NET Framework 3.0を抜かして一挙に.NET Framework 3.5がサポートされました。.NET Framework 3.5では、前述のLINQ / ASP.NET AJAXといった主要機能に加え、次のようにWPF/WCF/WFについても機能が追加されています。
コンポーネント | 機能説明 |
WPF | XAMLブラウザアプリケーション(XBAP)のFirefoxサポート |
3Dオブジェクトでの入力/フォーカス/イベントのサポート(UIElement3D/ContainerUIElement3D/ModelUIElement3D) | |
3Dオブジェクトへの2Dオブジェクトの配置(Viewport2DVisual3D) | |
データバインディング機能でのLINQのサポート | |
WCF | WCFによるWebサービス開発が可能に(WCF Webプログラミングモデル) |
Atom 1.0 / RSS 2.0によるサービスの配信機能の追加 | |
JSONのサポートにより、ASP.NET AJAXとの連係が容易に | |
WS-I(Web Services Interoperability)サポートの強化 | |
WCF/WF | WCF/WFを統合した機能が追加され、WCFサービス内でWFを使用したり、WFワークフローをWCFサービスとして公開可能に |
WPFについて
今回は、これらWPF/WCF/WFフレームワークの中からWPFについて取り上げます。
「WPF」は.NET Framework 3.0で導入されたユーザーインターフェイスフレームワークです。
これまでWindowsのグラフィックス機能を提供してきたGDIが基本的に2D描画機能のみだったのに対し、WPFは3Dグラフィックスを含め、さまざまなグラフィックス機能を扱うことができるようになっています。
WPFでは、XAML(Extensible Application Markup Language:ザメル/ザムル)と呼ばれるXMLをベースとした言語を使ってユーザーインターフェイスを記述することができます。また、WPFは高度な3Dグラフィックス機能を持つGPUを生かした描画を行うことができます。これまでゲームなどにしかそのポテンシャルを生かすことができなかったGPUの膨大な計算能力を用い、豊かなUIを実現することができます。
XAMLとは
「XAML」とは、ユーザーインターフェイスをXML形式で表現したものです。
.NET Framework 2.0までで使用していたWindows Formsでは、ユーザーインターフェイスがコードの固まりとして表現されていましたが、これはコントロール間の親子関係が掴みづらく、またデザインを直接編集するのが難しい方式でした。
XAMLでは、ユーザーインターフェイスに使用するコントロールをXMLの要素で、コントロールのプロパティをXMLの属性で表現し、コントロールの入れ子関係などもXMLの要素の親子関係で自然に表現することができます。
例えば、以下はウィンドウ上にテキストボックスとボタンを配置したXAMLコードです。
TextBox
要素、Button
要素とその属性がコントロールとプロパティに対応しています。
<Window x:Class="WpfTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WpfTest" Height="600" Width="400"
> <Grid> <TextBox Height="20" Name="textBox1"></TextBox> <Button Height="30" Name="button1" Width="120">Button</Button> </Grid> </Window>
例えば、矩形を特定の画像で塗りつぶす場合、矩形を表すRectangleコントロールの塗りつぶし方法を示す
fill
プロパティに、ImageBrush
オブジェクトを設定する必要があります。これは次のようなXAMLコードで表すことができます。<Rectangle Width="100" Height="100"
> <Rectangle.Fill> <ImageBrush ImageSource="fill.png"/> </Rectangle.Fill> </Rectangle>
Rectangle.Fill
要素がRectangleコントロールのFill
プロパティを表すプロパティ要素です。XAMLには、Windows Formsと同様のユーザーインターフェイスの静的な構造を記述する機能だけでなく、タイムラインに沿ったアニメーション効果や、さまざまなグラフィックス機能が収められています。
XAMLはXML形式であるため、Visual Studio以外のさまざまなツールでサポートされていくものと期待されています。ソフトウェア開発の現場において、デザイナがデザインに特化したツールでXAMLを出力し、それを開発者がVisual Studio 2008で開いて実際のコードを記述していく、といった作業分担も可能となっていくでしょう。
例えば、Microsoft Expression Blendは、XAMLをサポートしたデザインツールです。Expression BlendはVisual Studioと同じプロジェクトファイルを扱うことができますので、Expression BlendとVisual Studioにより、デザイナと開発者が協同してアプリケーション開発に取り組む体制を整えることができます。
WPFのアプリケーション形態
WPFは以下の2種類の形態で使用することができます。
- WPF アプリケーション
- WPF ブラウザ アプリケーション
SilverlightはWPF ブラウザ アプリケーションとは異なり、クロスブラウザ・クロスプラットフォームを実現したフレームワークです。専用のプラグインをインストールする必要があるものの、Windows(Internet Explorer / Mozilla Firefox)/Machintosh(Safari / Mozilla Firefox)がサポートされています。
以前はWPF/Eと呼ばれており、XAMLを使用するという点ではWPFに類似した技術ですが、WPFには含まれていません。
Silverlightを含め、これらのアプリケーションの特徴、用途についてまとめると、次のようになります。
あくまでもWindows OSと.NET Frameworkの組み合わせの上で動作するWPFと、クロスブラウザ・クロスプラットフォームを目指すSilverlightの位置づけの違いに注目してください。
本記事ではVisual Studio 2008によるWPF開発の流れを説明していきます。
Visual Studio 2008のWPFサポートは、CTP版のVisual Studio 2005 Extensions for WPFから改善された部分も多く、今後のWPFの普及に向けての活用が期待されます。
サンプル1~まずはHelloWorld
さっそくVisual Studio 2008でWPFを使ったアプリケーションを作成しましょう。
[新しいプロジェクト]画面で[Visual C#]-[Windows]カテゴリから[WPF アプリケーション]を選択します。
新しいプロジェクトが作成され、次のような画面となります。
画面左上がXAMLのフォームデザイナ、左下がXAMLコード、右下がXAMLのプロパティとなっています。フォームデザイナとXAMLコードが分割ビューで表示されていますが、これらは相互に同期しており、フォームデザイナに配置したXAMLコントロールはすぐにXAMLコード側に挿入され、XAMLコード側を変更した場合はフォームデザイナがそれに合わせて再描画されます。もちろん、プロパティペインとXAMLコードも相互に同期しています。
では、文字を表示するためのLabelコントロールを配置しましょう。左側のツールボックス内にXAMLコントロールが一覧表示されています。
ここからLabelをクリックしてドラッグし、フォームデザイナ上にドロップしてください。右下のプロパティウィンドウで表示文字列を表すContent
プロパティを"Hello WPF World!"とします。
この時点でのXAMLコードは次のようになっています。
<Window x:Class="WpfTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"> <Grid> <Label Height="28" Margin="66,89,92,0" Name="label1"
VerticalAlignment="Top">Hello WPF World !</Label> </Grid> </Window>
Windowコントロール-Gridコントロール-Labelコントロールの親子関係がXMLとして表現されていることに注目してください(なお、Gridコントロールはコントロールを並べるため、最初から配置されています)。
Content
プロパティを設定したのに、Contentという名前の属性ではなく、Label要素の子に文字列が設定されています。これはXAMLのコンテンツ要素と呼ばれる機能で、コントロールの特定のプロパティについて、プロパティ名を省略し、子要素として記述することができる、というものです。
もちろん、本来の属性を使用して
<Label Height="28" Margin="66,89,92,0" Name="label1"
VerticalAlignment="Top" Content="Hello WPF World !"></Label>
それでは以上のコードを実行してみましょう。
XAMLで記述したWPF アプリケーションの実行を確認できたでしょうか。
これまでのWindows Formsと同様にGUIでコントロールを配置し、プロパティを設定していくこともできますし、直接XAMLコードを編集することもできますので、いろいろ試してみてください。
ツールボックスに表示されないXAMLコントロール
Visual Studio 2008のツールボックスに表示されていないXAMLコントロールも多数存在します。しかし、そうしたコントロールがVisual Studio 2008でサポートされていないというわけではなく、XAMLコードに直接入力することで、同期してフォームデザイナにも表示されます。
例えば、グラデーションによる塗り潰しを行うLinearGradientBrushコントロールはツールボックスに表示されていませんが、次のようにXAMLコード内に記述することで、グラデーション塗り潰しされた矩形を表示することができます。
<Rectangle Width="100" HorizontalAlignment="Right" Margin="0,58,11,104"> <Rectangle.Fill> <LinearGradientBrush StartPoint="0.5, 0" EndPoint="0.5, 1"> <GradientStop Offset="0.0" Color="White" /> <GradientStop Offset="1.0" Color="Blue" /> </LinearGradientBrush> </Rectangle.Fill> </Rectangle>
サンプル2~イベントのハンドリング
では、続いてコントロールに対するイベントのハンドリングを行ってみましょう。
ボタンコントロールを配置し、ダブルクリックすると、イベントハンドラ記述のためのコードウィンドウへと切り替わります。コードウィンドウに次のように、ラベルに文字列を表示するコードを入力します。
private void button1_Click(object sender, RoutedEventArgs e) { label1.Content = "ボタンが押されました"; }
これまでのWindows Formsの場合と同じく、XAMLコード内に配置されている要素は、ソースコードからオブジェクトとしてアクセスすることができます。ラベルの文字列はサンプル1で見たとおり、Content
プロパティで設定します。
このときのXAMLコードは次のようになっています。
<Grid> <Label Height="28" Margin="66,89,92,0" Name="label1"
VerticalAlignment="Top" Content="Hello WPF World !"></Label> <Button Height="23" Margin="94,0,109,63" Name="button1"
VerticalAlignment="Bottom" Click="button1_Click"> Button</Button> </Grid>
Button要素のClick
属性に、イベントハンドラであるbutton1_Click
メソッドが指定されていることが分かります。
XAMLでは、イベント名の属性を作成し、イベントハンドラとなるメソッド名を指定することで、イベントのバインドが行われます。
[F5]キーを押してサンプルを実行し、イベントハンドラがきちんと動作していることを確認しましょう。
ボタンをクリックするとラベルの内容が変化します。
コードビハインド
イベントハンドラのコードは、C#の場合はXAMLファイル名の末尾に.csを付加したファイルに記述します(VBの場合は末尾に.vbを付加したファイル)。
このC#(あるいはVB)のファイルをコードビハインド ファイルと呼びます。このプロジェクトの場合は「Window1.xaml.cs」がコードビハインド ファイルです。
XAML側で定義したコントロールはコードビハインド側のコードから、同じクラスのメンバとしてアクセスすることができます。これはコードビハインドのコードが部分(partial)
クラスでXAMLコードと同じクラスとして定義されているためです。
実際には、コードビハインド ファイルの他に、XAMLのコントロールをメンバとして定義するファイルが内部的に自動生成されています。
コードウィンドウの右上のメンバ一覧から、label1などのXAMLのコントロールを選択することで、自動生成されたコードを確認することができます。
public partial class Window1 : System.Windows.Window, System.Windows.Markup.IComponentConnector { #line 6 "..\..\Window1.xaml" internal System.Windows.Controls.Label label1; #line default #line hidden #line 7 "..\..\Window1.xaml" internal System.Windows.Controls.Button button1;
XAMLで定義されたlabel1やbutton1といったコントロールが、部分クラス内にメンバとして定義されていることが確認できます。これによって、イベントハンドラ内でコントロールへのアクセスが可能となっています。
なお、このファイルの先頭のコメントにも記されていますが、誤動作を避けるため、自動生成されたファイルの内容は編集しないようにしましょう。
WPFで採用しているユーザーインターフェイスをXML形式のファイルで記述し、イベントハンドラをコードビハインド ファイルに記述する、という方式ですが、実は、ASP.NETで以前から類似の方式(.aspxと.aspx.cs/.vbの関係)が用いられています。ASP.NET経験者には理解しやすい構造と言えるでしょう。従って、デザインとプログラムの分離という面でもASP.NETと同様のメリットを享受することになります。
サンプル3~ダブルクリック以外でのイベントのバインド
さて、XAMLコントロールのプロパティウィンドウを見ると、これまでのWindows Formsのコントロールのプロパティウィンドウとはちょっと異なることに気付きます。
全般的な雰囲気が違うのはもちろんですが、特にWindows Formsコントロールで表示されている、イベントを扱うための雷アイコンが、XAMLコントロールでは表示されていないことに注目してください。
先ほどのサンプルでは、ボタンをダブルクリックした場合には自動的にClickイベントのバインド行われました。Visual Studio 2008では、これまでのバージョンと同様に、コントロールをダブルクリックした場合には、各コントロールの代表的なイベントについてのバインドが行われます。
では、他のイベントについてはサポートされていないのか? と言うと、そういうわけではありません。
ここでは、ダブルクリックでバインドされないイベントについて、Visual Studio 2008でどう記述するかを確認しましょう。
先ほど見たとおりXAMLでは、イベントに対応する属性を作成し、イベントハンドラのメソッド名を記述することでイベントのバインドを行うことができます。しかし、自分でこうしたコードをすべて記述するのはミスしやすいですし、定型の内容を毎回手動で入力するというのは無駄に感じます。
Visual Studio 2008では、ダブルクリックでバインドされないイベントについても、IntelliSenseを使用することで、簡単にイベントハンドラの作成を行うことができます。
先ほどのサンプルで、ボタン上にマウスカーソルが入った場合(MouseMoveイベント)と、マウスカーソルが出て行った場合(MouseLeaveイベント)の2イベントをハンドリングしてみましょう。
XAMLコードのButton
要素の開始タグ内でスペースキーを押すと、IntelliSenseが働き、そこに記述可能な属性の一覧が表示されます。ここで、一覧からMouseMoveイベントを選択しましょう。
イベントを選択すると、新しいイベントハンドラを作成するかどうか、メッセージが表示されますので、そのまま[Enter]キーを押します。
新しいイベントハンドラが作成され、属性にセットされます。
<Button Height="23" Margin="94,0,109,63" Name="button1"
VerticalAlignment="Bottom" Click="button1_Click"
MouseMove="button1_MouseMove">Button</Button>
MouseMove
属性の上で右クリックし、メニューから[イベント ハンドラへ移動]を選択すると、コードビハインド ファイルに作成されたイベントハンドラに移動することができます。
同様に、MouseLeaveイベントも作成しましょう。今回はイベントハンドラとして、新たに作成するか、既にあるbutton1_MouseMove
メソッドをバインドするかを尋ねてきますので、<新しいイベント ハンドラ>を選択しましょう。
MouseLeave
属性の上で右クリックし、メニューから[イベント ハンドラへ移動]を選択し、次のようにイベントハンドラを記述しましょう。
private void button1_MouseMove(object sender, MouseEventArgs e) { label1.Content = "マウスカーソル進入"; } private void button1_MouseLeave(object sender, MouseEventArgs e) { label1.Content = "マウスカーソル通過"; }
この状態でのXAMLコードは次のとおりです。
<Button Height="23" Margin="94,0,109,63" Name="button1"
VerticalAlignment="Bottom" Click="button1_Click"
MouseMove="button1_MouseMove"
MouseLeave="button1_MouseLeave">Button</Button>
[F5]キーを押して実行すると、マウスカーソルがボタン内に入った場合、外に出た場合でラベルの文字列が変化することを確認できます。
このように、ダブルクリックでバインドされないイベントについても、IntelliSenseのサポートにより、簡単にバインドを行うことができます。
以上で作成したサンプルは、サンプルファイルのWpfTestプロジェクト内に含まれています。
サンプル4~XAMLのポテンシャルを垣間見る
ここまで、Visual Studio 2008でのWPFサポート機能を用いて、いくつかのサンプルを見てきました。Windows Formsと同じ機能がWPFでもサポートされており、XAMLという新しい概念が追加されたからといって、アプリケーション実装の流れが大きく異なるわけではないことが分かったかと思います。
しかし、XAMLならではの機能、という面では、これまでのサンプルではほとんど伝わってこなかった、というのも実感でしょう。
次のサンプルは、Visual Studio 2008のツールボックスではサポートされていないXAMLコントロールを使い、ボタンやチェックボックスといったごく普通の2Dのコントロールを3D空間上に表示する、というものです。この3Dオブジェクトへの2Dオブジェクトの配置は、前述の通り.NET Framework 3.5の新機能で、Viewport2DVisual3Dを使って実現しています。
また、ボタンの"中に"チェックボックスを配置するという荒技も行っています。
このサンプルはサンプルファイルの3DUIプロジェクトに含まれています。詳細はソースコードをご覧ください。
このサンプルでは、Viewport3Dコントロールを用いて3D表示を行っています。これはVisual Studio 2008で直接サポートされていないコントロールですので、詳細は省略します。
Viewport3Dコントロール内にViewport2DVisual3Dコントロールを使ってボタンを配置し、その配下にチェックボックスを配置しています。この部分のXAMLコードを引用します。
<Button Width="150" Height="50" Background="Aqua" Click="Button_Click"> <Button.Content> <CheckBox Name="angleCheckbox">Right/Left angle</CheckBox> </Button.Content> </Button>
コードを見ると分かるとおり、ButtonコントロールのContent
プロパティにCheckBoxコントロールを定義しています。これは通常のWindows Formsではあり得ない親子関係ですが、XAMLではこうした無茶な定義を行ってもきちんと描画が行われます。
今回はこのボタンの押下時に、チェックボックスがチェックされているかどうかに合わせて、3D表示の角度を変えるようなイベントハンドラを記述してみました。
サンプルを実行し、チェックボックスをチェックすると、次のように表示角度が入れ替わります。
このサンプルですが、実用性はともかくとして、3Dの制御やコントロールの入れ子といった、これまでのWindows Formsでは決して実現できなかった機能を、50行以下のXAMLコードと、数行のイベントハンドラだけで実装していることに注目してください。画面キャプチャでは分かりづらいので、ぜひサンプルを実行してみてください。3Dベースなのに、普通の2Dのコントロールが…、しかもボタンの中にチェックボックスが…と何とも不思議な気持ちになること請け合いです。
近年、Webデザインの分野を中心に、人間がコンピュータと接するためのUIは、より洗練されたものへと進化していきました。そうした流れがある中で、ボタンなどの標準的なコントロールについては、ほとんどデザイン的な改良がなく、OSお仕着せのスタイルがそのまま使われてきました。
3Dグラフィックスのサポートと、さらなるUI表現の追求を可能とするXAMLのポテンシャルは、これまでになかった種類のアプリケーションを実現する助けとなるでしょう。
XAMLには他にもタイムラインベースのアニメーション機能など、膨大な機能が含まれています。ドキュメントを見ながら新しいコントロールをお試しください。また、Expression Blendを使ってさまざまな効果を含めたUIをオーサリングして、Visual Studio 2008に取り込んで連係してみてください。
まとめ
Visual Studio 2008でWPFが正式サポートされることで、XAMLを使ったWPFアプリケーションの作成が行えるようになりました。
イベントのバインドがプロパティウィンドウから行えないなど、これまでのWindows Formsとは少し異なる部分もありますが、IntelliSenseのサポートが強力なので、スムーズにイベント記述を行うことができます。
こうした点は、Visual Studio 2005 Extensions for WPFから大きく進歩した部分と言えるでしょう。Visual Studio 2005 Extensions for WPFは、XAMLコントロールの配置・フォームデザイナ機能のみを提供し、イベントのハンドリングを行うことができませんでした。XAMLで配置したボタンをダブルクリックしても何の反応も無いというのは、RADプログラミングに慣れた身体には少々刺激が強かったものです。コードビハインド側のソースコードで直接イベントのバインドを行うことを強いられたため、統合開発環境を使っているのになぜこんな原始的な方法を…と感じたものでした。
Visual Studio 2008では、コントロールの代表的なイベントはダブルクリックで、それ以外のイベントについてもIntelliSenseを使用することでバインドを行え、快適なコーディングが可能となったと言えるでしょう。
Windows Vistaが出荷されて1年以上が経過しましたが、WPFを使用したアプリケーションはまだそれほど普及しているわけではありません。3.0以降の.NET Frameworkのインストールが必要であることもさることながら、Visual Studioでの正式サポートが無かったため、開発が行いづらかった、というのも一因かもしれません。
待望のVisual Studio 2008による正式サポートは、WPFを利用したさまざまなアプリケーションが世に出るきっかけとなることでしょう。
本記事ではWPFの機能のほんのさわりの部分までしか扱うことはできませんでしたが、WPF/XAMLに収められた機能は非常に膨大です。また、これまでソースコードを書かなければ実現できなかったようなグラフィック機能を、XAMLで記述することができるようにもなりました。前述したデザイナと開発者の共同作業が可能になったことも含め、より豊かなユーザーエクスペリエンスの実現が期待されます。
次回は、WPFアプリケーションの本格的なデザインには欠かせないExpression BlendとVisual Studio 2008の連携について紹介します。
参考資料
- Silverlight入門(1)-XAMLの文法
- WPFでの3Dオブジェクトのイベントサポートについて
- WPF(Windows Presentation Foundation)+XAMLチュートリアル