C# 其他视图内的视图(WPF/MVVM)
我有一个名为ControlButtonsView的用户控件C# 其他视图内的视图(WPF/MVVM),c#,wpf,mvvm,C#,Wpf,Mvvm,我有一个名为ControlButtonsView的用户控件 <Grid> <Button Style="{StaticResource MinimizeButton}" Command="{Binding MinimizeAppCommand}" Height="40" Width="120" VerticalAlignment="Top" HorizontalAlign
<Grid>
<Button Style="{StaticResource MinimizeButton}" Command="{Binding MinimizeAppCommand}" Height="40" Width="120" VerticalAlignment="Top" HorizontalAlignment="Right"/>
<Button Content="X" Style="{StaticResource ExitButton}" Command="{Binding ExitAppCommand}" Height="40" Width="60" VerticalAlignment="Top" HorizontalAlignment="Right"/>
</Grid>
在我的主窗口中.xaml.cs
this.DataContext = new AppManagerViewModel();
AppManagerViewModel控制视图之间的切换
我想要的是能够在多个其他视图中使用这个ControlButtonsView及其ControlButtonsViewModel,这个视图是一个带有最小化和最大化按钮的用户控件,我想在多个视图中,在LogInView、MenuView等中使用它们
如果有更简单的方法,请告诉我)谢谢
AppManagerViewModel
中,添加ControlButtonsViewModel
的属性
公共控制按钮视图模型控制按钮视图模型{get;set;}
AppManagerViewModel
的构造函数中,添加
ControlButtonsViewModel=新的ControlButtonsViewModel()代码>
AppManagerView
的Xaml中
窗口
逻辑不属于视图模型。视图模型不关心用户界面。您必须始终假装没有UI,只有一个模型来实现视图模型
因此,在视图模型中引用MainWindow
,将导致应用程序与视图/UI紧密耦合
MVVM的目标是消除这种紧密耦合。显然,由于您引入的紧密耦合,您目前没有实现MVVM模式(您实现它是错误的)。例如,如果不创建视图,您将无法测试视图模型 将视图作为构造函数依赖项注入会使情况变得更糟 因为这些命令执行UI逻辑(close、minimize),所以必须从MVVM的角度将它们移动到控件-视图组件 要使这些命令在整个视图中或相对于实际视觉树全局可用,您应将这些命令作为路由命令来执行,例如在您的
主窗口上
,您希望通过命令来控制这些命令
因为它们是静态的,所以它们可以被其他控件引用。因为它们是路由的,所以它们可以在命令目标(主窗口<代码>所属)所属的同一可视树中的任何位置使用
在内部,该命令一旦执行,将引发一个路由事件,该事件将遍历可视化树,直到找到处理程序
在您的情况下,main窗口将注册Execute和CanExecute处理程序以关闭或最小化自身
以下示例仅实现关闭窗口的逻辑
您可以按照该模式提供附加逻辑,例如最大化窗口
:
MainWindow.xaml.cs
partial class MainWindow : Window
{
public static readonly RoutedUICommand CloseWindowRoutedCommand = new RoutedUICommand(
"Closes the application.",
nameof(MainWindow.CloseWindowRoutedCommand),
typeof(MainWindow));
public MainWindow()
{
InitializeComponent();
this.CommandBindings.Add(
new CommandBinding(MainWindow.CloseWindowRoutedCommand,
ExecuteCloseWindow,
CanExecuteCloseWindow));
}
private void CanExecuteCloseWindow(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = true;
private void ExecuteCloseWindow(object sender, ExecutedRoutedEventArgs e) => Close();
}
ControlButtonsView.xaml
<Grid>
<-- ICommand traverse visual tree until handler(s) is found -->
<Button Content="X" Command="{x:static MainWindow.CloseWindowRoutedCommand}" />
</Grid>
“如果有更简单的方法来做这件事”:比什么更简单?您已将问题标记为MVVM。通过向视图模型添加与视图相关的逻辑,您当前违反了该模式。视图模型是一个不知道视图存在的组件:不允许将控件传递给视图模型并控制其行为。您可以将视图模型添加到控件中,例如通过设置DataContext。视图的构造函数可以请求视图模型,但不能反过来请求DataContext=this.DataContext=new-AppManagerViewModel()代码>没有多大意义,是吗?你到底有什么问题?您可以将UserControl添加到任意多个其他控件中。这就像使用文本框。注意,为了提高性能,更重要的是,为了避免内存泄漏,您的绑定源(视图模型类)必须实现INotifyPropertyChanged
。即使您没有引发事件,UI逻辑也必须移动到UserControlControlButtonsView
。然后,控件必须将这些命令作为路由命令来执行。由于您似乎只对控制主窗口感兴趣,因此应该将包含路由命令的逻辑移到此类中。路由命令是静态的,因此可以全局引用它们。MainWindow可以处理每个命令调用,只要该命令由一个孩子调用。我有一个UserControl视图,其中有两个按钮(最小化和退出),在该UserControl的视图模型中,我有两个用于这些按钮的命令按钮,问题是,我可以在其他视图中使用该视图,但是UserControl没有绑定到它的视图模型命令。这只允许我使用UserControl,但两个按钮的绑定找不到命令。谢谢,如果我理解正确,我不需要ViewModels作为UserControl,我计划全局多次使用,对吗?我只是照你说的做不完全是。我说不允许您处理UI逻辑或在视图模型中建立对视图的依赖关系-这样做不符合MVVM。它将引入许多您想要避免的问题,这就是您选择MVVM的原因。您可以将视图模型用于控件,但不要混淆职责。当你的视图模型可以在没有视图的情况下存在时,你就走上了一条好路。通常你会说,视图模型不知道有一个UI和一个用户。视图模型只知道模型并与模型对话。按照我向你展示的方式做确实能解决这个问题,对吗?我们将与UI相关的职责移回UI。现在UI可以处理自己的逻辑。例如,UI逻辑处理可见性、布局、外观(例如颜色)、动画和用户交互,或者通常处理控件及其行为;(哪个是UI逻辑rigt?因为它对UI有影响)在我的ViewModel中,我违反了MVVM模式,这是不正确的,我的ViewModels应该只执行数据逻辑并保存视图绑定到的变量?正确。视图模型从模型中获取数据,并通过数据绑定将其呈现给视图。视图模型不访问数据库
<Grid>
<-- ICommand traverse visual tree until handler(s) is found -->
<Button Content="X" Command="{x:static MainWindow.CloseWindowRoutedCommand}" />
</Grid>