期待
MVVMや双方向バインディングでは、バインドしたViewModelの更新を画面に反映して欲しいです。
そのような場合、ViewModelにINotifyPropertyChangedインターフェイスを実装して実現するようです。
INotifyPropertyChangedを実装する方法
方法 : INotifyPropertyChanged インターフェイスを実装するに、従って実装します。
ViewModel.cs
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace WpfApplication1
{
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private string message = "";
public string Message
{
get
{
return this.message;
}
set
{
if (value != this.message)
{
this.message = value;
NotifyPropertyChanged();
}
}
}
}
}
次のような気持ちでいっぱいです。
- PropertyChangedEventHandlerとNotifyPropertyChangedのおまじない感
- 自動実装プロパティーで、プロパティーを簡潔に書けるC#の魅力とはなんだったのか?
- (必要な場合)さらにModelとの変換ロジックも実装するの?
- こんなことで「ViewModelを書けば、(ビューの)データと描画ロジックを美しく分離できる」と言えるのか?
MainWindow.xaml.cs
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new ViewModel();
DataContext = vm; // DataContextにViewModelをバインド
vm.Message = "Hello"; // DataContextのプロパティーを更新すると画面に反映
}
}
}
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock Text="{Binding Message}"/>
</Grid>
</Window>
こちらは期待通りです。
スクリーンショット
軽減手段
いくつか多少軽減する方法はあるようです。
データクラスとして非本質的な記述が、あまり減らないのが気になります。
ReactivePropertyを使うと
ViewModel.cs
using Reactive.Bindings;
namespace WpfApplication1
{
public class ViewModel
{
public ReactiveProperty<string> Message { get; } = new ReactiveProperty<string>();
}
}
この簡潔さ。データクラスがプロパティー定義だけを持つ、圧倒的な簡潔さです。
型名は少し長いですが、VisualStudioの補完機能を考えれば気になりません。
MainWindow.xaml.cs
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new ViewModel();
DataContext = vm; // DataContextにViewModelをバインド
vm.Message.Value = "Hello"; // DataContextのプロパティーを更新すると画面に反映
}
}
}
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock Text="{Binding Message.Value}"/>
</Grid>
</Window>
値の参照・設定にValue
を使う点に注意が必要です。
はじめて試した時、見事にはまりました。