Data binding 为什么绑定刷新延迟到委托命令完成?(MVVM)

Data binding 为什么绑定刷新延迟到委托命令完成?(MVVM),data-binding,mvvm,refresh,inotifypropertychanged,Data Binding,Mvvm,Refresh,Inotifypropertychanged,我正在应用MVVM模式。我有一个按钮,单击该按钮时,将调用ViewModel中的委托命令。在委托方法的一开始,我设置了一个属性值(WaitOn),该属性值应该通过显示一个动画控件通知用户返回UI等待 但是,在委托完成执行之前,显示该动画控件的绑定不会刷新,此时等待已完成。为什么会发生这种情况?我应该如何解决 样本XAML: <Button Command="{Binding DoStuffCommand}" /> <ctl:MyAnimatedControl Name="ctl

我正在应用MVVM模式。我有一个按钮,单击该按钮时,将调用ViewModel中的委托命令。在委托方法的一开始,我设置了一个属性值(WaitOn),该属性值应该通过显示一个动画控件通知用户返回UI等待

但是,在委托完成执行之前,显示该动画控件的绑定不会刷新,此时等待已完成。为什么会发生这种情况?我应该如何解决

样本XAML:

<Button Command="{Binding DoStuffCommand}" />
<ctl:MyAnimatedControl Name="ctlWait" Caption="Please Wait..." 
Visibility="{Binding WaitNotification}" />
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;
}
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();
    } 
现在从XAML向后编码以捕获引发的事件:

<Button Command="{Binding DoStuffCommand}" />
<ctl:MyAnimatedControl Name="ctlWait" Caption="Please Wait..." 
Visibility="{Binding WaitNotification}" />
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;
}
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();
    } 

绑定很可能正在更新,但由于您正在UI线程上执行“大量工作”,应用程序没有机会更新屏幕。您应该考虑将处理移动到后台线程,或者使用<代码>分派器.RealNojKEK()/Cuffe >以便用户界面可以自由更新和显示等待消息。 在WPF中,
Dispatcher
类有一个静态变量,您可以从ViewModel中使用它来调度任务。您的
DoStuff
方法如下所示:

public void DoStuff()
{
  WaitOn = true;
  Dispatcher.CurrentDispatcher.BeginInvoke(() =>
    {
      //Do lots of stuff
      WaitOn = false;
    });
}
public bool WaitOn
{
  get { return _waitOn; }
  set
  {
    if(value != _waitOn)
    {
      _waitOn = value;
      RaisePropertyChanged("WaitOn");
    }
  }
}
在Silverlight中,您可以使用以下类访问当前调度程序:

另一方面,您可能希望使用,以便只需要绑定的
OnWait
属性。此外,您的
OnWait
setter当前正在触发通知,即使属性设置回相同的值,您也应该这样实现它:

public void DoStuff()
{
  WaitOn = true;
  Dispatcher.CurrentDispatcher.BeginInvoke(() =>
    {
      //Do lots of stuff
      WaitOn = false;
    });
}
public bool WaitOn
{
  get { return _waitOn; }
  set
  {
    if(value != _waitOn)
    {
      _waitOn = value;
      RaisePropertyChanged("WaitOn");
    }
  }
}

我确实让Rory的解决方案起作用了,只是做了一些调整。我最终做了这样的事:

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

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

使用“(Action)”创建新的操作来包装代码意味着我不必在任何地方声明委托,而使用“Background”的优先级使UI有机会进行更新。

感谢转换器上的信息。我一定会好好利用的。但是对于Dispatcher部分,从ViewModel内部看并不是那么简单。我的ViewModel的方法是从UI中的直接命令绑定调用的,因此在该方法开始之前,我无法控制事情。我看了这篇关于将Dispatcher与MVVM-->一起使用的有趣文章,我不确定它是否会在完成之前更新UI,因为它也会包装我的方法的全部内容。@ml\u black:我已经用几个示例更新了我的答案,这些示例介绍了如何从视图模型中使用Dispatcher。您的
DoStuff
方法仍然由UI线程调用,
WaitOn
在工作开始之前设置,但其他所有内容都通过dispatcher调用。我知道这个方法是有效的,因为我以前使用过它,但是如果它不适用于您,您可以使用手动创建的线程或线程池。您只需要小心地从后台线程设置
WaitOn
属性(以及UI可能绑定到的任何其他属性)。希望有帮助。谢谢。我在研究你的建议,但没有看到代码写得这么清楚。我有这个功能,但是,它不工作。我不知道这是否是因为我交给调度器的“很多东西”也会引发一个事件,视图正在代码隐藏中处理该事件。我会稍微更新一下代码示例。很高兴你让它工作起来了。只是想知道是否强制转换到
操作
是绝对必要的,我相信lambda语法会为您解决这个问题。。。