简体   繁体   English

WPF MVVM 自定义标题

[英]WPF MVVM Custom TItle

I decided to make a custom title for my program in WPF and encountered difficulties.我决定在 WPF 中为我的程序制作自定义标题,但遇到了困难。

I started to study MVVM pattern and its essence to get rid of using standard events in View.我开始研究 MVVM 模式及其本质,以摆脱在 View 中使用标准事件。 I wanted to make buttons to close, minimize and maximize window, but ran into difficulties.我想制作按钮来关闭、最小化和最大化 window,但遇到了困难。 I can't understand where the logic of these buttons should be.我不明白这些按钮的逻辑应该在哪里。 If you don't use standard events, but use commands, it won't work, because ViewModel doesn't know anything about the window.如果您不使用标准事件,而是使用命令,它将无法正常工作,因为 ViewModel 对 window 一无所知。 And I don't want to use events.而且我不想使用事件。

I found this solution for window close button我找到了 window 关闭按钮的解决方案

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
    <i:CallMethodAction MethodName="Close"
                        TargetObject="{Binding RelativeSource={RelativeSource
                                                Mode=FindAncestor,
                                                AncestorType=Window}}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

But I don't know how to do the other two buttons the same way.但我不知道如何以同样的方式完成其他两个按钮。 I tried to find other MethodNames that can be used here, but I found only method Hide, but it does not suit me, because it hides the window completely, it is neither on the taskbar nor in the tray, but it is still running and visible in the task manager.我试图找到可以在这里使用的其他 MethodNames,但我只找到了方法 Hide,但它不适合我,因为它完全隐藏了 window,它既不在任务栏上,也不在托盘中,但它仍在运行并且在任务管理器中可见。

Can you tell me how I can do the same window minimizing and resizing through XAML code?您能告诉我如何通过 XAML 代码执行相同的 window 最小化和调整大小吗?

UPD:升级版:

I found a way to minimize the window, but I still do not know how to make a button that will change the WindowsState to Normal if the WindowState Maximized and vice versa.我找到了一种最小化 window 的方法,但我仍然不知道如何制作一个按钮,如果 WindowState 最大化,反之亦然。


<i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
        <i:ChangePropertyAction PropertyName="WindowState"
            TargetObject="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
            Value="{Binding Source={x:Static sys:WindowState.Minimized}}"
        />
    </i:EventTrigger>
</i:Interaction.Triggers>

In MVVM any UI related logic must be in the View.在 MVVM 中,任何与 UI 相关的逻辑都必须在视图中。 This should be clear.这应该很清楚。

Commands are not View Model only.命令不仅限于查看 Model。 Your View can also define commands.您的视图还可以定义命令。 Special ICommand implementation is the RoutedCommand .特殊的ICommand实现是RoutedCommand Don't think that because it is a command, then it must be handled in the View Model.不要以为因为是命令,那么就必须在View Model中处理。

You should not use the Interaction.Triggers , especially not in your case.您不应该使用Interaction.Triggers ,尤其是在您的情况下。 If you are not firm with MVVM, Interaction.Triggers will very likely introduce code smells.如果你对 MVVM 不坚定, Interaction.Triggers很可能会引入代码异味。
Simply create an event handler for the Button.Click event in your Window class' code-behind eg, MainWindow.xaml.cs file.只需在Window类的代码隐藏中为Button.Click事件创建一个事件处理程序,例如MainWindow.xaml.cs文件。

Also, there is no reason to bind to a static variable or a constant or an enum.此外,没有理由绑定到 static 变量或常量或枚举。 Just reference it directly:直接引用即可:

<i:ChangePropertyAction Value="{x:Static sys:WindowState.Minimized}" ...  />

However, to solve your problem simply add an event handler in your code-behind:但是,要解决您的问题,只需在代码隐藏中添加一个事件处理程序:

MainWindow.xaml主窗口.xaml

<Button Click="OnMaximizeButtonClicked"
        Content="Toggle Maximize" />

MainWindow.xaml.cs主窗口.xaml.cs

// Toggle the WindowState between Maximized and Normal
private void OnMaximizeButtonClicked(object sender, RoutedEventArgs e)
  => this.WindowState = this.WindowState == WindowState.Normal
    ? WindowState.Maximized
    : WindowState.Normal;

Alternatively, use routed commands ( How to: Create a RoutedCommand ):或者,使用路由命令( 如何:创建 RoutedCommand ):

MainWindow.xaml主窗口.xaml

<Button Command="{x:Static local:MainWindow.ToggleMaximizeStateCommand}"
        Content="Toggle Maximize" />

MainWindow.xaml.cs主窗口.xaml.cs

partial class MainWindow : Window
{
  public static RoutedCommand ToggleMaximizeStateCommand { get; } = new RoutedCommand("ToggleMaximizeStateCommand", typeof(MainWindow));

  public MainWindow()
  {
    InitializeComponent();

    // Register the command handler
    var toggleMaximizeStateCommandBinding = new CommandBinding(
      ToggleMaximizeCommand, 
      ExecuteToggleMaximizeStateCommand, 
      CanExecuteToggleMaximizeStateCommand);
    this.CommandBindings.Add(toggleMaximizeCommandBinding);
  }
    
  // Toggle the WindowState between Maximized and Normal
  private void ExecuteToggleMaximizeStateCommand(object sender, ExecutedRoutedEventArgs e) 
    => this.WindowState = this.WindowState == WindowState.Normal
      ? WindowState.Maximized
      : WindowState.Normal;

  private void CanExecuteToggleMaximizeStateCommand(object sender, CanExecuteRoutedEventArgs e) 
    => e.CanExecute = true;
}

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

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