不仅要使用SOLID 设计原则构建您的视图模型,而且还要在您的视图中执行此操作,这是一种很好的做法。用户控件的使用可以帮助您解决这个问题。
如果技术上可行,您建议的方法的缺点是这种设计将违反SRP 和OCP。
SRP 因为您的用户控件需要的所有依赖项都必须注入到使用窗口/视图中,而该视图可能不需要(所有)这些依赖项。
还有 OCP,因为每次您从用户控件中添加或删除依赖项时,您还需要从使用窗口/视图中添加或删除它。
使用用户控件,您可以像编写其他类(如服务、命令和查询处理程序等)一样编写视图。在依赖注入方面,编写应用程序的位置是 composition root
WPF 中的ContentControls 都是关于从应用程序中的其他“内容”“组合”视图。
像Caliburn Micro 这样的 MVVM 工具通常使用 contentcontrols 来注入带有自己的视图模型的用户控件视图(阅读:xaml,没有代码后面)。事实上,当使用 MVVM 时,作为最佳实践,您将从 usercontrols 类构建应用程序中的所有视图。
这可能看起来像这样:
public interface IViewModel<T> { }
public class MainViewModel : IViewModel<Someclass>
{
public MainViewModel(IViewModel<SomeOtherClass> userControlViewModel)
{
this.UserControlViewModel = userControlViewModel;
}
public IViewModel<SomeOtherClass> UserControlViewModel { get; private set; }
}
public class UserControlViewModel : IViewModel<SomeOtherClass>
{
private readonly ISomeService someDependency;
public UserControlViewModel(ISomeService someDependency)
{
this.someDependency = someDependency;
}
}
以及 MainView 的 XAML:
// MainView
<UserControl x:Class="WpfUserControlTest.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ContentControl Name="UserControlViewModel" />
</Grid>
</UserControl>
// UserControl View
<UserControl x:Class="WpfUserControlTest.UserControlView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<TextBlock Text="SomeInformation"/>
</Grid>
</UserControl>
结果将是MainView 显示在一个窗口中,该窗口的DataContext 设置为MainViewModel。内容控件将填充UserControlView,其DataContext 设置为UserControlViewModel 类。这是自动发生的,因为 MVVM 工具会使用 Convention over configuration 将视图模型绑定到相应的视图。
如果您不使用 MVVM 工具,而是直接在窗口类后面的代码中注入您的依赖项,您只需遵循相同的模式即可。在您的视图中使用 ContentControl,就像上面的示例一样,并在窗口的构造函数中注入 UserControl(使用包含您希望的参数的构造函数)。然后只需将 ContentControl 的 Content 属性设置为您的 UserControl 的注入实例。
看起来像:
public partial class MainWindow : Window
{
public MainWindow(YourUserControl userControl)
{
InitializeComponent();
// assuming you have a contentcontrol named 'UserControlViewModel'
this.UserControlViewModel.Content = userControl;
}
// other code...
}