WPF テキストボックスにおける強いバリデーション

Windows Presentation Foundation (WPF) のデータバインドアプリケーションを扱う際、ユーザーの入力が有効で安全であることを保証するためにバリデーションは重要です。一般的なシナリオの一つは、高さのようなヌル許容のデシマルプロパティにバインドされた TextBox に関するものです。しかし、無効な値が入力された場合でも TextBox がフォーカスを失うリスクがあります。このブログ記事では、WPF における強いバリデーションを実装するための効果的な戦略を探り、特に TextBox の入力状態を扱うための2つの主要な方法に焦点を当てます。

問題: 有効なユーザー入力の確保

アプリケーションの中でデシマルプロパティにバインドされた TextBox を考えてみましょう。この TextBox はユーザーが高さの値を入力することを許可します。ユーザーがデシマルに変換できない値を入力すると、TextBox はエラーをハイライトします。しかし、ユーザーが TextBox からフォーカスを外してしまうリスクがあり、アプリケーションが無効な状態になることがあります。これに対処するために、2つの可能な解決策を考えます:

  1. 有効な値が入力されるまで TextBox がフォーカスを失わないようにします。
  2. 無効な入力でフォーカスを失った場合、TextBox の内容を最後の有効な値に戻します。

解決策 1: フォーカス障害の防止

有効な入力が提供されるまで TextBox にフォーカスを維持するための効果的な方法は、PreviewLostKeyboardFocus イベントをハンドルすることです。このアプローチは、無効な状態が検出されるたびにプログラム的にフォーカスの移動を防ぐことを含みます。この解決策を実装する方法は以下の通りです:

XAML 実装

まず、TextBox 定義内で PreviewLostKeyboardFocus のイベントハンドラを追加します:

<TextBox PreviewLostKeyboardFocus="TextBox_PreviewLostKeyboardFocus" 
         Text="{Binding Height, UpdateSourceTrigger=PropertyChanged, 
                         ValidatesOnExceptions=True, 
                         Converter={StaticResource NullConverter}}" />

C# コード実装

次に、フォーカスの損失を防ぐためにコードビハインドでイベントハンドラを実装します:

private void TextBox_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) {
    TextBox box = sender as TextBox;
    var binding = box.GetBindingExpression(TextBox.TextProperty);
    
    // バリデーションエラーをチェック
    if (binding.HasError) {
        // フォーカスの移動をブロック
        e.Handled = true;
    }
}

この方法を使用すると、ユーザーが有効なデシマル値を入力するまで TextBox がフォーカスを失うことはありません。これにより、入力段階でのデータの整合性が確保されます。

解決策 2: 最後の有効な値への復元

別の解決策は、フォーカスが失われる際に TextBox の内容を最後の有効な入力値に戻すことです。これは、最後の有効な状態を保持することが望ましいユーザーフレンドリーなアプリケーションに特に役立ちます。

既存の方法

すでに LostKeyboardFocus イベントハンドラでこの基本的な形式を実装しているかもしれません。完成のために、以下のように構成できます:

private void TextBox_LostKeyboardFocus(object sender, RoutedEventArgs e) {
    TextBox box = sender as TextBox;
    var binding = box.GetBindingExpression(TextBox.TextProperty);
    
    if (binding.HasError) {
        binding.UpdateTarget(); // 最後の有効な値に戻す
    }
}

この方法は機能しますが、即時のフィードバックが求められるシナリオでは最も洗練された解決策を提供しないかもしれません。さらに、ユーザーが無効な入力を続ける場合、彼らが入力しようとしている以前の値に混乱し、フラストレーションを感じることがあるかもしれません。

結論

WPF TextBox コントロールにおける強いバリデーションの実装は、処理されるデータが有効であることを保証することで、ユーザーエクスペリエンスを大幅に向上させることができます。フォーカスの損失を防ぐか、最後の有効な値に戻ることで、アプリケーションが収集するデータの整合性を維持できます。アプリケーションのニーズに最も適した方法を選択し、効率的でユーザーフレンドリーな体験を提供しましょう。

これらの技術を用いることで、データ入力フォームの堅牢性を高め、ユーザーがアプリケーションと成功裏にインタラクションできるよう導くことができます。