2

MVVMパターンを適用しています。クリックすると、ViewModelでデリゲートコマンドを呼び出すボタンがあります。そのデリゲートメソッドの最初に、アニメーション化されたコントロールを表示して待機するようにUIにユーザーに通知するプロパティ値(WaitOn)を設定しました。

ただし、そのアニメーション化されたコントロールを表示するためのバインディングは、デリゲートが実行を完了するまで更新されません。実行が完了すると、待機が完了します。なぜこれが発生し、それを回避するにはどうすればよいですか?

サンプルXAML:

<Button Command="{Binding DoStuffCommand}" />
<ctl:MyAnimatedControl Name="ctlWait" Caption="Please Wait..." 
Visibility="{Binding WaitNotification}" />

ViewModelからのスニペット:

public bool WaitPart1On
{
  get { return _waitPart1On; }
  set
  {
    _waitPart1On = value;
    if (_waitPart1On == true)
    {
      WaitNotification = "Visible";
    }
    else
    {
      WaitNotification = "Hidden";
    }
    RaisePropertyChanged("WaitPart1On");
  }
}

public string WaitNotification
{
  get { return _waitNotification; }
  set
  {
    _waitNotification = value;
    RaisePropertyChanged("WaitNotification");
  }
}


public void DoStuff()
{
  WaitPart1On = true;
  //Do lots of stuff (really, this is PART 1)
  //Notify the UI in the calling application that we're finished PART 1
  if (OnFinishedPart1 != null)
  {
    OnFinishedPart1(this, new ThingEventArgs(NewThing, args));
  }
  WaitPart1On = false;
}

そして今、発生したイベントをキャッチするためにXAMLからコードビハインドします。

public void Part1FinishedEventHandler(NewThing newThing, ThingEventArgs e)
    {
      //at this point I expected the WaitPart1On to be set to false
      //I planned to put a new wait message up (WaitPart2)
      FinishPart2();
    } 
4

2 に答える 2

6

バインディングが更新されている可能性がありますが、UIスレッドで「多くのこと」を実行しているため、アプリケーションは画面を更新する機会を得ていません。Dispatcher.BeginInvoke()UIが自由に更新され、待機メッセージが表示されるように、処理をバックグラウンドスレッドに移動するか、を使用することを検討する必要があります。

WPFでは、Dispatcherクラスには静的なCurrentDispatcherプロパティがあり、ViewModel内からタスクをスケジュールするために使用できます。メソッドDoStuffは次のようになります。

public void DoStuff()
{
  WaitOn = true;
  Dispatcher.CurrentDispatcher.BeginInvoke(() =>
    {
      //Do lots of stuff
      WaitOn = false;
    });
}

Silverlightでは、 Deploymentクラスを使用して現在のディスパッチャーにアクセスできます。

public void DoStuff()
{
  WaitOn = true;
  Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
      //Do lots of stuff
      WaitOn = false;
    });
}

ちなみに、バインディングのプロパティのみが必要になるように、BooleanToVisibilityConverterを利用することもできます。OnWaitまた、OnWaitプロパティが同じ値に戻されている場合でも、セッターは現在通知を発行しています。次のように実装する必要があります。

public bool WaitOn
{
  get { return _waitOn; }
  set
  {
    if(value != _waitOn)
    {
      _waitOn = value;
      RaisePropertyChanged("WaitOn");
    }
  }
}
于 2010-02-22T17:19:49.967 に答える
4

少し調整を加えて、Roryのソリューションを機能させました。私はこれをすることになった:

public void DoStuff() 
{ 
  WaitPart1On = true; 
  Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, (Action)(() =>

    { 
      //Do lots of stuff 
      WaitPart1On = false; 
    }); 
}

「(Action)」を使用してコードをラップする新しいアクションを作成することは、どこにもデリゲートを宣言する必要がないことを意味し、「Background」の優先度を使用すると、UIが更新される可能性があります。

于 2010-02-24T16:35:14.660 に答える