RunningCSharp

MS系開発者による、雑多な記事。記事は所属企業とは関係のない、個人の見解です。

WPF:TextBoxで連続入力中の入力エラーを抑制

<Window x:Class="WpfApplication.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:WpfApplication"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>
    <Grid>
        <TextBox HorizontalAlignment="Stretch" VerticalAlignment="Center"
                  Text="{Binding TestValue, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}" />
    </Grid>
</Window>

上記画面にて、バインド元のViewModelのプロパティで入力内容のエラーチェック(数値の場合、1000未満はエラー)を行うものとします。

    public class MainViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string testValue;
        public string TestValue
        {
            get { return testValue; }
            set
            {
                int parse = default(int);
                //数値の場合1000未満はエラー
                if (int.TryParse(value, out parse) && parse < 1000)
                    throw new Exception();
                testValue = value;
                PropertyChanged(this, new PropertyChangedEventArgs("TestValue"));
            }
        }
    }

このアプリケーションを実行し、数値の「5000」をテキストボックスに入力しようとすると、 一文字目の「5」を入力した段階でエラーとなってしまいます。 UpdateSourceTriggerがPropertyChangedなので当たり前の挙動ですが、LostFocusではなくプロパティ変更の段階でエラーを通知したい、でも入力した瞬間に即エラーを出されるのも微妙、そこでDelayで少し通知を遅らせてみます。

<Grid>
    <TextBox HorizontalAlignment="Stretch" VerticalAlignment="Center"
                Text="{Binding TestValue, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True, Delay=500}" />
</Grid>

上記のように、TextプロパティのBInding文の中でDelayを設定すると、入力直後のエラー表示は避けられます。 単位はミリ秒ですので、例では入力終了後0.5秒後にエラー表示されます。

文字を連続で入力している場合は、最終入力から0.5秒後にエラー表示されます。