RadBusyIndicator не показывает PRISM/MEF/WPF из ViewModel
Я использую MVVM/PRISM/MEF для своего приложения WPF. Он имеет одну DataGrid с несколькими записями, и когда дважды щелкается одна строка, в область с несколькими элементами управления добавляется отдельное представление, инициализация элементов управления занимает около 10 секунд для нового экрана, поэтому я хочу показать RadBusyIndicator во время этого время.
Следуя в 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, но что я могу сделать, чтобы избежать этого, я использовал BackgroudWorker
уже?
РЕДАКТИРОВАТЬ
1- Я поднимаю событие PropertyChanged для свойства IsBusy. и я уже перепробовал все опции для темы в подписке на событие. т.е. Thread.BackgroundThread
, Thread.UIThread
а также Thread.PublisherThread
, но без изменений.
2- Я проверил Thread.Sleep
скорее что DisplayView
в bw_DoWork
и его показ RadBusyIndicator
правильно, это означает, что элементы управления GUI инициализируются в потоке GUI, независимо от того, я создал BackgroundWorker
для этого.
2 ответа
Наконец-то я нашел решение. Для справки можно посмотреть следующий пост. Я реализовал дочернее окно без хрома с RadBusyIndicator, используя подход, описанный в этом посте.
Создание нескольких потоков пользовательского интерфейса в WPF
Появится ли индикатор, если вы используете Thread.Sleep(5000)
вместо this.DisplayView(global_navItem)
?
Я предполагаю, что показ представления будет использовать поток пользовательского интерфейса, и это заблокирует пользовательский интерфейс, независимо от того, используете ли вы BackgroundWorker
или нет.
Редактировать:
Похоже, что ваша операция загрузки пользовательского интерфейса блокирует поток пользовательского интерфейса, а также ваш BusyIndicator, вы можете попробовать разместить один из них в другом потоке. Подход объясняется в этой статье.