2012-03-15 17 views
0

TextBoxバインディングの検証規則で検証されたテキストのみをユーザーが入力できるようにします。私はそれをする方法を考え出した:バインディングターゲットを更新せずに値を検証する方法は?

public static void PreviewTextChanged(
    object sender, 
    PreviewTextChangedEventArgs e) 
{ 
    var textBox = e.Source as TextBox; 
    var bindingExpression = textBox.GetBindingExpression(TextBox.TextProperty); 
    if (!ReferenceEquals(null, bindingExpression)) 
    { 
     // save original parameters for possible restoration 
     var originalSelectionStart = textBox.SelectionStart; 
     var originalSelectionLength = textBox.SelectionLength; 
     var originalText = textBox.Text; 

     // check validation 
     textBox.Text = e.Text; 
     if (!bindingExpression.ValidateWithoutUpdate()) 
     { 
      // restore original values 
      textBox.Text = originalText; 
      bindingExpression.UpdateSource(); 
      textBox.SelectionStart = originalSelectionStart; 
      textBox.SelectionLength = originalSelectionLength; 
     } 
     else 
     { 
      // correct the selection 
      var selectionStart = originalSelectionStart + 
       originalSelectionLength + 
       e.Text.Length - 
       originalText.Length; 
      textBox.SelectionStart = Math.Max(selectionStart, 0); 
      textBox.SelectionLength = 0; 
     } 

     e.Handled = true; 
    } 
} 

上記のコードは動作します。しかし、バインディングターゲットを更新せずに新しい値が有効かどうかを確認する方法を見つけることができれば、はるかに簡単で、バグが発生しにくくなります。 1つはありますか?

答えて

0

この場合、Binding Convertersで中継する方が簡単だと思います。 converterは、データがバインドされたフィールドに割り当てられるたびに呼び出されます。 このメソッドの内部では、データの入力を検証し、検証結果の戻り値または古いデータ(原因の検証に失敗した)に基づいて、ModelViewから回復するか、または検証が成功した場合にそれを受け入れることができます。

これが役に立ちます。

+0

私はあなたの考えを理解していますが、コンバータの内部から古いデータにアクセスするにはどうすればよいですか? –

+0

"古い"データは、UIに適用された変更の影響を受けていない**データです。正しい?したがって、あなたの 'ModelView'には、UI上で可視化されたデータがあります。ユーザーはバインドされたフィールドで何かを変更しました。だから何が起こるべきか、それは 'ModelView'関連のプロパティに設定された値を変更しました。しかし** **の前にコンバーターが呼ばれています。コンバーターの戻り値は 'ModelView'に割り当てられた値と' UI'に割り当てられた値になります。したがって、その時点で検証すると、 'UI'と' ModelView'レイヤの間で渡される値を制御できます。 – Tigran

関連する問題