第一次在 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 无关。