【问题标题】:RadBusyIndicator not showing PRISM/MEF/WPF from ViewModelRadBusyIndi​​cator 未从 ViewModel 显示 PRISM/MEF/WPF
【发布时间】:2013-01-29 07:12:13
【问题描述】:

我正在为我的 WPF 应用程序使用 MVVM/PRISM/MEF。它有一个带有多条记录的 DataGrid,当双击一行时,一个单独的视图被添加到上面有多个控件的区域,新屏幕的控件初始化大约需要 10 秒,这就是为什么我想在那期间显示 RadBusyIndi​​cator时间。

遵循 XAML

<!-- This is Main View -->
<!-- Module: MainModule, ViewModel: MainViewViewModel -->
<telerik:RadBusyIndicator IsBusy="{Binding IsBusy}" BusyContent="{Binding BusyContent}">
<!-- All PRISM regions are here -->
</telerik:RadBusyIndicator>

它的视图模型是

class MainViewViewModel : ViewModelBase
    {
        ImportingConstructor]
        public MainViewViewModel(IEventAggregator eventAggregator, IRegionManager regionManager, IServiceLocator serviceLocator)
            :base(eventAggregator, regionManager, serviceLocator)
        {
            eventAggregator.GetEvent<BusyStateChangedEvent>().Subscribe(OnBusyStateChanged,ThreadOption.BackgroundThread);
        }

        #region BusyStateChanged

        private void OnBusyStateChanged(bool newState)
        {
            IsBusy = newState;
        }

        #endregion
}

而在其他视图中双击DataGrid行时调用ViewModelBase函数,如下

public class ViewModelBase
{
        private NavigationItem global_navItem = null;

        public virtual void OnNavigationItemChanged(NavigationItem item)
        {
            changeNav = true;
            global_navItem = item;

            //Firing event to change the state
            EventAggregator.GetEvent<BusyStateChangedEvent>().Publish(true);

            //Using BackgroundWorker, but its not showing any Busy Indicator as well
            var bw = new BackgroundWorker();
            bw.DoWork += bw_DoWork;
            bw.RunWorkerCompleted += bw_RunWorkerCompleted;

            bw.RunWorkerAsync();
        }

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //Setting busy indicator to false
            EventAggregator.GetEvent<BusyStateChangedEvent>().Publish(false);
        }

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            //DisplayView function is taking too long
            if (global_navItem != null) this.DisplayView(global_navItem);
        }
}

public void DisplayView(NavigationItem item)
        {
                    try
                    {
                        //This call is taking long as it initializes the View
                        MyCustomeUserControl view = this.ServiceLocator.GetInstance<MyCustomeUserControl>(item.viewName);

                        view.Region = this.Region;
                    }catch(Exception e)
                    {
                    }                   
        }

事件被正确触发并且视图显示正确,但我的问题是忙碌指示器根本没有显示,当我双击 DataGrid 行时,GUI 变得无响应,并且在一段时间后出现了新视图。我怀疑这是 GUI 线程忙的问题,但是我可以做些什么来避免这种情况,我已经使用了BackgroudWorker?

编辑

1- 我正在为 IsBusy 属性引发 PropertyChanged 事件。我已经在事件订阅中尝试了 Thread 的所有选项。即Thread.BackgroundThread、Thread.UIThread 和Thread.PublisherThread。但没有变化。

2- 我测试了Thread.Sleep 而不是bw_DoWork 中的DisplayView,并且它正确显示RadBusyIndicator,所以这意味着GUI 控件正在GUI 线程中初始化,无论我是否创建了@987654333 @为它。

【问题讨论】:

  • 您发布的代码似乎没问题。只是一个愚蠢的问题(我无意伤害)您是否为 IsBusy 属性引发 PropertyChanged 事件?我只需要问...还有一件事...here 它说 如果您需要能够在收到事件时更新用户界面元素,请订阅以在用户界面上接收事件线程。 所以如果我是你,我会在订阅 BusyStateChangedEvent 时使用 ThreadOption.UIThread 切换 ThreadOption.BackgroundThread。但这些只是想法......
  • 感谢@ViktorLaCroix,是的,我正在为IsBusy Property 发起PropertyChanged 事件。而且我已经在事件订阅中尝试了 Thread 的所有选项。即Thread.BackgroundThread、Thread.UIThread 和Thread.PublisherThread。但没有变化。
  • 现在它变得有趣了 :) 那么请您使用这些附加信息编辑您的问题吗?并且请不要忘记,当您使用 Thread.Sleep 切换 DoWork 方法的主体时一切正常
  • 我要尝试的最后一件事是在后台创建视图实例,然后将其作为 DoWork 的结果传递,并将其添加到 WorkerCompleted 方法中的区域。如果它与 DoWork 中的 Thread.Sleep 一起使用,则可能意味着您正在后台为 UIThread 创建一些工作......它可能会将其添加到该区域。如果这没有帮助,那我就帮不了你了。
  • 我分析的是ServiceLocator 需要时间来初始化GUI 控件,而不是向Region 调用添加视图。所以我认为这不会有什么不同。

标签: wpf mvvm prism backgroundworker busyindicator


【解决方案1】:

如果您使用Thread.Sleep(5000) 而不是this.DisplayView(global_navItem),会出现指示符吗?

我假设显示视图将使用 UI 线程,无论您是否使用 BackgroundWorker,这都会阻塞 UI。

编辑:

由于您的 UI 加载操作似乎阻塞了 UI 线程,因此您的 BusyIndi​​cator,您可以尝试将其中一个托管在不同的线程中。在this article 中解释了一种方法。

【讨论】:

  • 感谢您的建议,是的,我尝试使用 Thread.Sleep 并正确显示 BusyIndi​​cator。 :(。在加载繁重的 GUI 时显示繁忙指示器的任何其他方法可能是什么?
  • 这并不容易。有一些方法可以在 UI 线程之外的不同线程中显示 BusyIndi​​cator。我会尽快添加答案的链接。
【解决方案2】:

终于找到了解决办法。可以查看以下帖子以供参考。我已经使用本文中讨论的方法实现了一个带有 RadBusyIndi​​cator 的子无铬窗口。

Creating multiple UI Threads in WPF

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-06
    • 1970-01-01
    • 2014-09-17
    • 2013-10-31
    相关资源
    最近更新 更多