简体   繁体   English

在其他视图中查看 (WPF/MVVM)

[英]View inside other View (WPF/MVVM)

I have this UserControl called ControlButtonsView我有这个名为 ControlButtonsView 的 UserControl

<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>

and ControlButtonsViewModel和 ControlButtonsViewModel

class ControlButtonsViewModel
{
    private MainWindow _mainWindow;

    public ICommand MinimizeAppCommand { get; set; }
    public ICommand ExitAppCommand { get; set; }

    public ControlButtonsViewModel(MainWindow mainWindow)
    {
        _mainWindow = mainWindow;

        MinimizeAppCommand = new BaseICommand(MinimizeApp);
        ExitAppCommand = new BaseICommand(ExitApp);
    }

    public void MinimizeApp(object obj)
    {
        _mainWindow.WindowState = System.Windows.WindowState.Minimized;
    }

    public void ExitApp(object obj)
    {
        _mainWindow.Close();
    }
}

In my MainWindow.xaml.cs在我的 MainWindow.xaml.cs

this.DataContext = new AppManagerViewModel();

AppManagerViewModel controls the switching between Views AppManagerViewModel 控制 View 之间的切换

What I want is to be able to use this ControlButtonsView with its ControlButtonsViewModel in multiple other Views, this view is a UserControl with a minimize and a maximize buttons and I want to use them in multiple Views, in LogInView, MenuView etc.我想要的是能够在多个其他视图中使用这个 ControlButtonsView 及其 ControlButtonsViewModel,这个视图是一个带有最小化和最大化按钮的 UserControl,我想在多个视图中使用它们,在 LogInView、MenuView 等中。

If there is an easier way to do this please tell me) Thank you.如果有更简单的方法,请告诉我)谢谢。

  1. In AppManagerViewModel , add a property of ControlButtonsViewModel .AppManagerViewModel中,添加ControlButtonsViewModel的属性。

    public ControlButtonsViewModel ControlButtonsViewModel {get; set;}

  2. In the constructor of AppManagerViewModel , add ControlButtonsViewModel = new ControlButtonsViewModel();AppManagerViewModel的构造函数中,添加ControlButtonsViewModel = new ControlButtonsViewModel();

  3. In Xaml of AppManagerView ,AppManagerView的 Xaml 中,

    <ControlButtonsView DataContext="{Binding ControlButtonsViewModel}"... /> <ControlButtonsView DataContext="{绑定 ControlButtonsViewModel}"... />

Window logic does not belong to the view model. Window逻辑不属于视图 model。 View model does not care about UI.查看 model 不关心 UI。 You must always implement the view model pretending like there is no UI, only a model.您必须始终实现视图 model 假装没有 UI,只有 model。

Therefore having a reference of MainWindow in you view model will lead to a tight coupling of the application to the view/UI.因此,在您的视图 model 中引用MainWindow将导致应用程序与视图/UI 紧密耦合。

The goal of MVVM is to remove this tight coupling. MVVM 的目标是消除这种紧密耦合。 Obviously, due to the tight coupling you have introduced, you are currently not implementing the MVVM pattern (you are implementing it wrong).显然,由于您引入的紧密耦合,您当前没有实现 MVVM 模式(您实现错了)。
For example, you won't be able to test the view model without creating a view.例如,如果不创建视图,您将无法测试视图 model。

Injecting the view as constructor dependency makes it even worse.将视图作为构造函数依赖注入会使情况变得更糟。

Because the commands execute UI logic (close, minimize), they have to be moved to a control - to the view component from a MVVM point of view.因为命令执行 UI 逻辑(关闭、最小化),所以必须将它们移至控件 - 从 MVVM 的角度移至视图组件。

To make those commands available throughout your view or globally relative to the actual visual tree, you should implement those commands as routed commands eg on your MainWindow , which you want to control via commanding.要使这些命令在整个视图中或相对于实际可视树全局可用,您应该将这些命令实现为路由命令,例如在您希望通过命令控制的MainWindow上。

Since routed commands are static, they can be referenced by every other control.由于路由命令是 static,它们可以被所有其他控件引用。 Because they are routed, they can be used everywhere in the same visual tree that the command target (the MainWindow ) belongs to.因为它们是路由的,所以它们可以在命令目标( MainWindow )所属的同一可视树中的任何地方使用。

Internally the command, once executed, will raise a routed event which will traverse the visual tree until it finds a handler.在内部,该命令一旦执行,将引发一个路由事件,该事件将遍历可视化树,直到找到处理程序。

Commanding Overview 指挥概述

In your case, MainWindow will register the Execute and CanExecute handler to close or minimize itself .在您的情况下, MainWindow将注册 Execute 和 CanExecute 处理程序以关闭或最小化自身

The following example implements only the logic to close the Window .以下示例仅实现了关闭Window的逻辑。
You can follow the pattern to provide additional logic eg to maximize the Window :您可以按照该模式提供额外的逻辑,例如最大化Window

MainWindow.xaml.cs主窗口.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 ControlButtonsView.xaml

<Grid>
  <-- ICommand traverse visual tree until handler(s) is found -->
  <Button Content="X" Command="{x:static MainWindow.CloseWindowRoutedCommand}" />
</Grid>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM