2012-01-19 16 views
0

私は私のUIで....プリズムからなぜ私のコマンドはボタンを有効にできませんでしたか?

をDelgateCommandを使用することを学んで、私は私のユーザー名テキストボックスとPasswordBoxを持っています。そして、

<Button Name="button1" Command="{Binding LoginCommand, Mode=TwoWay}" CommandTarget="{Binding ElementName=_UserNameTextBox, Path=Text}">Login</Button> 

<TextBox Name="_UserNameTextBox" Text="{Binding UserName, Mode=TwoWay}" /> 

<PasswordBox Name="_PasswordBox"></PasswordBox> 

そして、私のログインボタン私のViewModel私は持っています:

string _UserName = string.Empty; 
    public string UserName 
    { 
     get 
     { 
      return _UserName; 
     } 
     set 
     { 
      if (value != _UserName) 
      { 
       _UserName = value; 
       RaisePropertyChanged("UserName"); 
      } 
     } 

    } 

    //For reference the password 
    PasswordBox _PasswordBox { get; set; } 


    public DelegateCommand<string> LoginCommand { get; set; } 

    public LoginViewModel(PasswordBox passwordBox) 
    { 
     _PasswordBox = passwordBox; 

     LoginCommand = new DelegateCommand<string>(
      (
       //Execute 
       (str) => 
       { 
        Login(_PasswordBox.Password); 
       } 
      ), 
       //CanExecute Delgate 
       (usr) => 
       { 
        if (string.IsNullOrEmpty(usr) || string.IsNullOrEmpty(_PasswordBox.Password)) 
         return false; 
        return true; 
       } 
      ); 
    } 

私のUserNameがbindiです正しく設定されていて、ViewModelコンストラクタのRefereceとしてPasswordBoxを渡しました。アプリケーションを実行すると、ボタンが無効になるので、コマンドにバインドされていることがわかります。

しかし、私は、私はUserNameとPasswordBoxで物事を入力した後、チェックをされている書いた....そして、決して有効になりませんCanExecuteのdelgateを見たことがない...

は、だから私は間違って何をしたのですか?

EDIT:

=====

だから、最後の結果は...このですか?

string _UserName = string.Empty; 
     public string UserName 
     { 
      get 
      { 
       return _UserName; 
      } 
      set 
      { 
       if (value != _UserName) 
       { 
        _UserName = value; 
        RaisePropertyChanged("UserName"); 
        LoginCommand.RaiseCanExecuteChanged(); 
       } 
      } 

     } 

     //For reference the password 
     PasswordBox _PasswordBox { get; set; } 


     public DelegateCommand<string> LoginCommand { get; set; } 

     public LoginViewModel(PasswordBox passwordBox) 
     { 
      _PasswordBox = passwordBox; 
      _PasswordBox.PasswordChanged += delegate(object sender, System.Windows.RoutedEventArgs e) 
      { 
       LoginCommand.RaiseCanExecuteChanged(); 
      }; 
      LoginCommand = new DelegateCommand<string>(
       (
        (str) => 
        { 
         Login(_PasswordBox.Password); 
        } 
       ), 
        (usr) => 
        { 
         if (string.IsNullOrEmpty(usr) || string.IsNullOrEmpty(_PasswordBox.Password))       
          return false; 
         return true; 
        } 
       ); 
     } 
+0

CanExecuteデリゲートはどこにありますか?button.Enabled = trueを設定する必要があります。どこでそれをやってるの? – MethodMan

+0

hmm? DelgateCommand の2番目のパラメータがFunc UserNameがnullでないか、空でない、Passwordがnullでない、または空でない場合にのみ、lambada式をtrueに戻しています。または私は間違っていた? –

+0

Jonによると、そこにはPasswordBoxへの参照があるはずではないので、パスワードもプロパティにします。 –

答えて

2

CanExecuteによって返されるエフェクト値が変更されるたびに、通常RaiseCanExecuteChangedに電話する必要があります。この特定のケースでは、ユーザーまたはパスワードフィールドの値が変更されたときにいつでも呼び出す必要があります。 ViewModelの実装は完全に間違っています。

H EREあなたの代わりに何をすべきかです:

  1. があなたのViewModel内UsernamePasswordプロパティを公開します。 getterとsetterを明示的に実装する必要があります(つまり、自動プロパティではありません)。
  2. ビュー内で、ユーザー名とパスワードの入力フィールドの内容をこれらのプロパティにバインドします。
  3. プロパティセッターの内部では、LoginCommand.RaiseCanExecuteChangedを呼び出します。

    1. ユーザーがパスワードボックス内の文字:

    はここ(のは、例えば、パスワードボックスを選択しましょう)あなたがこれを行うと何が起こるかです。

  4. WPFは、双方向バインディングのためにLoginViewModel.Passwordの値を設定します。
  5. パスワード設定ツールはRaiseCanExecuteChangedを呼び出し、コマンドのCanExecuteChangedイベントを発生させます。
  6. 送信ボタン(コマンドにバインドしたときにそのイベントにサブスクライブしている)に通知されます。
  7. ボタンはCanExecuteを呼び出して、コマンドの実行が許可されているかどうかを確認します。
  8. デリゲートが実行され、trueが返されるため、ボタンがアクティブになります。
+0

+1 CommandTargetをCommandParameterに置き換えた後、RaiseCanExecuteChangedにPasswordChangedのEventHandlerを追加し、UserNameセッターでRaiseCanExecuteChangedを発生させて、完全に機能しました。 :)そして、私はこの記事によると、PasswordBoxのPasswordプロパティをPasswordBoxにバインドしていませんでした。この記事を読むと、http://stackoverflow.com/questions/1483892/wpf-binding-to-the-passwordbox-in-mvvm-working-solution –

+0

@KingChan:その投稿は誤っています。その下の高評価のコメントが何を読むのかを読んでください。あなたのパスワードを盗もうとするあなたのシステム上で実行されている敵対的なプロセスがあると信じるならば、あなたは単に 'PasswordBox'を投げて、何とか魔法のようにあなたのアプリケーションを安全にしたと思うより大きな問題があります。 – Jon

+0

o hmmm代わりにPasswordBoxからパスワードを取得するために、Password用のGetterプロパティを記述する必要がありますか?私はPasswordBoxに直接バインドできないので... –

1

あなたはそのバインディングの変更がCanExecuteは、私の知る限りではreevalutedされている場合、(ExecuteCanExecuteに渡されます)Button.CommandParameterをバインドする必要があります。

は(私は唯一のコマンドルーティングおよびなどの面で関連することができ、特定の要素にコマンドを(上昇させるために使用される、 CommandTargetは、コマンド内で使用されていない、あなたは CommandTargetCommandParameterが混乱していると思います)

+0

+1ああ、私はCommandParameterを使うべきです....ありがとう –

+1

@ KingChan:**これをしないでください**あなたは間違った方向にあなたを連れて行きます。私の例を読んで、ここで何が起きているのかを理解してください。これがハッキングされて作業をすることができたとしても、パスワードボックスと全く同じ問題が発生します。 – Jon

+0

@ジョン:実際にはそれは本当に問題ではありません。あなたはこれを簡単に適応させることができます.2つの依存関係は、 'MultiBinding'だけ必要です。 –

関連する問題