【发布时间】:2013-01-29 07:12:13
【问题描述】:
我正在为我的 WPF 应用程序使用 MVVM/PRISM/MEF。它有一个带有多条记录的 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 变得无响应,并且在一段时间后出现了新视图。我怀疑这是 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,是的,我正在为
IsBusyProperty 发起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