繁体   English   中英

尝试在长时间运行的操作中在WPF中显示“请稍候”消息

[英]Trying to display a “please wait” message in WPF during a long-running operation

我在XAML中有一个TextBlockplease wait ,其Visibility属性绑定到ViewModel(实现INotifyPropertyChanged )上的IsBusy属性。 一个单独的按钮将启动一个长时间运行(2-3秒)的过程,如下所示:

IsBusy = true;

try
{
    // Do some long-running process
}

finally
{
    IsBusy = false;
}

但是please wait消息永远不会出现。 我假设该操作正在UI线程上运行,因此没有给它刷新的机会吗? 如果我在单独的线程上运行上述代码,它确实可以工作,但是我不希望用户在操作运行时做任何事情-我很高兴UI可以freeze

如何显示please wait消息? 还是我会更好地在后台线程上运行它并(在某种程度上)在持续时间内锁定UI? 我正在使用.Net 4 btw。

您是正确的,它不会更新,因为您是在同一线程上运行代码,因此直到过程完成后才继续渲染。

您说您不使用后台线程是因为您不希望用户在操作运行时执行任何操作,但是完全锁定这样的应用程序从来不是一个好主意。

更好的解决方案是将Form / Window / UserControl / etc的IsEnabled绑定到IsBusy属性。 然后,当它变得繁忙时,整个表单将被禁用,以防止用户修改它,而不会锁定您的应用程序。

首先, 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上获得异常

如果在单独的线程上运行代码,仍然可以通过Dispatcher.BeginInvoke方法访问UI。

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
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM