2011-12-08 9 views
0

私はMVVM & WPFのいくつかの例を使って作業していましたが、デバッグ中に私のビューのボタンに関連付けられたRelayCommandが(ImportHoursCommandを実行して)すぐにプログラムが開始されます。ここでWPF&RelayCommand - ボタンは常に点滅します

コードスニペットは、次のとおりです。

ビュー

<Button x:Name="ImportHoursButton" Content="Import Hours" 
     Command="{Binding ImportHoursCommand}" 
     Height="25" Width="100" Margin="10" 
     VerticalAlignment="Bottom" HorizontalAlignment="Right"     
     Grid.Row="1" /> 

のViewModel

 private RelayCommand _importHoursCommand; 
     public ICommand ImportHoursCommand 
     { 
      get 
      { 
       if (_importHoursCommand == null) 
       { 
        _importHoursCommand = new RelayCommand(param => this.ImportHoursCommandExecute(), 
                  param => this.ImportHoursCommandCanExecute); 
       } 
       return _importHoursCommand; 
      } 
     } 

     void ImportHoursCommandExecute() 
     { 
      MessageBox.Show("Import Hours", 
          "Hours have been imported!", 
          MessageBoxButton.OK); 
     } 

     bool ImportHoursCommandCanExecute 
     { 
      get 
      { 
       string userProfile = System.Environment.GetEnvironmentVariable("USERPROFILE"); 
       string currentFile = @userProfile + "\\download\\test.txt"; 
       if (!File.Exists(currentFile)) 
       { 
        MessageBox.Show("File Not Found", 
            "The file " + currentFile + " was not found!", 
            MessageBoxButton.OK); 
        return false; 
       } 
       return true; 
      } 
     } 

私は 'という文字列USERPROFILE = ...' 行にブレークポイントを置く場合プログラムを実行すると、Visual Studioはブレークポイントで停止し、breakpoiで停止し続けますnt毎回デバッグの「続行」ボタンをクリックします。ブレークポイントがない場合、プログラムは正常に実行されますが、このコマンドは実行可能かどうかを常にチェックする必要がありますか?

私はJosh Smithの記事hereのRelayCommandを使用しています。

答えて

6

ボタンがコマンドにバインドされている場合、CanExecute()はボタンが有効かどうかを判断します。つまり、CanExecute()は、ボタンが有効な値(画面に描画されたときなど)をチェックする必要があるときにいつでも実行されます。

VSでブレークポイントを使用しているので、VSがフォーカスを取得したときにアプリケーションが非表示になっていると推測しており、[続行]ボタンを押したときにボタンを再描画しています。ボタンを再描画すると、それは再びCanExecute()と評価されています。あなたが見ている無限のサイクルに入ります。

確かに1つの方法は、ブレークポイントをDebug.WriteLineに変更して、アプリケーションが実行中です。

RelayCommandをMicrosoft PrismのDelegateCommandに変更することもできます。私はあまりにも密接に違いを見ていないが、特定の条件が満たされたときにが自動的にCanExecuteChanged()イベントを発生させることがわかっている(プロパティ変更、視覚的無効化など)。DelegateCommandsは、つまり、CanExecute()は、状況に応じて、自動的にではなく、具体的に指示するときにのみ評価されます。

+0

これは意味があります。私が行ってきた例では、CanExecuteがボタン自体を制御していたことを明確にしていませんでした。コマンド自体が実行可能かどうかを判断する方法だと思った。 – BrianKE

+0

@BrianKEいいえ、あなたが 'Command.Execute()'を手動で実行した場合は、まず 'Command.CanExecute()'を実行してください – Rachel

2

これは完全に正常です。 WPFは、コマンドが非常に頻繁に実行できるかどうかを再評価します。たとえば、フォーカスコントロールが変更されたとき、またはウィンドウにフォーカスが当てられたときなどです。 「続行」をクリックするたびにウィンドウが再びフォーカスを受け取り、コマンドのCanExecuteが再評価され、ブレークポイントが再び表示されます。

+0

なぜこれが正常な動作ですか?ボタンを押したときにコマンドをチェック/実行するべきではありませんか? ボタンをクリックしたときにのみこれをチェックする方法はありますか?このコマンドを実行すると、ファイルが存在するかどうか、インポートする時間が既に存在するかどうか、メッセージボックスが表示されて何か問題が発生したかどうかをユーザーに知らせるためのチェックが行われます。それが常に状態をチェックするとき、私はMesasgeBoxesをノンストップしてプログラムを使用できなくすることになっています。 – BrianKE

+2

@BrianKE 'CanExecute'は、ボタンが有効かどうかを判断するので、UIがボタンを再描画する必要があるときや、RelayCommandがCanExecuteパラメータが変更されたと考えるときはいつでも、CanExecute()メソッドが実行されます。ボタンのClickメソッドまたはFileNameのPropertyChangedイベントにファイルが存在するかどうか(または他のそのようなロジック)をチェックする方がよいでしょう。 – Rachel

+0

MVVMを使用してコードとビューの分離を維持する場合、ClickメソッドがCommandに置き換えられたと思いますか?これは当てはまらないのですか、私はCommandExecute()のポイントを見逃していますか? – BrianKE

関連する問題