2016-06-23 3 views
0

WPF MVVMプロジェクトで作業しています。WPF UIの変更が延期される

VieModelの内部では、長いプロセスを開始する前にコントロールを非表示にしたいと考えています。次のように

コマンドコードは次のようになります。

private RelayCommand _DeleteCommand; 
public RelayCommand DeleteCommand 
{ 
    get 
    { 
     return _DeleteReferenceCommand 
      ?? (_DeleteReferenceCommand = new RelayCommand(
      () => 
      { 


        GridViewVisibility = false; 

        //Long process.... 

      }, 
      () => { return ReferencesGridWithPicsUC.SelectedReference != null; } 

      )); 
    } 
} 

GridViewVisibilityは、ビューに私のコントロールの可視性にバインドされ、raiseeventを使用しています。 looongプロセスの後で、コマンドが返った後に可視性が実際に更新される点を除いて、正常に動作します。 私は明らかにそれができるだけ早く更新したい。

Application.Current.Dispatcher.BeginInvoke(new Action(() => 
          GridViewVisibility = false)); 

同じ結果と

GridViewVisibility = false; 

は私がディスパッチャと置き換えを使用してみました。

どうすれば動作させることができますか?

+2

'GridViewVisibility = false'を設定した後、ロングプロセスを非同期に実行しようとしないのはなぜですか? – ViVi

答えて

2

コマンドexecuteメソッドはUIスレッドをブロックします。あなたはそこにUI更新を引き起こす何かをしていますが、あなたが実際にあなたが求めるものをUIにさせるためにUIスレッドのブロックを解除しているわけではありません。代わりに、UIスレッドを長時間ブロックし続けます。 UIスレッドのブロックを停止すると、UIが再び応答し、更新が行われます。

長いプロセスが完了する前にUIの更新を実行するには、長いプロセスのスレッドを起動する必要があります。古いMFCの時代には、メッセージループをポンピングするのに使用しましたが、その後、禁止を廃止しました。とにかくそのメソッドは***のように機能していました。最終的にはC++でスレッドを書く必要がありました。雪の中で脇の下まで、何も食べずに古いソックスで書かなければなりませんでした。そして、私たちはそれを好きだった。

Task.Run()きれいに行う必要があります。

private RelayCommand _DeleteCommand; 
public RelayCommand DeleteCommand 
{ 
    get 
    { 
     return _DeleteReferenceCommand 
      ?? (_DeleteReferenceCommand = new RelayCommand(
      () => 
      { 
       GridViewVisibility = false; 

       Task.Run(() => 
       { 
        // Long process.... 
       }); 

      }, 
      () => { return ReferencesGridWithPicsUC.SelectedReference != null; } 
     )); 
    } 
} 

あなたはそれがない推測何をしないんだDispatcher.BeginInvoke()事。これは、通常、UI以外のスレッドがUIに触れると、例外が発生するということです。それは許可されていません。 Dispatcher.Invoke()またはDispatcher.BeginInvoke()をUIスレッド外から呼び出すと、UIスレッドの中でにUIタッチコードが実行されます。 でコントロールが更新され、PropertyChangedというプロパティに更新された場合は、バックグラウンドで呼び出しが行われます。それはそのような共通のパターンです、彼らはそれをフレームワークに組み込みました。ただし、INotifyCollectionChangedが呼び出されません。 ObservableCollectionに商品を追加する場合は、Invokeが必要です。 ObservableCollectionを新しいものに置き換えるだけであればOKですが、大量のコレクションでUIが少し反応しなくてもOKです。それは実際にはより速いですが、スピナーが回転している間にアイテムが1つずつリストに追加されるのを見た場合とは違った感じになります。人間の心は面白いものです。

+0

この詳細な説明ありがとうございましたEd! :) –

関連する問題