2 Stimmen

Warum wird die Aktualisierung der Bindung bis zur Beendigung des Delegate Command verzögert? (MVVM)

Ich wende das MVVM-Muster an. Ich habe eine Schaltfläche, die, wenn sie angeklickt wird, einen delegierten Befehl in meinem ViewModel aufruft. Ganz am Anfang dieser Delegatenmethode setze ich einen Eigenschaftswert (WaitOn), der den Benutzer in der Benutzeroberfläche benachrichtigen soll, dass er warten soll, indem er ein animiertes Steuerelement anzeigt.

Die Bindung zur Anzeige des animierten Steuerelements wird jedoch erst dann aktualisiert, wenn der Delegat die Ausführung abgeschlossen hat, so dass die Wartezeit beendet ist. Warum geschieht dies und was sollte ich tun, um es zu umgehen?

Beispiel-XAML:

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

Schnipsel aus 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;
}

Und nun Code-Behind aus der XAML, um das ausgelöste Ereignis abzufangen:

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();
    }

6voto

Rory Punkte 2722

Wahrscheinlich wird die Bindung zwar aktualisiert, aber da Sie im UI-Thread "viele Dinge" erledigen, hat die Anwendung keine Chance, den Bildschirm zu aktualisieren. Sie sollten erwägen, die Verarbeitung in einen Hintergrund-Thread zu verlagern oder die Dispatcher.BeginInvoke() damit die Benutzeroberfläche aktualisiert werden kann und Ihre Wartenachricht angezeigt wird.

In WPF wird die Dispatcher Klasse hat eine statische CurrentDispatcher-Eigenschaft die Sie innerhalb des ViewModel verwenden können, um Aufgaben zu planen. Ihr DoStuff Methode würde etwa so aussehen:

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

In Silverlight können Sie auf den aktuellen Dispatcher zugreifen, indem Sie die Einsatz Klasse:

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

Nebenbei bemerkt, sollten Sie vielleicht die Möglichkeit nutzen, die BooleanToVisibilityConverter so dass Sie nur die OnWait Eigenschaft für die Bindung. Auch Ihr OnWait Setter derzeit Benachrichtigungen auslöst, auch wenn die Eigenschaft auf denselben Wert zurückgesetzt wird, sollten Sie es wie folgt implementieren:

public bool WaitOn
{
  get { return _waitOn; }
  set
  {
    if(value != _waitOn)
    {
      _waitOn = value;
      RaisePropertyChanged("WaitOn");
    }
  }
}

4voto

ml_black Punkte 361

Ich habe die Lösung von Rory mit ein paar Anpassungen zum Laufen gebracht. Am Ende habe ich dies getan:

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

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

Durch die Verwendung von "(Action)" zum Erstellen einer neuen Action, um den Code zu verpacken, musste ich nirgendwo einen Delegaten deklarieren, und die Verwendung der Priorität "Background" gab der Benutzeroberfläche die Möglichkeit, sich zu aktualisieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X