前回は、XAML の名前空間と、x:Class、x:Name、x:Key などの特別な指定を見ました。
今回は、その中でもコード側との結び付きに関係する構文を整理します。
WPF の XAML は、単独で存在している文書ではありません。多くの場合、C# のクラスと結び付き、画面の構造は XAML、画面の振る舞いは C# に分けて書きます。
この結び付きを理解するうえで重要なのが、次の指定です。
x:Classx:ClassModifierx:Namex:FieldModifier
XAML と partial クラス
WPF のウィンドウは、通常次のような XAML で定義します。
<Window x:Class="SampleApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Sample"
Width="400"
Height="250">
<Grid>
<Button x:Name="SaveButton"
Content="保存" />
</Grid>
</Window>
この XAML に対応するコード側のクラスは、次のようになります。
namespace SampleApp;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
ここで注目したいのは、partial です。
WPF では、XAML から生成されるコードと、自分で書くコードが、同じクラスの別の部分として結合されます。XAML から生成される側には、画面要素を作成し、プロパティを設定し、名前付き要素をフィールドとして保持する処理が含まれます。
自分で書く側には、コンストラクターやイベントハンドラー、画面の動作に関する処理を書きます。
x:Class
x:Class は、XAML がどのクラスと結び付くかを指定します。
<Window x:Class="SampleApp.MainWindow">
この指定により、XAML は SampleApp.MainWindow クラスの一部として扱われます。
コード側のクラス名や名前空間と一致していない場合、ビルド時または実行時にエラーになります。
たとえば、XAML 側が次のようになっているとします。
<Window x:Class="SampleApp.MainWindow">
この場合、コード側も同じ名前空間とクラス名である必要があります。
namespace SampleApp;
public partial class MainWindow : Window
{
}
XAML ファイル名とクラス名は必ずしも同じである必要はありませんが、通常は MainWindow.xaml と MainWindow のように対応させます。そのほうが読みやすく、管理もしやすくなります。
x:ClassModifier
x:ClassModifier は、生成されるクラスの可視性を指定するために使います。
<Window x:Class="SampleApp.MainWindow"
x:ClassModifier="public"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Window>
通常の WPF アプリケーションでは、あまり頻繁に指定するものではありません。多くの場合、既定の設定で十分です。
ただし、ライブラリとして画面部品を公開する場合や、生成されるクラスの可視性を明示したい場合に使うことがあります。
初心者のうちは、x:ClassModifier は「XAML から生成されるクラスの公開範囲を変えるための指定」と理解しておけば十分です。
x:Name
x:Name は、XAML の要素に名前を付けます。
<Button x:Name="SaveButton"
Content="保存" />
名前を付けた要素は、コード側から参照できるようになります。
SaveButton.Content = "保存しました";
これは、XAML の読み込み時に名前付き要素がフィールドとして生成されるためです。
イメージとしては、次のようなフィールドが生成されると考えると分かりやすいです。
private Button SaveButton;
実際の生成コードはプロジェクト形式やビルド環境によって異なりますが、x:Name によってコード側から要素を参照できるようになる、という点が重要です。
Name プロパティとの違い
WPF の多くの要素には、Name プロパティもあります。
<Button Name="SaveButton"
Content="保存" />
x:Name と Name は、多くの場面で同じように使えます。どちらを指定しても、名前スコープに登録され、コード側から参照できることがあります。
ただし、XAML 言語としての名前付けは x:Name です。Name は WPF の FrameworkElement などが持つプロパティです。
そのため、初心者のうちは次のように使い分けるとよいでしょう。
| 指定 | 考え方 |
|---|---|
x:Name | XAML の要素に名前を付ける基本的な方法 |
Name | WPF の要素が持つ名前プロパティ |
WPF の画面要素に名前を付けるだけなら、どちらでも見かけます。ただし、XAML の構文を学ぶ文脈では x:Name を基準に考えると整理しやすくなります。
x:FieldModifier
x:FieldModifier は、x:Name で生成されるフィールドの可視性を指定します。
<Button x:Name="SaveButton"
x:FieldModifier="private"
Content="保存" />
指定できる値には、private、public、protected、internal などがあります。
たとえば、次のように public を指定できます。
<TextBlock x:Name="StatusText"
x:FieldModifier="public"
Text="待機中" />
ただし、名前付き要素を外部から直接操作できるようにする設計は、慎重に扱う必要があります。
WPF では、画面の状態を外部から直接コントロールするよりも、プロパティ、データバインディング、コマンドなどを通じてやり取りするほうが保守しやすいことが多いです。
そのため、x:FieldModifier を使って公開範囲を広げる場面は限定的です。
名前を付けすぎない
初心者のうちは、あとで使うかもしれないと思って、すべての要素に名前を付けたくなることがあります。
<StackPanel x:Name="RootPanel">
<TextBlock x:Name="TitleText"
Text="ユーザー情報" />
<TextBox x:Name="NameTextBox" />
<Button x:Name="SaveButton"
Content="保存" />
</StackPanel>
しかし、コード側から直接参照しない要素には、名前を付ける必要はありません。
<StackPanel>
<TextBlock Text="ユーザー情報" />
<TextBox x:Name="NameTextBox" />
<Button x:Name="SaveButton"
Content="保存" />
</StackPanel>
名前は、コードとの接点です。接点が多すぎると、画面構造とコードが強く結び付き、変更しにくくなります。
まずは、イベント処理や値の取得などで本当に必要な要素だけに名前を付けるのがよいでしょう。
まとめ
XAML とコード側のクラスは、x:Class によって結び付きます。
| 指定 | 役割 |
|---|---|
x:Class | XAML が属するクラスを指定する |
x:ClassModifier | 生成されるクラスの可視性を指定する |
x:Name | 要素に名前を付け、コード側から参照できるようにする |
x:FieldModifier | 名前付き要素として生成されるフィールドの可視性を指定する |
WPF の XAML は、見た目だけを表す静的な文書ではありません。ビルド時や実行時に .NET のオブジェクトへ変換され、コード側のクラスと連携して動作します。
次回は、XAML の最も基本的な読み方である、要素、属性、型変換について整理します。