WPF アーキテクチャと XAML ランタイム処理の詳細

1. XAML とコードビハインドの協調動作

WPF では、ユーザーインターフェース定義(XAML)とロジック実装(C#)が明確に分離され、x:Class 属性と InitializeComponent() メソッドを通じて統合されます。
XAML 定義例(MainWindow.xaml)
<Window x:Class="DemoApp.MainView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:DemoApp.ViewModels"
        Title="計算パネル" Height="480" Width="760">
    <Window.DataContext>
        <vm:CalculationViewModel />
    </Window.DataContext>
    <Grid Margin="12">
        <StackPanel Spacing="16">
            <Slider Minimum="0" Maximum="100" Value="{Binding OperandA, Mode=TwoWay}" />
            <Slider Minimum="0" Maximum="100" Value="{Binding OperandB, Mode=TwoWay}" />
            <Slider Minimum="0" Maximum="200" Value="{Binding Sum, Mode=OneWay}" IsEnabled="False" />
            <Button Content="加算実行" Command="{Binding ExecuteAddition}" HorizontalAlignment="Center" />
        </StackPanel>
    </Grid>
</Window>
この XAML は、xmlns:x 名前空間を経由して、x:Class 属性で指定された部分クラスと結びつきます。この属性は MSBuild によってコンパイル時に解析され、対応する partial クラス(例: MainView.g.cs)が自動生成されます。
C# コードビハインド(MainView.xaml.cs)
namespace DemoApp
{
    public partial class MainView : Window
    {
        public MainView()
        {
            InitializeComponent(); // BAML を読み込み、UI オブジェクトを構築
        }
    }
}
InitializeComponent() は、XAML のコンパイル結果である BAML をロードし、プロパティ値の割り当て、イベントハンドラーの登録、データコンテキストの初期化などを行います。このメソッドは、XAML ファイルに対応する自動生成クラスに実装されており、手動で編集すべきではありません。 必須条件として:
  • XAML 側では x:Class 属性が正しく設定され、xmlns:x 名前空間が宣言されていること
  • C# 側では、partial クラス名が x:Class と一致し、基底クラス(WindowUserControl など)を継承していること
  • コンストラクタ内で InitializeComponent() を呼び出すこと

2. XAML のコンパイルフローとランタイム処理

WPF では、XAML は実行前にバイナリ形式へ変換されます。この形式は BAML(Binary Application Markup Language)と呼ばれ、XML 形式の XAML よりも高速なパースとロードが可能です。 コンパイルステップ:
  1. foo.xamlSystem.Xml.XmlTextReader により構文解析される
  2. MSBuild の XAML コンパイラが BamlWriter を使用して obj\Release\foo.baml を生成
  3. 同時に、foo.g.cs に自動生成された partial クラスが作成され、InitializeComponent() 実装が含まれる
  4. BAML は最終アセンブリ(EXE/DLL)に埋め込まれ、実行時にリソースとして読み込まれる

2.1 名前空間の役割

  • http://schemas.microsoft.com/winfx/2006/xaml/presentation:WPF のコントロールやレイアウトクラス(Button, Grid, TextBox など)を提供
  • http://schemas.microsoft.com/winfx/2006/xaml:XAML 固有の機能(x:Name, x:Key, x:Static, x:Class)を定義

2.2 XAML の基本原則

  • 各 XML 要素は .NET クラスのインスタンスに対応(例:<TextBox>System.Windows.Controls.TextBox
  • 要素の入れ子はオブジェクトグラフの階層構造を表現(例:Grid 内の Button
  • 属性は対応するクラスのパブリックプロパティにマッピング(例:Width="200"Width プロパティの設定)

2.3 トップレベル要素の種類

  • Window:独立したウィンドウ(アプリケーションのメイン画面など)
  • Page:ナビゲーションフレームワーク(Frame)内での遷移単位
  • Application:グローバルリソース、起動エントリ、シャットダウン制御を定義

2.4 InitializeComponent() の内部動作

このメソッドは、Application.LoadComponent() を呼び出し、埋め込まれた BAML リソースから UI オブジェクトツリーを再構築します。処理内容には以下が含まれます:
  • BAML ストリームのデシリアライズ
  • 各要素に対応する .NET オブジェクトのインスタンス化
  • 属性値の適用(バインディング含む)
  • x:Name 付き要素のフィールド参照生成(コードビハインドからのアクセス用)
  • イベントハンドラーの自動接続(Click="OnButtonClick" のような記述がある場合)

タグ: WPF XAML BAML DataBinding INotifyPropertyChanged

7月16日 20:57 投稿