2011-10-19 6 views
0

私はWPFアプリケーションを持っていて、MVVMを使用しています。私の見解モデルでWPFのPropertyChangedとBindの間のカーソルを待ちます。

私が持っている:

private string logs; 
    public string Logs 
    { 
     get { return logs; } 
     set 
     { 
      logs = value; 
      OnPropertyChanged("Logs"); 
     } 
    } 

    private void ExecLoadData() 
    { 
     using (new WaitCursor()) 
      Logs = LogFile.ReturnContent(); 
    } 

    private RelayCommand loadData; 
    public ICommand LoadData 
    { 
     get 
     { 
      if (loadData == null) 
       loadData = new RelayCommand(param => this.ExecLoadData()); 
      return loadData; 
     } 
    } 

ビューでは:私は、ページ上のデータのOnPropertyChangedをの撮影とプレゼンテーションの間の遅延を発生することを気づい

<i:Interaction.Triggers> 
    <i:EventTrigger EventName="Loaded"> 
     <i:InvokeCommandAction Command="{Binding LoadData}" /> 
    </i:EventTrigger> 
</i:Interaction.Triggers> 

画面に表示されるデータに待機カーソルを表示する方法が必要です。

すでにWaitCursor()メソッドが実装されていますが、待機カーソルは、データファイルがメモリにロードされるまで、つまりデータがメモリにロードされてからカーソルが正常なページに表示されるまで表示されます。

ヒント?

編集(AngelWPFの助けを借りて、最終的な解決策):

private Boolean isBusy = false; 
    public Boolean IsBusy 
    { 
     get { return isBusy; } 
     set 
     { 
      if (isBusy == value) 
       return; 
      isBusy = value; 
      OnPropertyChanged("IsBusy"); 
     } 
    } 

    private string logs; 
    public string Logs 
    { 
     get { return logs; } 
     set 
     { 
      logs = value; 
      OnPropertyChanged("Logs"); 
     } 
    } 

    public void ExecuteBusy(DoWorkEventHandler doWorkEventHandler) 
    { 
     IsBusy = true; 

     var backgroundWorker = new BackgroundWorker(); 
     backgroundWorker.DoWork += doWorkEventHandler; 
     backgroundWorker.RunWorkerCompleted += (sender, e) => { IsBusy = false; }; 
     backgroundWorker.RunWorkerAsync(); 
    } 

    protected override void ExecLoadData() 
    { 
     LoadLogs(); 
    } 

    private void LoadLogs() 
    { 
     ExecuteBusy((sender, e) => 
     { 
      Logs = LogFile.ReturnContent(); 
     }); 
    } 

<Page.Resources> 
    <ut:BooleanVisibilityConverter x:Key="BooleanVisibilityConverter" /> 
</Page.Resources> 

<Page.DataContext> 
    <vm:ManutencaoMonitoracaoLogsViewModel/> 
</Page.DataContext> 

<i:Interaction.Triggers> 
    <i:EventTrigger EventName="Loaded"> 
     <i:InvokeCommandAction Command="{Binding LoadData}" /> 
    </i:EventTrigger> 
</i:Interaction.Triggers> 

<Grid> 

    <TextBox Text="{Binding Logs, Mode=OneWay}" VerticalScrollBarVisibility="Auto" IsReadOnly="True" BorderBrush="White" /> 

    <Border BorderBrush="Black" BorderThickness="1" Background="#80DBDBDB" Grid.RowSpan="3" 
      Visibility="{Binding IsBusy, Converter={StaticResource BooleanVisibilityConverter}}"> 
     <Grid> 
      <ct:LoadingAnimation HorizontalAlignment="Center" VerticalAlignment="Center"/>    
     </Grid> 
    </Border> 

</Grid> 

答えて

0

あなたはUI ExecelLoadData(から呼ぶのですか、モデルの実装にカーソルへの参照を持つべきではありません)方法?電話をかける前にカーソルの状態を変更し、返信時に交換することをお勧めします。

+0

こんにちはマックホー!私はより多くのコードを投稿する投稿を編集します。だから、私はちょうどビューにイベントを "ポストバインディング"を取得する必要があります知っている必要があります。 – Alexandre

0

これは、AsyncWorkerと呼ばれる何かを介して重い機能を編成する必要があります。これは、バックグラウンドワーカーを使用した非同期コマンド実行です。これは、ビューモデルから真であるとして起動されるワンタイムトリガフラグを持ち、重い機能がそれに委任されたときにウィンドウのアドナーで実行されます。機能が実行されているとき、アニメーションは、おそらく遅れた機能が実行中であり、彼/彼女が待つべきであることをユーザに示す。その後、代理人が終了すると、AsyncWorker自体がアニメーションを非表示にし、Pageを適切にユーザーに表示します。

http://elegantcode.com/2009/08/21/a-simple-wpf-loading-animation/

私は基本的に私たちがtrueにAsyncWorker.StartOperationを設定するとき、私たちはアニメーションのストーリーボードと親パネルのadornerをレンダリングする...それがこの方法を行うことができます

Characteristics of `AsyncWorker` 
    1. It is a Control that runs an animation such as 
     a neverending progressing progress bar 
     or rotating circles etc. in the adorner of the UI. 
    2. It accepts the parent panel on which the waiter animation is shown. 
    3. It has a boolean dependency property say "StartOperation".   
     When this changes to true we start the animation. 
     When true this also begins excuting the `WorkerDelegateCommand` given below. 
    4. It also has a ICommand dependency property called "WorkerDelegateCommand" 
     This will be supplied from your `ViewModel`. 
     It will hold the time consuming operation as a delegate. 

を想像することができますし、 バックグラウンドワーカーをキックオフします。このバックグラウンドワーカーは、別のスレッドでWorkerDelegateCommandを実行します。したがって、あなたの遅い操作はUI以外のスレッドで実行されます。一方、非同期作業者アニメーションは実行を継続します。 WorkerDelegateCommandデリゲートが遅い作業を終了すると、バックグラウンドウォーカーDoWorkがコール終了し、RunCompletedが呼び出されます。ここではStartOperationをfalseに設定します。ブトンはボタンが含まれているグリッドを、クリックされたときに我々は、このAsyncWorkerを設定することができます

方法がこの方法です...だから、上記の例では、

<Grid> 
     <Button Content="Do some slow work" 
       Command="{Binding RunAsyncWorkerCommand}" /> 
     <AsyncWorker 
       ParentPanel="{Binding RelativeSource={RelativeSource 
             AncestorType={x:Type Grid}}}" 
       StartOperation="{Binding StartSlowWork, Mode=TowWay}" 
       WorkerDelegateCommand="{Binding MySlowDelegateCommand}" 
       Visibility="Collapsed" /> 
    </Grid> 

は、ウェイターのアニメーションを表示し、実行を開始します遅い操作。このために、DataContextまたはViewModelには3つのプロパティが必要です...

1. `StartSlowWork` - A boolean flag to start AsyncWorker which is TwoWay bound. 
2. `RunAsyncWorkerCommand` - Command to set the `StartSlowWork` flag to true. 
3. `MySlowDelegateCommand` - Command to execute slow work. 

これを実行すると、実行速度の遅い操作をすべてAsyncWorkerに移動できます。

+0

こんにちは天使、素敵な例、ありがとう!だから、私はスクリーンのレンダリングのこの始まりと終わりをどう扱うべきかわかりませんが、あなたはその例を持っていますか?つまり、データバインディングの開始と終了のイベントですか? – Alexandre

+0

私の編集をご覧ください。これはあなたの単純な要件のためにあまりにも多く見えるかもしれませんが、私はそれをやっている方法です。そして、これまでのところ不満はない! :-) –

+0

こんにちは天使、私はあなたの視点を理解しましたが、私は質問があります:重い活動が完了したと仮定し、この活動の結果は何かの1.000項目のリストです。 したがって、私が言ったように、WPFでは、ビューバインディングを介してビューモデルのプロパティ割り当てと画面のプロパティ表示値の間に遅延があります。私は、この実装でも、プロパティ値をビジュアル要素に転送するためにデータバインドに必要な時間であるため、遅延が存在し続けると考えています。 – Alexandre

関連する問題