WPFUI报错
page does not have a parameterless constructor. If you are using Wpf.Ui.IPageService do not navigate initially and don't use Cache or Precache
问题原因
WPFUI中的NavigationView只支持导航页面的无参构造函数或含一个dataContext的有参构造函数。由于在View的构造函数中注入了一些服务,导致View创建失败,WPFUI报错。
问题处理
查看非常堆栈,找报错位置:- 在 Wpf.Ui.Controls.NavigationViewActivator.CreateInstance(Type pageType, Object dataContext) 在 Wpf.Ui.Controls\NavigationViewActivator.cs 中: 第 37 行
- 在 Wpf.Ui.Controls.NavigationView.GetPageInstanceFromCache(Type targetPageType) 在 Wpf.Ui.Controls\NavigationView.cs 中: 第 1206 行
- 在 Wpf.Ui.Controls.NavigationCache.Remember(Type entryType, NavigationCacheMode cacheMode, Func`1 generate) 在 Wpf.Ui.Controls\NavigationCache.cs 中: 第 25 行
- 在 Wpf.Ui.Controls.NavigationView.GetNavigationItemInstance(INavigationViewItem viewItem) 在 Wpf.Ui.Controls\NavigationView.cs 中: 第 1185 行
- 在 Wpf.Ui.Controls.NavigationView.NavigateInternal(INavigationViewItem viewItem, Object dataContext, Boolean addToNavigationStack, Boolean isBackwardsNavigated) 在 Wpf.Ui.Controls\NavigationView.cs 中: 第 1131 行
- 在 Wpf.Ui.Controls.NavigationViewItem.OnClick() 在 Wpf.Ui.Controls\NavigationViewItem.cs 中: 第 314 行
- ...
复制代码 看源码,找解决方案:- private object GetNavigationItemInstance(INavigationViewItem viewItem)
- {
- if (viewItem.TargetPageType is null)
- {
- throw new InvalidOperationException(
- $"The {nameof(viewItem)}.{nameof(viewItem.TargetPageType)} property cannot be null."
- );
- }
- if (_serviceProvider is not null)
- {
- return _serviceProvider.GetService(viewItem.TargetPageType)
- ?? throw new InvalidOperationException(
- $"{nameof(_serviceProvider)}.{nameof(_serviceProvider.GetService)} returned null for type {viewItem.TargetPageType}."
- );
- }
- if (_pageService is not null)
- {
- return _pageService.GetPage(viewItem.TargetPageType)
- ?? throw new InvalidOperationException(
- $"{nameof(_pageService)}.{nameof(_pageService.GetPage)} returned null for type {viewItem.TargetPageType}."
- );
- }
- return _cache.Remember(
- viewItem.TargetPageType,
- viewItem.NavigationCacheMode,
- ComputeCachedNavigationInstance
- )
- ?? throw new InvalidOperationException(
- $"Unable to get or create instance of {viewItem.TargetPageType} from cache."
- );
- object? ComputeCachedNavigationInstance() => GetPageInstanceFromCache(viewItem.TargetPageType);
- }
复制代码 可以看到,假如提供了serviceProvider或者pageService,就可以通过容器获取View实例,不需要通过NavigationViewActivator.CreateInstance创建实例了。
提供ServiceProvider,比方使用Prism:- public class PrismServiceProvider : IServiceProvider
- {
- private readonly IContainerProvider _containerProvider;
- public PrismServiceProvider(IContainerProvider containerProvider)
- {
- _containerProvider = containerProvider;
- }
- public object GetService(Type serviceType)
- {
- return _containerProvider.Resolve(serviceType);
- }
- }
复制代码 WPFUI中未提供默认的IPageService实现,但demo.mvvm中提供了基于IServiceProvider的实现,可以参考。本文基于Prism实现:- public class PageService : IPageService
- {
- private readonly IContainerProvider _containerProvider;
- public PageService(IContainerProvider containerProvider)
- {
- _containerProvider = containerProvider;
- }
- public T GetPage<T>() where T : class
- {
- if (!typeof(FrameworkElement).IsAssignableFrom(typeof(T)))
- throw new InvalidOperationException("The page should be a WPF control.");
- return (T)_containerProvider.Resolve(typeof(T));
- }
- public FrameworkElement GetPage(Type pageType)
- {
- if (!typeof(FrameworkElement).IsAssignableFrom(pageType))
- throw new InvalidOperationException("The page should be a WPF control.");
- return _containerProvider.Resolve(pageType) as FrameworkElement;
- }
- }
复制代码 最后一步,将PrismServiceProvider、PageService注入容器,并通过INavigationService为NavigationView设置IServiceProvider和IPageService:- // App.xaml.cs
- protected override void RegisterTypes(IContainerRegistry containerRegistry)
- {
- var serviceProvider = new PrismServiceProvider(Container);
- containerRegistry.RegisterInstance<IServiceProvider>(serviceProvider);
- containerRegistry.RegisterSingleton<IPageService, PageService>();
- containerRegistry.RegisterSingleton<INavigationService, NavigationService>();
- }
- // MainWindow.xaml.cs
- public MainWindow(INavigationService navigationService,
- IPageService pageService,
- ISnackbarService snackbarService)
- {
- InitializeComponent();
- navigationService.SetPageService(pageService);
- navigationService.SetNavigationControl(NavigationView);
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |