我的XAML中有一个 please wait
TextBlock
,其Visibility
属性绑定到我的ViewModel上的IsBusy
属性(实现{ {1}})。一个单独的按钮启动一个长时间运行(2-3秒)的过程,如下所示:
INotifyPropertyChanged
但 IsBusy = true;
try
{
// Do some long-running process
}
finally
{
IsBusy = false;
}
消息永远不会出现。我假设操作在UI线程上运行,因此没有给它机会刷新?如果我在一个单独的线程上运行上面的代码, 可以工作,但我不希望用户在操作运行时做任何事情 - 我很高兴用户界面{{1} }。
如何显示 please wait
讯息?或者我会更好地在后台线程上运行它并(以某种方式)锁定UI持续时间?我正在使用.Net 4顺便说一句。
答案 0 :(得分:5)
你是对的,它没有更新,因为你在同一个线程上运行代码,所以在你的进程完成之后,渲染才会继续。
您说您没有使用后台线程,因为您不希望用户在操作运行时执行任何操作,但完全锁定您的应用程序绝不是一个好主意。
更好的解决方案是将Form / Window / UserControl / etc的IsEnabled
绑定到IsBusy
属性。然后当它变忙时,整个表单被禁用以防止用户修改它,同时不锁定你的应用程序。
答案 1 :(得分:1)
首先Visibility
属性不是bool
,所以如果要将bool
变量绑定到它,则需要使用IValueConverter
,其次,是的,你是对的虽然UI线程忙于长时间运行,但它不会执行任何其他操作,包括可见性更改。
我建议使用WPF Toolkit
BusyIndicator
期望放置自己的面板,它具有IsBusy bool
属性。
另外froozen UI不是用户友好的,通常我使用这个片段
IsBusy = true;
Task.Factory.StartNew(() =>
{
// Do work.
})
.ContinueWith(t=>IsBusy=false,
TaskScheduler.FromCurrentSynchronizationContext());
另请注意检查ContinueWith
方法中的错误,否则您将在Task
dispose上获得例外
答案 2 :(得分:0)
如果您在单独的线程上运行代码,您仍然可以通过Dispatcher.BeginInvoke Method访问用户界面。
if (!YOURCONTROL.Dispatcher.CheckAccess())
{
YOURCONTROL.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(delegate()
{
//do something with the control/form/...
}));
}
else
{
//update your control
}