Question

I am using MVVM/PRISM/MEF for my WPF application. It has one DataGrid with multiple records, and when one row is double clicked a separate view is added to region with multiple controls on it, the initialization of controls takes about 10 seconds for new screen, so thats why I want to show RadBusyIndicator during that time.

Following in the XAML

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

Its view model is

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
}

And in other view when DataGrid row is double clicked ViewModelBase function is called, as follows

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)
                    {
                    }                   
        }

Events are being fired correctly and view is displayed correctly, but my problem is that Busy indicator is not shown at all, when I double click on DataGrid row the GUI become unresponsive, and after some time the new view appears. I am in doubt that this is problem of GUI thread being busy, but what can I do to avoid this, I have used BackgroudWorker already?

EDIT

1- I am raising PropertyChanged event for IsBusy Property. and I have already tried all options for Thread in event subscription. i.e. Thread.BackgroundThread, Thread.UIThread and Thread.PublisherThread. but no change.

2- I have tested Thread.Sleep rather that DisplayView in bw_DoWork, and its showing RadBusyIndicator properly, so it means that GUI controls are being initialized in GUI thread, no matter I have created a BackgroundWorker for it.

Was it helpful?

Solution 2

Finally I have found a solution. For reference following post can be seen. I have implemented a child chrome-less window with RadBusyIndicator using the approach discussed in this post.

Creating multiple UI Threads in WPF

OTHER TIPS

Would the indicator appear if you use Thread.Sleep(5000) instead of this.DisplayView(global_navItem)?

I assume showing the view will use the UI thread and this will block the UI no matter you use a BackgroundWorker or not.

Edit:

As it seems like your UI loading operation blocks the UI thread and so your BusyIndicator, you can try to host one of them in a different thread. An approach is explained in this article.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top