MvvmGenでメンドクサいINotifyPropertyChangedの実装を楽にする(VisualStudio)
メンドクサいMVVM
XAMLアプリではMVVMパターン、モデル・ビュー・ビューモデルパターンで実装するのがセオリーとされています。ビューが描画を、モデルがデータとロジックを担当し、ビューモデルがその間を取り持ちます。
なるほど、理屈は分かります。
<TextBox Text="{Binding ID}" />
<TextBox Text="{Binding CustomerName}" />
<TextBox Text="{Binding PhoneNumber}" />
XAML側でこんな定義をして…。
public class DemoCustomer
{
public Guid ID { get; set; } = Guid.NewGuid();
public string CustomerName { get; set; }
public string PhoneNumber { get; set; }
private DemoCustomer()
{
CustomerName = "Customer";
PhoneNumber = "(312)555-0100";
}
}
プロパティとバインドすれば、プロパティの変更が自動的に反映されるわけです。
…というのは嘘で、その反映は手動でやらないといけません。
マイクロソフトの例に従えば、こうしないといけません。
public class DemoCustomer : INotifyPropertyChanged
{
private Guid idValue = Guid.NewGuid();
private string customerNameValue = String.Empty;
private string phoneNumberValue = String.Empty;
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private DemoCustomer()
{
customerNameValue = "Customer";
phoneNumberValue = "(312)555-0100";
}
public static DemoCustomer CreateNewCustomer()
{
return new DemoCustomer();
}
public Guid ID
{
get
{
return this.idValue;
}
}
public string CustomerName
{
get
{
return this.customerNameValue;
}
set
{
if (value != this.customerNameValue)
{
this.customerNameValue = value;
NotifyPropertyChanged();
}
}
}
public string PhoneNumber
{
get
{
return this.phoneNumberValue;
}
set
{
if (value != this.phoneNumberValue)
{
this.phoneNumberValue = value;
NotifyPropertyChanged();
}
}
}
}
たった3つしかプロパティがないのに、猛烈に見通しが悪くなっています。MFCの暗黒時代に戻ったかのようです。
メンドクサくないMVVM
MvvmGenはこの面倒を解決するための手段の1つです。MvvmGenでDemoCustomerはこうなります。
[ViewModel]
public partial class DemoCustomer
{
[Property]
private Guid id = Guid.NewGuid();
[Property]
private string customerName;
[Property]
private string phoneNumber;
partial void OnInitialize()
{
CustomerName = "Customer";
PhoneNumber = "(312)555-0100";
}
}
最初にやりたかったコードとほとんど変わりません。変数に対応するプロパティはMvvmGenが裏で勝手に作ってくれています。プロパティは名前の先頭が大文字になっています。
この裏でこっそり作られているプロパティは、ソリューションエクスプローラーから参照できます。
// <auto-generated>
// This code was generated for you by
// ⚡ MvvmGen, a tool created by Thomas Claudius Huber (https://www.thomasclaudiushuber.com)
// Generator version: 1.1.2
// </auto-generated>
using MvvmGen.Commands;
using MvvmGen.Events;
using MvvmGen.ViewModels;
namespace Sample
{
partial class DemoCustomer : global::MvvmGen.ViewModels.ViewModelBase
{
public DemoCustomer()
{
this.OnInitialize();
}
partial void OnInitialize();
public System.Guid Id
{
get => id;
set
{
if (id != value)
{
id = value;
OnPropertyChanged("Id");
}
}
}
public string CustomerName
{
get => customerName;
set
{
if (customerName != value)
{
customerName = value;
OnPropertyChanged("CustomerName");
}
}
}
public string PhoneNumber
{
get => phoneNumber;
set
{
if (phoneNumber != value)
{
phoneNumber = value;
OnPropertyChanged("PhoneNumber");
}
}
}
}
}
この面倒から解放されるのはありがたいですね。ていうか最初からこうしてくれよマイクロソフト。
プロパティの変更を検知する
MvvmGenはプロパティを自動生成するため、そのままではsetterで何か処理をするということができません。PropertyCallMethod属性を追加することで、プロパティがセットされたときにそのメソッドを呼んでくれます。
[ViewModel]
public partial class DemoCustomer
{
[PropertyCallMethod("OnUpdateCustomerName")]
[Property]
private string customerName;
private void OnUpdateCustomerName()
{
System.Diagnostics.Debug.WriteLine($"customerName has been changed to {customerName}");
}
}
コマンド
PropertyはViewModelからViewへの通信でしたが、この逆のViewからViewModelへの通信としてコマンドという仕組みがあります。MvvmGenはこのコマンドにも対応しています。
[ViewModel]
public partial class DemoCustomer
{
[Property]
private Guid id = Guid.NewGuid();
[Property]
private string customerName;
[Property]
private string phoneNumber;
partial void OnInitialize()
{
CustomerName = "Trump";
PhoneNumber = "(312)555-0100";
}
[Command]
private void ClickFire()
{
CustomerName = "Biden";
}
}
CustomerNameをTrumpにしておき、ボタンがクリックされたらBidenに書き換えます。ClickFireメソッドにCommand属性が追加されています。
<TextBlock Name="SampleText" FontSize="100" Text="{Binding CustomerName}"/>
<Button Content="Fire!" Command="{Binding ClickFireCommand}"/>
ClickFireCommandがMvvmGenにより自動生成されていますので、これをXAML側でボタンにバインドします。作業はこれだけで完了です。
これでも.NET FrameworkのWinFormに比べればまだ煩雑ですが、だいぶ許容範囲になりました。
Author And Source
この問題について(MvvmGenでメンドクサいINotifyPropertyChangedの実装を楽にする(VisualStudio)), 我々は、より多くの情報をここで見つけました https://qiita.com/hayashida-katsutoshi/items/9f6f08e224f2fee23e4b著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .