ml_*_*ack 2 data-binding refresh mvvm inotifypropertychanged
我正在应用MVVM模式.我有一个按钮,当点击它时,在我的ViewModel中调用一个委托命令.在该委托方法的最开始,我设置了一个属性值(WaitOn),它应该通过显示动画控件来通知UI中的用户等待.
但是,在委托完成执行之前,显示动画控件不会刷新的绑定,此时等待完成.为什么会发生这种情况,我应该怎么做才能解决它?
示例XAML:
<Button Command="{Binding DoStuffCommand}" />
<ctl:MyAnimatedControl Name="ctlWait" Caption="Please Wait..."
Visibility="{Binding WaitNotification}" />
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
现在从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();
}
Run Code Online (Sandbox Code Playgroud)
机会是绑定正在更新,但因为你在UI线程上做了很多东西,应用程序没有机会更新屏幕.您应该考虑将处理移动到后台线程或使用,Dispatcher.BeginInvoke()以便UI可以自由更新并显示您的等待消息.
在WPF中,Dispatcher该类具有静态CurrentDispatcher属性,您可以在ViewModel中使用该属性来计划任务.你的DoStuff方法看起来像这样:
public void DoStuff()
{
WaitOn = true;
Dispatcher.CurrentDispatcher.BeginInvoke(() =>
{
//Do lots of stuff
WaitOn = false;
});
}
Run Code Online (Sandbox Code Playgroud)
在Silverlight中,您可以使用Deployment类访问当前的调度程序:
public void DoStuff()
{
WaitOn = true;
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
//Do lots of stuff
WaitOn = false;
});
}
Run Code Online (Sandbox Code Playgroud)
另外,您可能希望使用BooleanToVisibilityConverter,以便只需要OnWait绑定属性.此外,OnWait即使属性设置回相同的值,您的setter当前也会触发通知,您应该像这样实现它:
public bool WaitOn
{
get { return _waitOn; }
set
{
if(value != _waitOn)
{
_waitOn = value;
RaisePropertyChanged("WaitOn");
}
}
}
Run Code Online (Sandbox Code Playgroud)