QA@IT

ValidatesOnExceptions の必要性

3366 PV

WPF で binding の設定で ValidatesOnExceptions を true にするか ValidationRules に ExceptionValidationRule を設定すれば例外をキャッチしてバリデーションエラーにしてくれるのですよね。
調べてみると、どちらかを設定してbindingのソースのプロパティのsetterで例外を投げてる例を見かけました。

ですが、これらを設定していなくてもデフォルトで、例外が発生したり自分で throw new Exception("テスト") などしたものがバリデーションのエラーとして扱われていました。

ValidatesOnExceptions のデフォルト値は false ですし、 ValidationRules は自分で設定したものだけで、 ExceptionValidationRule が最初から含まれてるということはありませんでした。

調べているときに、 ExceptionValidationRule がなしだとテキストボックスにint型をbindingして「a」などの数字以外を打っても赤枠が出ないで、ExceptionValidationRuleをつけると数値以外を打つと赤枠出るようになるというページがありました。
http://blogs.wankuma.com/kazuki/archive/2008/02/11/122718.aspx

ですが、実際はルールを設定しなくても例外を投げたり、int型にbindingしたテキストボックスにアルファベット入れるとバリデーション
エラーになって赤枠が出ます。

デフォルトの動きが変わったのでしょうか?
その場合、逆にバリデーションエラーにしたくないときにすでに ValidatesOnExceptions は false なので外すことができなくなっていると思うのですが、例外は絶対にバリデーションエラーにするのが強制されるのでしょうか?

回答

あまり細部までは知らないですが、

  • 振る舞いの違いについて

.NET 3.5ではデータ変換時のエラーでBorderが赤くなることがありませんでした。
.NET 4.0あたりからはデータ変換でBorderが赤くなるようになったようです。
これはビルド設定で.NET3.5を指定( Taskのusingはコメントアウトする必要が出ると思います )すると、VS2015でもそういう動作になります。

  • 例外時の動作について

これはVS2015+.NET4.5.2でもValidatesOnExceptions=Falseであれば例外時にBorderは赤くならず、ValidatesOnExceptions=Trueの場合は赤くなります。
たとえばバインドしているプロパティのSetで無条件にthrowした場合(提示のコードのコメントアウトを解除した場合)に赤くなるかならないかの差が生まれます。(ただしデータ変換エラーはこれとは別に赤くなるので、入力する値は数値のみにしてください。)

※ もしVS2015を利用している場合、デバッグ実行では画面が更新される前にsetterでthrowされた例外が未キャッチの例外として捕捉されてしまうので、「続行」するか「デバッグなしで実行」して画面を確認してください。
「例外が発生したり」と言っていたのはその事ではないかと感じましたが違ったらすいません。


提示されたURLのコードとほぼ同じですが一応載せておきます。
usingは省略しています。

namespace WpfApplicationQA9990 {
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
            DataContext = this;
        }

        private int target;
        public int TargetValue {
            get {
                return target;
            }
            set {
                target = value;
                // throw new Exception("");
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e) {
                MessageBox.Show(target.ToString());
        }
    }
}
<Window x:Class="WpfApplicationQA9990.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:WpfApplicationQA9990"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <TextBox HorizontalAlignment="Center" VerticalAlignment="Center" MinWidth="100" >
            <TextBox.Text>
                <Binding Path="TargetValue" UpdateSourceTrigger="PropertyChanged">
                </Binding>
            </TextBox.Text>
        </TextBox>
        <Button Grid.Row="1" Content="Alert!" Click="Button_Click" Height="20" />
    </Grid>
</Window>
編集 履歴 (0)
  • すみません。型の違いでは赤枠になりましたが、例外を投げたときには赤枠になっていませんでした。既存プロジェクトで関係ありそうなところコメントアウトして確認していたのですが、関係なさそうだったところの処理が影響していたようです。

    BindingGroupを一度設定すると削除してもbindingの設定変更されたままなのですね・・・
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。