1つ前でVMでやるのがおすすめですよって書いたけどどうやるの?っていう記事です。
今回はReactivePropertyの組み込みのエラーチェック機能を使ってやってみます。まず。intしか受け付けないValidationAttributeを作ります。
using System.ComponentModel.DataAnnotations; namespace WpfApplication12 { publicclass IntAttribute : ValidationAttribute { public IntAttribute(string errorMessage) : base(errorMessage) { } publicoverridebool IsValid(objectvalue) { int temp; returnint.TryParse(value?.ToString(), out temp); } } }
そして、それをセットしたReactivePropertyを定義します。
publicclass MainWindowViewModel : BindableBase { [Int("整数で入力してね")] public ReactiveProperty<string> Input1 { get; } [Int("整数で入力してね")] public ReactiveProperty<string> Input2 { get; } public ReactiveCommand ExecuteCommand { get; } public MainWindowViewModel() { this.Input1 = new ReactiveProperty<string>("0") .SetValidateAttribute(() => this.Input1); this.Input2 = new ReactiveProperty<string>("0") .SetValidateAttribute(() => this.Input2); this.ExecuteCommand = new[] { this.Input1.ObserveHasErrors, this.Input2.ObserveHasErrors, }.CombineLatestValuesAreAllFalse() .ToReactiveCommand(); } }
ExecuteCommandは、Input1とInput2でエラーが全部Falseだったら実行可能なコマンドに加工しています。CombineLatestValuesAreAllFalse(True版もあるよ)はReactivePropertyのちょっとした便利メソッドですね。
これを以下のような感じでXAMLにバインドすれば出来上がりです。
<Window x:Class="WpfApplication12.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:WpfApplication12"mc:Ignorable="d"Title="MainWindow"Height="350"Width="525"><Window.DataContext><local:MainWindowViewModel /></Window.DataContext><StackPanel><TextBox x:Name="TextBoxInput1"Text="{Binding Input1.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /><TextBlock Text="{Binding (Validation.HasError), ElementName=TextBoxInput1}" /><TextBox x:Name="TextBoxInput2"Text="{Binding Input2.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /><TextBlock Text="{Binding (Validation.HasError), ElementName=TextBoxInput2}" /><Button Content="OK"Command="{Binding ExecuteCommand}"/></StackPanel></Window>
めでたしめでたし。