rksoftware

Visual Studio とか C# とかが好きです

まだまだ現役! Windows フォームアプリの新機能を確認する (1)

devblogs.microsoft.com

最近あまり面白い話題が少ない感じでしたがついに来ました。みんな大好き Windows フォームアプリのお話です。
↑ のブログ記事。見ていきましょう!

※ 現在 WPF でなく WinForms を愛用している日本の IT 技術者が WinForms アプリを MVVM で作りたいと思っているかは別として。

■ 背景?

最初に WinForms でデータバインディングが新しいものではないと語っています。少なくとも日本では大人気の DataGrid と型付き DataSet もそうですし、私は知らなかったのですが VB6 の時代には既に一般的だったそうです。
しかし、まあ多くはイベントハンドラとコードビハインドでコードが書かれ、ロジックと UI 操作が混在した難解なコードが多く書かれていました。これでは、テストも困難ですしロジックを他のものに再利用することもできないことが言及されています。

■ INotifyPropertyChanged

WPF で MVVM が出てみな MVVM で書くようになったことになっています。実際位はそうはならなかったことを私たちは知っていますが、ポジション的にはそう言わざるを得ません。
で、記事では WPF の MVVM に触れ INotifyPropertyChanged の実装の実例コードが書かれています。このコード、日本語のぼろ具などで実際にはあまり見ることはないかもしれません。私も例としてこのようなコードを書くことはあまりしてきませんでした。
※コメントや改行、ネームスペースについては私の好みに書き換えました。

public class NotifyPropertyChangeDemo: System.ComponentModel.INotifyPropertyChanged
{
    public event PropertyChangedEventHandler ? PropertyChanged;

    private string ? _lastName;
    private string ? _firstName;

    public string ? LastName { get => _lastName; set { if (_lastName == value) { return; } _lastName = value; OnPropertyChanged(); } }
    public string ? FirstName { get => _firstName; set { if (_firstName == value) { return; } _firstName = value; OnPropertyChanged(); } }

    private void OnPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

INotifyPropertyChanged と言えば私は良く BindableBase クラスを作ってしまうやり方を書いていましたね。

public class BindableBase: System.ComponentModel.INotifyPropertyChanged
{
    public event PropertyChangedEventHandler ? PropertyChanged;

    protected bool SetProperty<T>(ref T property, T value, [CallerMemberName] string propertyName = "")
    {
        if(Object.Equals(property, value)) return false;
        property = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        return true;
    }
}

public class NotifyPropertyChangeDemo: BindableBase
{
    private string ? _lastName;
    private string ? _firstName;

    public string ? LastName { get => _lastName; set => SetProperty(ref _lastName, value); }
    public string ? FirstName { get => _firstName; set => SetProperty(ref _firstName, value); }
}

最近書いていなかったから懐かしいです。

■ なぜ WinForms を使うのか

だいぶ見出しタイトルを解釈を大きくした意訳しましたが、WinForms を使う理由にも触れています。
新規でアプリを作るなら WinUI を使えばいいが、巨大な既存 WinForms アプリを捨てられないし巨大すぎて一気につくりかえることもできないでしょう? 改修しながら MVVM に書き換えていこう! そうしたら一部分の機能は MAUI でモバイルでも、という事もできるようになっていくのですよ、という事のようですね。

■ サンプルソリューション

問うわけでサンプルのコードが紹介されています。ViewModel をプロジェクトに切り出して、テストプロジェクトも作って、MAUI と WinForms で ViewModel を共有するサンプルですね。
github.com

■ ここまでは背景説明

ここまでは背景説明ですね。ここから .NET 7 で追加された WinForms のバインディング機能の紹介になっていくようです。長くなるのでまずはここまで。次回からゆっくりと .NET 7 でもまだまだ現役! WinForms の新機能!! を見ていきましょう。