第一次在 Prism(MEF v.5)wpf 应用程序中加载视图非常慢
View is loading very slow for the first time in a Prism(MEF v.5) wpf application
第一次加载视图需要 2-5 秒依赖于视图内容。但第二次是立即加载。
大多数"heavy"内容只有一个RadGridView,但是程序集和所有数据(空数据)在初始化时已经从数据库加载。
private void Navigate(NavigateInfo info)
{
_workingNavigateInfo = info;
_regionManager.RequestNavigate(MAIN_REGION_NAME, new Uri(info.NextViewName, UriKind.Relative), NavigationCompleted);
}
我在应用程序初始化过程中初始化了一个视图和视图模型
var jobB = _container.GetExportedValue<ViewB>();
var jobBModel = _container.GetExportedValue<ViewBModel>();
jobB.DataContext = jobBModel;
这是我的 ViewModels 的例子
[Export]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ViewBModel : NavigationViewModel
{
private readonly IRegionManager _regionManager;
private readonly NavigationService<ViewB> _navigation;
[ImportingConstructor]
public ViewBModel(IRegionManager regionManager)
{
this._regionManager = regionManager;
this.GotoA = new DelegateCommand<object>(this.ExecuteGotoA);
this.GotoBack = new DelegateCommand<object>(this.ExecuteGotoBack);
_navigation = new NavigationService<ViewB>(regionManager);
}
public DelegateCommand<object> GotoA { get; private set; }
public DelegateCommand<object> GotoBack { get; private set; }
private void ExecuteGotoA(object notused)
{
_navigation.NavigateToPage("ViewA");
}
private void ExecuteGotoBack(object notused)
{
_navigation.NavigateBack();
}
}
并查看
[Export]
public partial class ViewB : UserControl
{
public ViewB()
{
InitializeComponent();
}
}
由于导航在没有 [Export("ViewB", typeof(ViewB))] 属性的情况下无法工作,因此我创建了一个新的 MefServiceLocatorAdapter 以避免未找到错误
public class MyMefServiceLocatorAdapter : MefServiceLocatorAdapter
{
CompositionContainer _container;
public MyMefServiceLocatorAdapter(CompositionContainer container): base(container)
{
_container = container;
}
protected override object DoGetInstance(Type serviceType, string key)
{
IEnumerable<Lazy<object, object>> exports = this._container.GetExports(serviceType, null, key).ToList();
if ((exports != null) && (exports.Count() > 0))
{
// If there is more than one value, this will throw an InvalidOperationException,
// which will be wrapped by the base class as an ActivationException.
return exports.Single().Value;
}
var extended = this._container.Catalog.Where(x => x.ExportDefinitions.Any(y => y.ContractName.EndsWith(key))).ToList();
if ((extended != null) && (extended.Count() > 0))
{
var type = ReflectionModelServices.GetPartType(extended.Single()).Value;
var serviceTypeIdentity = AttributedModelServices.GetTypeIdentity(type);
return _container.GetExports(serviceType, null, serviceTypeIdentity).First().Value;
}
throw new ActivationException(FormatActivationExceptionMessage(new CompositionException("Export not found"), serviceType, key));
}
}
我找到了一篇如何使导航更快的好文章Navigate faster with Prism and WPF
但 id 没有给我任何改进。
我使用了性能分析器 Redgate 的 ANTS,它向我展示了在第一次导航期间方法 LoadContent 和 RequestCanNavigateFromOnCurrentlyActiveViewModel(不明白为什么)运行 1 sec,但是第二次用了不到 1 毫升。
我尝试在初始化期间执行 LoadContent 并添加到区域,但我无法加载所有视图并将其添加到区域。不幸的是,这个策略并没有给我任何改进。
第一次 运行 速度慢的原因是因为 Telerik 网格。渲染网格并加载所有程序集后,第二次加载速度会快得多。我几乎可以向您保证,如果您从视图中删除 Telerik 网格并 运行 您的应用程序,视图将加载得更快。
我同意布赖恩的意见。您正在使用 Telerik,如果您使用 DevExpress 的类似产品(我在这里说的是经验),您会遇到同样的事情,这与 Prism 无关。
第一次加载视图需要 2-5 秒依赖于视图内容。但第二次是立即加载。 大多数"heavy"内容只有一个RadGridView,但是程序集和所有数据(空数据)在初始化时已经从数据库加载。
private void Navigate(NavigateInfo info)
{
_workingNavigateInfo = info;
_regionManager.RequestNavigate(MAIN_REGION_NAME, new Uri(info.NextViewName, UriKind.Relative), NavigationCompleted);
}
我在应用程序初始化过程中初始化了一个视图和视图模型
var jobB = _container.GetExportedValue<ViewB>();
var jobBModel = _container.GetExportedValue<ViewBModel>();
jobB.DataContext = jobBModel;
这是我的 ViewModels 的例子
[Export]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ViewBModel : NavigationViewModel
{
private readonly IRegionManager _regionManager;
private readonly NavigationService<ViewB> _navigation;
[ImportingConstructor]
public ViewBModel(IRegionManager regionManager)
{
this._regionManager = regionManager;
this.GotoA = new DelegateCommand<object>(this.ExecuteGotoA);
this.GotoBack = new DelegateCommand<object>(this.ExecuteGotoBack);
_navigation = new NavigationService<ViewB>(regionManager);
}
public DelegateCommand<object> GotoA { get; private set; }
public DelegateCommand<object> GotoBack { get; private set; }
private void ExecuteGotoA(object notused)
{
_navigation.NavigateToPage("ViewA");
}
private void ExecuteGotoBack(object notused)
{
_navigation.NavigateBack();
}
}
并查看
[Export]
public partial class ViewB : UserControl
{
public ViewB()
{
InitializeComponent();
}
}
由于导航在没有 [Export("ViewB", typeof(ViewB))] 属性的情况下无法工作,因此我创建了一个新的 MefServiceLocatorAdapter 以避免未找到错误
public class MyMefServiceLocatorAdapter : MefServiceLocatorAdapter
{
CompositionContainer _container;
public MyMefServiceLocatorAdapter(CompositionContainer container): base(container)
{
_container = container;
}
protected override object DoGetInstance(Type serviceType, string key)
{
IEnumerable<Lazy<object, object>> exports = this._container.GetExports(serviceType, null, key).ToList();
if ((exports != null) && (exports.Count() > 0))
{
// If there is more than one value, this will throw an InvalidOperationException,
// which will be wrapped by the base class as an ActivationException.
return exports.Single().Value;
}
var extended = this._container.Catalog.Where(x => x.ExportDefinitions.Any(y => y.ContractName.EndsWith(key))).ToList();
if ((extended != null) && (extended.Count() > 0))
{
var type = ReflectionModelServices.GetPartType(extended.Single()).Value;
var serviceTypeIdentity = AttributedModelServices.GetTypeIdentity(type);
return _container.GetExports(serviceType, null, serviceTypeIdentity).First().Value;
}
throw new ActivationException(FormatActivationExceptionMessage(new CompositionException("Export not found"), serviceType, key));
}
}
我找到了一篇如何使导航更快的好文章Navigate faster with Prism and WPF 但 id 没有给我任何改进。 我使用了性能分析器 Redgate 的 ANTS,它向我展示了在第一次导航期间方法 LoadContent 和 RequestCanNavigateFromOnCurrentlyActiveViewModel(不明白为什么)运行 1 sec,但是第二次用了不到 1 毫升。 我尝试在初始化期间执行 LoadContent 并添加到区域,但我无法加载所有视图并将其添加到区域。不幸的是,这个策略并没有给我任何改进。
第一次 运行 速度慢的原因是因为 Telerik 网格。渲染网格并加载所有程序集后,第二次加载速度会快得多。我几乎可以向您保证,如果您从视图中删除 Telerik 网格并 运行 您的应用程序,视图将加载得更快。
我同意布赖恩的意见。您正在使用 Telerik,如果您使用 DevExpress 的类似产品(我在这里说的是经验),您会遇到同样的事情,这与 Prism 无关。