連載:XAMLの基礎知識

第2回 XAMLとWPFの関係

デジタルアドバンテージ 遠藤 孝信
2008/02/15
Page1 Page2 Page3

 前回ではXAML版Hello Worldプログラムを作成し、そのビルド方法までを解説しました。今回はHello Worldプログラムをいろいろと修正しながら、XAMLとWPFの関係について探っていきます。

 ここでポイントとなるのは、「XAMLの要素はWPFクラス・ライブラリのクラスと対応している」という点です。今回で利用するXAMLの要素と、それに対応したクラスを次の表にまとめておきます。

XAML WPFのクラス
<Application>要素 System.Windows名前空間のApplicationクラス
<Window>要素 System.Windows名前空間のWindowクラス
<Button>要素 System.Windows.Controls名前空間のButtonクラス
今回で利用するXAMLの要素とそれに対応したWPFのクラス

ボタンの追加

 前回のHelloWorldプログラムのように、ウィンドウに「Hello World」のメッセージを出すだけでは少し寂しいので、今回はまず、メッセージの代わりにボタンを追加してみましょう。ボタンは<Button>要素で記述し、その内容がボタンのキャプションとなります。

 前回で作成した、ウィンドウを定義しているwin.xamlを次のように書き換えます。

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  Title="My First XAML"
  Width="320"
  Height="240"
>

  <Button Width="100" Height="50">
    Click Me!
  </Button>
</Window>
リスト1 メッセージの代わりにボタンを表示するwin.xaml

 このビルドには前回で作成したアプリケーション定義の「app.xaml」とプロジェクト・ファイル「hello.prj」が必要になります。以下にこの2つを再掲します。

<Application
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  StartupUri="win.xaml"
/>
リスト2 アプリケーションを定義したapp.xaml(再掲)

<Project
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
    DefaultTargets="Build" >

  <PropertyGroup>
    <AssemblyName>HelloWorld</AssemblyName>
    <OutputType>winexe</OutputType>
    <OutputPath>.\</OutputPath>
  </PropertyGroup>

  <ItemGroup>
    <ApplicationDefinition Include="app.xaml" />
    <Page Include="win.xaml" />

    <Reference Include="System" />
    <Reference Include="WindowsBase" />
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
  </ItemGroup>

  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" />

</Project>
リスト3 プロジェクト・ファイルhello.proj(再掲)

 前回解説したように、以上の3つのファイルのあるフォルダでMSBuild.exeを実行すれば、HelloWorld.exeが出来上がります。リスト1の実行時のウィンドウは次のようになります(以降、すべてWindows Vista上で実行しています)。

ボタンを配置したウィンドウ

 リスト1の<Button>要素では、その属性としてボタンの幅と高さしか指定していませんが、<Window>要素の子要素は自動的にセンタリングされるようになっています。

 ちなみに、ボタンを2つ表示しようとして<Button>要素を2つ並べても、ビルド時にエラーとなります。これは<Window>要素が1つの子要素しか持てないためです。次回以降で解説しますが、通常はコンテナとなるパネル系のコントロールを<Window>要素の直下に配置し、その中にアプリケーションに必要なコントロールを配置していくといった形になります。

 さて、ボタンは表示しただけでは意味がありません。続いてはボタンが押されたときの処理(ボタンのイベント・ハンドラ)を追加しましょう。

ボタンのイベント・ハンドラ

 ボタンがクリックされたらアニメーションを開始するといった動作はXAMLの「イベントトリガ」を使ってXAMLのみで記述できますが、XAMLは基本的にGUIの定義を記述するものであり、イベント・ハンドラやそれに起因するロジックはC#やVBで記述します。

 まずXAMLの方を修正して、ボタンがクリックされたときにC#/VBのメソッドが呼び出されるようにしておきます。具体的には、<Button>要素のClick属性に、ボタンがクリックされたときに呼び出されるメソッドの名前を記述しておきます。

 さらには、XAMLによるウィンドウの記述から暗黙的に作成されるクラスの名前を指定するために、<Window>要素に対して「x:Class属性」でクラス名を指定します(この属性のプリフィックス「x:」については後述の「[コラム]プリフィックス「x:」について」を参照)。

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="HelloWorldWindow"
  Title="My First XAML"
  Width="320"
  Height="240"
>

  <Button Width="100" Height="50" Click="HelloWorldWindow_Click">
    Click Me!
  </Button>
</Window>

リスト4 イベント・ハンドラの指定を追加したwin.xaml

 ここではx:Class属性で「HelloWorldWindow」という値を指定していますので、<Window>要素は最終的にはHelloWorldWindowクラスとしてコンパイルされることになります。

 XAMLの要素がWPFのクラスと対応するのであれば、<Window>要素は「Windowクラス」としてインスタンス化されるのではと思われるかもしれませんが、<Window>要素についてはWindowクラスを継承したクラス(子クラス)としてHelloWorldWindowクラスが作成されます。これは従来のWindowsフォーム・アプリケーションで、フォームが実際にはFormクラスの子クラスとしてプログラミングされるのと同じ構造ですね。

 また、<Button>要素のClick属性では「HelloWorldWindow_Click」という値を指定していますので、これによりボタンがクリックされたときには、HelloWorldWindow_Clickメソッドが呼び出されます。

 以上により、リスト4のwin.xamlからはHelloWorldWindowクラスが作成され、ボタンがクリックされると、そのHelloWorldWindow_Clickメソッドが呼び出されるようになりました。続いては部分クラスを使ってHelloWorldWindow_Clickメソッドを追加します。

[コラム]プリフィックス「x:」について

 例えばリスト4では、要素名である「Window」や「Button」や、その属性名である「Width」や「Height」の名前空間は、<Window>要素のxmlns属性で指定されている、

http://schemas.microsoft.com/winfx/2006/xaml/presentation

です。これは「WPF名前空間」と呼ばれ、この名前空間に属する要素や属性はWPFのクラス・ライブラリの項目と対応付けられます。

 これに対して、<Window>要素で指定するClass属性の名前空間はそれとは異なり、

http://schemas.microsoft.com/winfx/2006/xaml

として定義されています。これは「XAML名前空間」と呼ばれ、XAMLのコードを記述するのに必要な要素や属性のための名前空間です。これら2つの名前空間がXAMLで主に使用される名前空間です。

 既定の名前空間(XAMLの場合にはWPF名前空間)と異なる名前空間の要素や属性を記述するには、プリフィックスが必要になります。プリフィックスとして用いる文字列は何でもよく、例えば次のように「xaml」などにしてもよいのですが、XAML名前空間用には「x」を付ける決まりになっており、リファレンス・マニュアルなどもその前提で記述されています。

xmlns:xaml="http://schemas.microsoft.com/winfx/2006/xaml"
xaml:Class="HelloWorldWindow"

コードビハインド・ファイルによるイベント・ハンドラの記述

 ここではC#/VBを使って、ボタンがクリックされたときのイベント・ハンドラを記述します。ボタンがクリックされたときにはメッセージボックスを表示することにしましょう。

 部分クラス(partialキーワード)を使えば、本来は(暗黙的に作成される)HelloWorldWindowクラス内に存在しなければならないHelloWorldWindow_Clickメソッドを、外部から追加できます。そのメソッドを含む部分クラスは次のようになります。

using System.Windows;

public partial class HelloWorldWindow : Window {
  void HelloWorldWindow_Click(object sender, RoutedEventArgs e) {
    MessageBox.Show("クリックされました!");
  }
}
Imports System.Windows

Partial Public Class HelloWorldWindow
    Inherits Window
  Sub HelloWorldWindow_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    MessageBox.Show("クリックされました!")
  End Sub
End Class
リスト5 イベント・ハンドラとなるメソッドを含む部分クラス(上:win.xaml.cs、下:win.xaml.vb)

 このクラス定義は、最終的にはリスト4のXAMLの定義から生成されるクラスと合体して実行されることになります。

 リスト5を記述したファイルは、GUIを記述したリスト4のXAMLファイルの「コードビハインド・ファイル」となります。通常、ファイル名はXAMLファイルに「.cs」や「.vb」を付けたものにします。

 リスト4とリスト5をコンパイルするためにプロジェクト・ファイルも修正しましょう(リスト6)。リスト5のファイルを<Compile>要素により指定する必要があります。

<Project
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
    DefaultTargets="Build" >

  <PropertyGroup>
    <AssemblyName>HelloWorld</AssemblyName>
    <OutputType>winexe</OutputType>
    <OutputPath>.\</OutputPath>
  </PropertyGroup>

  <ItemGroup>
    <ApplicationDefinition Include="app.xaml" />
    <Page Include="win.xaml" />

    <Compile Include="win.xaml.cs" />

    <Reference Include="System" />
    <Reference Include="WindowsBase" />
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
  </ItemGroup>

  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" />

</Project>

<Project
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
    DefaultTargets="Build" >

  <PropertyGroup>
    <AssemblyName>HelloWorld</AssemblyName>
    <OutputType>winexe</OutputType>
    <OutputPath>.\</OutputPath>
  </PropertyGroup>

  <ItemGroup>
    <ApplicationDefinition Include="app.xaml" />
    <Page Include="win.xaml" />

    <Compile Include="win.xaml.vb" />

    <Reference Include="System" />
    <Reference Include="WindowsBase" />
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
  </ItemGroup>

  <Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" />
  <Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" />

</Project>

リスト6 プロジェクト・ファイルhello.proj(上:C#用、下:VB用)
リスト4とリスト5からHelloWorld.exeを作成するためのプロジェクト・ファイル。

 リスト4〜6の3つのファイルを用意してMSBuild.exeを実行すれば、実行ファイルであるHelloWorld.exeが出来上がります。これを実行して[Click Me!]ボタンをクリックしたときの画面は次のようになります。

[Click Me!]ボタンをクリックしたときの画面


 INDEX
  XAMLの基礎知識
  第2回 XAMLとWPFの関係
  1.コードビハインドによるイベント・ハンドラの記述
    2.ウィンドウをXMALではなくC#/VBで記述
    3.アプリケーション定義をC#/VBで記述
 
インデックス・ページヘ  「XAMLの基礎知識」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間