我有一个Prism 7/ WPF / MVVM应用程序,在具有视图模型的视图中配置了AutowireViewModel="True“。我的大多数视图模型都有我在Prism统一容器中配置的依赖项,并且这些依赖项被注入到viewmodel结构器中。我没有在任何地方的代码中显式地创建视图/视图模型的实例。我也不设置XAML中的数据上下文,即使用DataContext元素或d:DataContext)。XAML中唯一的引用是视图(即HamburgerMenu控件的一部分)。
除了每个视图/视图模型总是因为某种原因被构造两次之外,所有这些都很正常,不管这是主窗口,还是模块中的视图。我在模块管理器中放置了断点(只被击中一次)--以及视图构造函数和视图模型构造函数,它们都被击中了两次。下面是App类的一些代码,以及在运行时加载而不是按需加载的名为消息传递的模块的代码/view/viewmodel。由于希望尽可能多地使用MVVM模式,所以视图后面的代码非常少。注意:我试着看看这是否仅仅是启动时加载的模块的视图的问题,但是按需加载的模块也存在相同的命运。
App/PrismApplication类全文如下:
public partial class App : PrismApplication
{
private ILoggerFactory loggerFactory;
private TaskbarIcon _taskbarIcon;
protected override Window CreateShell()
{
// Register an instance of the Window (used by the dialog service to get a handle on the window when displaying dialogs)
Container.GetContainer().RegisterInstance(typeof(Window), "MainWindow", Container.Resolve<MainWindow>(), new ContainerControlledLifetimeManager());
return Container.Resolve<MainWindow>();
}
protected override void OnInitialized()
{
base.OnInitialized();
// Create the links to each module for the banner view to display
var menuService = Container.Resolve<IMenuService>();
var regionManager = Container.Resolve<IRegionManager>();
menuService.AddItem("Home", "Home", () => regionManager.RequestNavigate("MainRegion", "HomeMainView"));
menuService.AddItem("Messaging", "Messaging", () => regionManager.RequestNavigate("MainRegion", "MessagingMainView"));
menuService.AddItem("Charts", "Charts", () => regionManager.RequestNavigate("MainRegion", "ChartsMainView"));
menuService.AddItem("Admin", "Admin", () => regionManager.RequestNavigate("MainRegion", "AdminMainView"));
// Register banner view with region manager and display it
regionManager.RegisterViewWithRegion("BannerRegion", typeof(BannerView));
// Load the desired module into the main window on start up
Container.Resolve<IRegionManager>().RequestNavigate("MainRegion", "HomeMainView");
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
var container = this.ConfigureLogging(containerRegistry);
// Register types
container.RegisterInstance<IDbConnectionFactory>(
new SqlConnectionFactory(
ConfigurationManager.ConnectionStrings["Messaging"].ConnectionString,
loggerFactory));
/************************************************************/
// TODO: Not sure if need singletons or not - to test......
/************************************************************/
containerRegistry.RegisterSingleton<IMetroMessageDisplayService, MetroMessageDisplayService>();
containerRegistry.RegisterSingleton<IUserService, UserService>();
containerRegistry.RegisterSingleton<IUserStore, UserStore>();
containerRegistry.RegisterSingleton<IMenuService, MenuService>();
containerRegistry.Register<ICustomerService, CustomerService>();
containerRegistry.Register<INotifyIconService, NotifyIconService>();
containerRegistry.RegisterDialog<DefaultDialog, DefaultDialogViewModel>("Default");
containerRegistry.RegisterDialog<HtmlDialog, HtmlDialogViewModel>("Html");
// Get the current user's details - prevent a deadlock in the way we use Task.Run(...).Result
// Then add to container as we will be injecting into VMs
var clientUser = Task.Run(GetCurrentUserDetails).Result;
containerRegistry.RegisterInstance(clientUser);
containerRegistry.RegisterSingleton<IClientUser, ClientUser>();
// Add the task bar icon
_taskbarIcon = (TaskbarIcon)FindResource("NotifyIcon");
containerRegistry.RegisterInstance(_taskbarIcon);
// Create a logger instance
var logger = loggerFactory.CreateLogger<App>();
logger.LogDebug("Finished registering types in App.xaml.cs");
}
private async Task<ClientUser> GetCurrentUserDetails()
{
var userService = Container.Resolve<IUserService>();
var data = await userService.GetClientUsersAsync(ConfigurationManager.AppSettings.Get("TempUserName")).ConfigureAwait(true);
if (!data.Any())
{
// log unable to load user from database then return as no point in loading messages for a user that cannot be found!!
return null;
}
return data.FirstOrDefault();
}
protected override IModuleCatalog CreateModuleCatalog()
{
// We are returning a type that reads the modules from the config file.
return new ConfigurationModuleCatalog();
}
protected override void OnExit(ExitEventArgs e)
{
// The icon would clean up automatically, but this is cleaner
_taskbarIcon.Dispose();
base.OnExit(e);
}
private IUnityContainer ConfigureLogging(IContainerRegistry containerRegistry)
{
// Configure logging - Needed Unity.Microsoft.Logging package
// see https://github.com/unitycontainer/microsoft-logging and https://github.com/unitycontainer/examples/tree/master/src/Logging/Microsoft.Logging
var serilogLogger = new LoggerConfiguration()
.ReadFrom.AppSettings()
.CreateLogger();
this.loggerFactory = new LoggerFactory().AddSerilog(serilogLogger);
var container = containerRegistry.GetContainer();
container.AddExtension(new LoggingExtension(loggerFactory));
return container;
}
}消息传递模块:
public class MessagingModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
// Register main view with region manager
var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("MainRegion", typeof(MessagingMainView));
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<IMessageStore, MessageStore>();
containerRegistry.RegisterSingleton<IMessageService, MessageService>();
containerRegistry.RegisterSingleton<IChatService, ChatService>();
containerRegistry.RegisterSingleton<IFileDialogService, FileDialogService>();
containerRegistry.RegisterDialog<InboxMessageView, InboxMessageViewModel>("HtmlMessage");
// Here we are loading the config/settings from the app.config for this module so we
// can register a ChatServiceConfiguration type as it is injected into ChatService
var filename = Assembly.GetExecutingAssembly().Location;
var configuration = ConfigurationManager.OpenExeConfiguration(filename);
if (configuration != null)
{
var hubUrl = configuration.AppSettings.Settings["HubUrl"].Value;
if (string.IsNullOrEmpty(hubUrl))
{
throw new ArgumentException("The HubUrl app setting cannot ne null or whitespace.");
}
containerRegistry.RegisterInstance(new ChatServiceConfiguration(hubUrl));
containerRegistry.RegisterSingleton<IChatServiceConfiguration, ChatServiceConfiguration>();
}
}
}MessagingMainView:
<UserControl x:Class="Ascensos.Wpf.Modules.Messaging.Views.MessagingMainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:materialDesignConverters="clr-namespace:MaterialDesignThemes.Wpf.Converters;assembly=MaterialDesignThemes.Wpf"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:Ascensos.Wpf.Modules.Messaging.Views"
xmlns:helpers="clr-namespace:Ascensos.Wpf.Modules.Messaging.Helpers"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
</UserControl>背后的代码:
public sealed partial class MessagingMainView : UserControl
{
public MessagingMainView()
{
this.InitializeComponent();
}
}viewmodel (调用基本消息视图模型类):
public sealed class MessagingMainViewModel
{
public MessagingMainViewModel()
{
}
}更新:我已经从我的应用程序中删除了代码,所以只有上面的代码在视图和视图模型中。在模块初始化期间,视图构造函数和viewmodel构造函数仍然被击中两次。
发布于 2020-06-13 17:25:34
我发现了这个问题。它是App CreateShell()方法中的一行:
Container.GetContainer().RegisterInstance(typeof(Window), "MainWindow", Container.Resolve<MainWindow>(), new ContainerControlledLifetimeManager());注释掉这个问题已经解决了问题。再看一遍,我很傻,没有注意到这一点,就像我是新手一样。添加了这段代码,这样我就可以在服务类中访问MainWindow/MetroWindow --但是我需要尝试另一种方法。谢谢你抽出时间@豪金杰。
发布于 2020-06-13 14:29:15
我没有在任何地方(即仅在XAML中)代码中显式地创建视图/视图模型的实例。
这是一个矛盾--在xaml中创建视图模型意味着以与后面或其他任何地方的代码相同的方式创建视图模型。
就像前面说的,别这么做。也从xaml中删除对视图模型构造函数的所有引用(如<DataContext><MyViewViewModel/></DataContext>)。要在xaml中获取intellisense,请使用d:DataContext。
https://stackoverflow.com/questions/62360352
复制相似问题