ReactivePropertyで入力値チェック(Validation)をする

コンピュータ
入力値チェック(Validation)サンプルです。必須入力で0より大きい数値で奇数のみ受け付ける入力項目を作成しました。

ソースコード

ファイル名:MainWindow.xaml

<Window x:Class="ValidationSample.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:i="clr-namespace:Microsoft.Xaml.Behaviors;assembly=Microsoft.Xaml.Behaviors"
        xmlns:interactivity="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF"
        xmlns:local="clr-namespace:ValidationSample"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <StackPanel>
            <WrapPanel>
                <Label Content="数値" />
                <Label Content="{Binding ErrorText1.Value}" Foreground="Red" HorizontalAlignment="Right" />
            </WrapPanel>
            <TextBox Text="{Binding Text1.Value, UpdateSourceTrigger=PropertyChanged}" />
            <Button Content="実行" Command="{Binding ExecCommand}" />
        </StackPanel>
    </Grid>
</Window>

ファイル名:MainWindowViewModel.cs

using System;
using System.ComponentModel;
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using System.Reactive.Disposables;

using System.Diagnostics;
using System.Windows.Threading;
using System.Windows;

namespace ValidationSample;

public class MainWindowViewModel : INotifyPropertyChanged, IDisposable
{
    public event PropertyChangedEventHandler? PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        if (PropertyChanged == null) return;
        PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
    private CompositeDisposable Disposable { get; } = new ();
    public void Dispose() => Disposable.Dispose();

    public ReactiveProperty<string> Text1 { get; }
    public ReactiveProperty<string> ErrorText1 { get; }
    public ReactiveCommand ExecCommand { get; }

    
    public MainWindowViewModel()
    {
        Text1 = new ReactiveProperty<string>()
            .SetValidateNotifyError(
                x =>
                {
                    int value = 0;

                    if (string.IsNullOrEmpty(x)) return "必須";
                    if (int.TryParse(x, out value) == false) return "数値";
                    if (value <= 0) return "0より大きい数値";
                    if ((value % 2) == 0) return "奇数";

                    return null;
                })
            .AddTo(Disposable);
    
        ErrorText1 = new ReactiveProperty<string>()
            .AddTo(Disposable);
        
        Text1.ObserveValidationErrorMessage()
            .Subscribe(x => ErrorText1.Value = x ?? "");
        
        ExecCommand = 
            new[]
            {
                Text1.ObserveHasErrors,
            }
            .CombineLatestValuesAreAllFalse()
            .ToReactiveCommand();
        ExecCommand.WithSubscribe(_ =>
        {
            MessageBox.Show(Text1.Value);
        });
    }
}

実行例

初期状態

数値以外を入力

0以下の数値を入力

奇数を入力すると入力値のチェックが通り「実行」ボタンが活性化し押せるようになります。

コメント