2011-07-11 4 views
0

問題:コントロールのValidatesOnExceptionsプロパティを使用してTextBoxのユーザー入力を検証したいと思います。DependencyPropertyにデータバインドされた入力を検証する - Silverlight

XAMLコード:

DataContext="{Binding RelativeSource={RelativeSource Self}}"  
... 
<TextBox x:Name="TestTextBox" Text="{Binding TestText, Mode=TwoWay, ValidatesOnExceptions=True}" TextChanged="TestTextBox_TextChanged"/> 

1:通常のプロパティを使用して検証が正常に動作:

ビューモデルコード:

private string _testText, 

public string TestText { 
    get {return _testText;} 
    set { 
     if (value=="!") 
      throw new Exception("Error: No ! allowed!"); 
     _testText = value; 
    } 
} 

2:依存関係プロパティを使用して検証は、「Aを引き起こします'System.Exception' ... "型の最初のチャンス例外とアプリケーションが動作を停止します。

のViewModelコード:

public partial class MyControl : UserControl { 
    public MyControl() { 
     InitializeComponent(); 
    } 

    public static readonly DependencyProperty TestTextProperty = DependencyProperty.Register("TestText", typeof(String), typeof(MyControl), new PropertyMetadata("DefaultText", new PropertyChangedCallback(OnTestTextChanged))); 

    public event TextChangedEventHandler TestTextChanged; 

    public String TestText { 
     get { 
      return (String)GetValue(TestTextProperty); 
     } 
     set { 
      SetValue(TestTextProperty, value); 

      if (TestTextChanged != null) { 
       TestTextChanged(TestTextBox, null); 
      } 

      if (TestText=="!") { 
       throw new Exception("No ! allowed!"); 
      } 
     } 
    } 

    static void OnTestTextChanged(object sender, DependencyPropertyChangedEventArgs args) { 
     MyControl source = (MyControl)sender; 
     source.TestTextBox.Text = (String)args.NewValue; 
    } 

    private void TestTextBox_TextChanged(object sender, TextChangedEventArgs e) { 
     TextBox source = (TextBox)sender; 
     TestText = source.Text; 
    } 
} 

は私が間違って何をしているのですか?

答えて

3

2番目の例を実行し、例外がスローされたときにコールスタックを調べると、それは依存システムをまったく通過していないことがわかります。テキストボックスのテキストが変更され、イベントハンドラが実行され、例外が発生しました。それがアプリケーションが死ぬ理由で​​す。

OnTestTextChangedメソッドが呼び出されていないため、そのTextChangedイベントハンドラを配置したと思われます。それが起こるにつれ、これには理由がありますが、それは少し微妙で、私はそれをバックアップするためのドキュメントを見つけることができません。私はこの行動を「ブラックリスト化」と呼んでいます。要するに、依存関係プロパティにPropertyChangedCallbackがあり、PropertyChangedCallbackが同じ依存関係プロパティを直接的または間接的に設定すると、PropertyChangedCallbackは「ブラックリストに登録」され、再度呼び出されることはありません。次のように

あなたのPropertyChangedCallbackは次のとおりです。

static void OnTestTextChanged(object sender, DependencyPropertyChangedEventArgs args) { 
    MyControl source = (MyControl)sender; 
    source.TestTextBox.Text = (String)args.NewValue; // ******* 
} 

*印を付しラインは、ここで問題です。

  • あなたがテキストボックスのTextプロパティを設定し、
  • Silverlightはその後、バインディングを使用してTestText依存関係プロパティの値を更新
  • これはあなたのPropertyChangedCallbackに別のコールを引き起こす、次のように何が起こるかです。

しかし、この時点で、SilverlightはPropertyChangedCallbackを再帰的に呼び出すことを認識し、再度呼び出す代わりに、ブラックリストに登録することを決めました。この 'ブラックリスト登録'の結果、PropertyChangedCallbackが再び呼び出されることはありません。うんざりすると、これを行うときにエラーや警告はありません。

なぜ警告やエラーが出るのかわかりません。しかし、PropertyChangedCallbackをブラックリストに登録していない場合は、スタックオーバーフローが発生します。

コードをどのように修正しますか?さて、で開始する、私はあなたのコードに違反シルバー(およびWPF)依存関係プロパティ、での作業の黄金のルールを紹介したいと思います:依存関係プロパティに裏打ちされたプロパティに

SETTERはSetValueを呼び出す必要がありますと何もありません。依存関係プロパティーの値を変更するときは、プロパティー設定ツールでPropertyChangedCallbackとNOTを入力する必要があります。

このルールに固執しないと、痛みの世界に入ります。

あなたTestTextプロパティは、したがって、次のようになります。

public String TestText 
    { 
     get { return (String)GetValue(TestTextProperty); } 
     set { SetValue(TestTextProperty, value); } 
    } 

、その代わりに、あなたのPropertyChangedCallbackに検証を行う必要があります。

static void OnTestTextChanged(object sender, DependencyPropertyChangedEventArgs args) 
    { 
     if ((string)args.NewValue == "!") 
     { 
      throw new Exception("No ! allowed!"); 
     } 
    } 

あなたのコードにこれらの変更を行った後、私ができましたそれを実行し、!というテキストを入力したときにTextBoxに表示される検証ツールチップを取得します。

0

私は、依存関係プロパティとその慣れていないが、私は場合は、

を言うのコードの2番目のブロックにそれを見ることができます(TestText =「!」){

あなたが持つことを交換する必要があります

if(TestText == "!") { 

あなたのコードはTestTextを "!"に設定していました。それらが同じ文字列かどうかをチェックするのではなく、

+0

私は、OPが匿名でコードを匿名化しているので、その行に 'if(TestText ="! ")という行があると思われます。 C#の 'if'文の条件は' bool'型でなければならないので、上記のコードはコンパイルされませんが、 'TestText ="! "'という型は 'string'型です。 –

+0

ああ、代わりに警告を投げるかもしれないと思った。 – StephenT

関連する問題