XAMLを使わないWPF入門01「イントロダクション」

コンピュータ

VSCodeとdotnet.exeでWPFの開発をしていると、ビューであるXAMLはXMLファイルを直接編集することになります。
ビューが独立したファイルになっている点は良いのでが、コントロールを多数レイアウトしていくと、ネストが深くなりすぎて全体の把握が困難になりがちです。

また、最終的にXAMLをもとにC#のコードが生成されることになりますが、コンピュータが生成するコードは、往々にして難解で理解しがたいコードになりがちです。
残念ながらXAMLから生成されるコードも、その法則に当てはまり、ユーザーが把握できないC#コードが存在することになりデバックが困難になりがちです。

WPFの特徴でもあるXAMLですが、これを使わない方法でアプリを作成することが出来ます。あまり一般的でないので、それなりに困難もありそうですが面白そうなので試してみたいと思います。

サンプルコード

プロジェクトの作成

 dotnet new wpf -f net8.0

App.xaml、MainWindow.xamlは不要ですので、ばっさり削除します。

プロジェクトファイル
ファイル名:プロジェクト名.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UseWPF>true</UseWPF>
    <!-- Main メソッドを持つ型を指定 -->
    <StartupObject>NoXAML01.App</StartupObject>
  </PropertyGroup>

</Project>

StartupObjectにエントリポイントとなるクラスを指定します。
NoXAML01.AppNoXAML01はネームスペースでAppがクラスになります。

ファイル名:MainWindow.xaml.cs

using System.Windows;
using System.Windows.Controls;

namespace NoXAML01;

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    // ウィンドウ内に配置する UI を組み立てる
    private static UIElement BuildContent()
    {
        // ボタンを作り、クリック時のイベントを登録
        var button = new Button
        {
            Content = "クリックしてね",
            Width = 120,
            Height = 40,
            Margin = new Thickness(10)
        };
        button.Click += (_, __) =>
            MessageBox.Show("ボタンがクリックされました!", "Hello");

        // StackPanel にボタンを載せて返す
        return new StackPanel
        {
            Children = { button }
        };
    }

    // コンストラクタ
    public MainWindow()
    {
        Content = BuildContent();  // 中身の UI 要素を返すメソッド
    }
}

MainWindow.xaml.csはWindowクラスを継承したMainWindowを定義するクラスのファイルになります。

WindowContetプロパティにコントロールをセットします。
プロパティですのでWindowにセット出来るコントロールは1つだけのようです。

サンプルではBuildContent()メソッドでStackPanelが返りますので、そちらをContentにセットしています。

StackPanelは垂直または水平方向に子コントロールを積み上げます。複数子コントロールを配置する為、Childrenプロパティはコレクションになっています。
サンプルではButtonをStackPanelに登録しています。

ButtonはClickをトリガーとしてMessageBoxを表示するようにイベントコードを記述しています。

ファイル名:App.xaml.cs

using System.Windows;

namespace NoXAML01;

// Application を継承したエントリポイント
public partial class App : Application
{

    private static void App_Startup(object sender, StartupEventArgs e)
    {
        // ウィンドウ本体をコードで生成
        var window = new MainWindow
        {
            Title = "コードだけで作ったウィンドウ",
            Width = 400,
            Height = 300,
        };
        window.Show();
    }

    // エントリポイント
    [STAThread]
    public static void Main()
    {
        var app = new App();
        // Startup イベントでウィンドウを生成
        app.Startup += App_Startup;
        app.Run();
    }
}

こちらがアプリケーションのエントリポイント(開始位置)になります。
Main()メソッド内で、Appクラスのインスタンスを生成し、Startupイベントをで実行するコードを登録し、App.Run()でアプリケーションを起動します。
サンプルではApp_Startup()がStartupイベントで実行されるように登録されており、その内部ではMainWindowクラスのインスタンスを生成し、window.Show();メソッドでWindowを表示しています。

実行イメージ

1.実行するとボタンが配置されたウィンドウが表示されます。

2.ボタンを押すとメッセージボックスが表示されます。

コードが動作することが確認できました。

まとめ

若干異なりますが、WinFormでアプリケーションを作る方法とよくに似た手順で、WPFでもアプリケーションを作ることが出来そうです。
WinFormの開発に慣れた方であれば、XAMLを学ぶ省略できるので学習コストを下げることが出来るかもしれませんね。

今後、XAMLを使わない方法で、少しずつ色々のコントロールを試していきたいと思います。

コメント