XAML WPF MVVM自定义标题

mitkmikd  于 2022-12-07  发布在  其他
关注(0)|答案(1)|浏览(163)

我决定在WPF中为我的程序制作一个自定义标题,但遇到了困难。
我开始研究MVVM模式及其本质,以摆脱在View中使用标准事件。我想制作按钮来关闭、最小化和最大化窗口,但遇到了困难。我不明白这些按钮的逻辑应该在哪里。如果你不使用标准事件,而是使用命令,它不会工作,因为ViewModel不知道任何关于窗口的事情。而且我不想使用事件。
我发现这个解决方案窗口关闭按钮

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

但我不知道如何做其他两个按钮同样的方式。我试图找到其他方法名称,可以在这里使用,但我发现只有方法隐藏,但它不适合我,因为它完全隐藏了窗口,它既不在任务栏上,也不在托盘中,但它仍然在运行,并在任务管理器中可见。
您能告诉我如何通过XAML代码实现同样的窗口最小化和大小调整吗?
UPD:
我找到了一种最小化窗口的方法,但我仍然不知道如何制作一个按钮,如果WindowsState已最大化,该按钮将WindowsState更改为Normal,反之亦然。

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

dced5bon1#

在MVVM中,任何与UI相关的逻辑 * 必须 * 在视图中。这一点应该很清楚。
命令不仅仅是视图模型.你的视图也可以定义命令.特殊的ICommand实现是RoutedCommand .不要认为因为它是一个命令,那么它就必须在视图模型中处理.
您不应该使用Interaction.Triggers,尤其是在您的场景中。另外,如果您不坚持MVVM,Interaction.Triggers很可能会引入代码气味。
只需在Window类的代码隐藏(例如 MainWindow.xaml.cs 文件)中为Button.Click事件创建一个事件处理程序。
同样,也没有必要绑定到静态变量、常量或枚举,只需直接引用即可:

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

但是,要解决您的问题,只需在代码隐藏中添加一个事件处理程序:

主窗口.xaml

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

主窗口.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;

或者,使用路由命令(How to: Create a RoutedCommand):

主窗口.xaml

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

主窗口.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;
}

相关问题