C# 如何使用核心项目和WPF应用程序之间的依赖项注入来更改页面?
我正在使用C# 如何使用核心项目和WPF应用程序之间的依赖项注入来更改页面?,c#,.net,wpf,mvvm,dependency-injection,C#,.net,Wpf,Mvvm,Dependency Injection,我正在使用MVVM框架以及Ninject为依赖性注入构建一个WPF程序。我创建了两个项目,一个是.Net类库核心项目,用于其他.Net应用程序,另一个是WPF特定应用程序 目前,我正在使用带有属性的应用程序视图模型更改应用程序的页面CurrentPage是一种名为ApplicationPage的Enum类型,包含我的应用程序中的不同页面。在我的WPF应用程序的主窗口中有一个框架,其内容绑定到当前页面属性,并使用值转换器将值转换为不同的自定义页面,我使用开关语句制作,如下所示: if (value
MVVM
框架以及Ninject
为依赖性注入构建一个WPF
程序。我创建了两个项目,一个是.Net类库
核心项目,用于其他.Net
应用程序,另一个是WPF
特定应用程序
目前,我正在使用带有属性的应用程序视图模型更改应用程序的页面CurrentPage
是一种名为ApplicationPage
的Enum
类型,包含我的应用程序中的不同页面。在我的WPF应用程序的主窗口中有一个框架,其内容绑定到当前页面属性,并使用值转换器将值转换为不同的自定义页面
,我使用开关
语句制作,如下所示:
if (value is ApplicationPage)
switch ((ApplicationPage)value)
{
case ApplicationPage.PageOne:
return new PageOne();
case ApplicationPage.PageTwo:
return new PageTwo();
default:
throw Exception;
}
}
我想使用构造函数
注入
将这些页面的视图模型
传递到转换器
内页面的构造函数
,使用视图模型
,这些视图模型又被注入应用程序视图模型
类,有点像这样:
case ApplicationPage.PageOne:
return new PageOne(PageOneViewModel);
我的第一个想法是,是否有某种方法可以使CurrentPage
属性实际上成为一个特定的ViewModel
,并在其上执行开关ViewModel
,从而转换器将视图模型
转换为页面
但是,CurrentPage
的类型是一个问题,因为它必须设置为一个ViewModels
,因此无法获取不同的ViewModel
的值,只剩下一个ViewModel
类
我的想法是:是否有办法将视图模型
传递到转换器
?或者我可以将CurrentPage
设置为IViewModelFactory
并从工厂在转换器内创建ViewModel
?在这种情况下,如何更改CurrentPage
的值以更改应用程序中的页面
在遵循这一逻辑的同时,是否有一种方法可以坚持依赖关系,还是有另一种方法,我需要重新考虑我的代码以进行页面更改?不幸的是,我看到的大多数示例都属于所谓的ServiceLocator
反模式。答案是使用如下数据模板
<Window.Resources>
<DataTemplate x:Key="View1Template" DataType="{x:Type local:MainWindowViewModel}">
<!-- Custom control style with a Data Context set to a Viewmodel
object in the MainWindowViewModel -->
<local:CustomPage1 DataContext="{Binding CustomPage1ViewModel}" />
</DataTemplate>
<DataTemplate x:Key="View2Template" DataType="{x:Type local:MainWindowViewModel}">
<!-- Custom control style with a Data Context set to a Viewmodel
object in the MainWindowViewModel -->
<local:CustomPage2 DataContext="{Binding CustomPage2ViewModel}" />
</DataTemplate>
</Window.Resources>
CurrentView
是一个属性,可以在代码中更改为Trigger
在UI
中的更改-可以设置为PageNames
的Enum
不,不,不。老实说,这里有一个争论,但我给你两分。当涉及到数据绑定和视图模型时,DI和导航不应该是同一个。当然像Prism这样的产品也允许这样做,但我不同意这种方法。您当然可以注入视图,但我个人建议不要以这种方式注入ViewModel或控制导航。在MVC中,您允许控制器指示视图和导航,但在MVVM中,您应该对导航做出反应。换句话说,将视图模型编写成更像绑定端点,并……进行反应性导航。在视图层中构建导航。这将分离关注点,并允许在任何层上对系统进行更轻松的扩展/选项/更改。我喜欢您的导航视图模型方法,您可以在视图层中使用独特的MVVM样式的导航,但从逻辑上讲,它不需要,而且IMO不应该依赖于ViewModel层。这是一个很长的讨论,在网上有争议,所以我不会说这是必须的,但我在这里用各种方法做了很多工作,从我的个人经验可以告诉你,我不会再选择这样做了。我相信,分离这个逻辑也会解决你的问题。如果您有一个独特的视图系统,请将其视为可视模型的附件。不要假装知道ViewModel层中的视图,也不要假装视图始终相同。用任何视图都可以附加和工作的想法来构建它,无论它们如何使用VM。谢谢你们,这非常有帮助。使用数据模板似乎是前进的方向。我已经找到了结合你两个答案的解决方案,效果非常好!我之所以有一个单独的导航视图模型,只是为了让我能够在其他项目中使用它,而不是在这个项目中,但我想每个项目都有自己的导航需求。
<ContentControl Content="{Binding}">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<!-- The Default/initial View being shown -->
<Setter Property="ContentTemplate" Value="{StaticResource View1Template}" />
<!-- Triggers bound to the CurrentView Property -->
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentView}" Value="1">
<Setter Property="ContentTemplate" Value="{StaticResource View1Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding CurrentView}" Value="2">
<Setter Property="ContentTemplate" Value="{StaticResource View2Template}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>