1つ前でVMでやるのがおすすめですよって書いたけどどうやるの?っていう記事です。
今回はReactivePropertyの組み込みのエラーチェック機能を使ってやってみます。まず。intしか受け付けないValidationAttributeを作ります。
using System.ComponentModel.DataAnnotations; namespace WpfApplication12 { public class IntAttribute : ValidationAttribute { public IntAttribute(string errorMessage) : base(errorMessage) { } public override bool IsValid(object value) { int temp; return int.TryParse(value?.ToString(), out temp); } } }
そして、それをセットしたReactivePropertyを定義します。
public class 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>
めでたしめでたし。