You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WPF MVVM模式下用C#通过Interaction Triggers实现窗口最大化最小化?

解决WPF中用Interaction Triggers实现窗口最大化/最小化(.NET 4.5,不破坏MVVM)

问题原因

你原来的方法无效,是因为WPF的Window类根本没有Maximize或Minimize这两个公共方法——它是通过WindowState属性来控制窗口状态的(可选值:WindowState.Normal/Maximized/Minimized),而CallMethodAction只能调用目标对象的公共方法,自然找不到对应方法导致失效。

下面给两种符合MVVM模式的解决方案:


方案1:自定义Interaction Action(View层处理,不侵入ViewModel)

这种方式适合把窗口状态控制逻辑留在View层,ViewModel不需要感知窗口细节。

步骤1:创建自定义TriggerAction

新建一个类,继承System.Windows.Interactivity.TriggerAction<DependencyObject>:

using System.Windows;
using System.Windows.Interactivity;

public class SetWindowStateAction : TriggerAction<DependencyObject>
{
    public static readonly DependencyProperty TargetWindowProperty =
        DependencyProperty.Register("TargetWindow", typeof(Window), typeof(SetWindowStateAction));

    public static readonly DependencyProperty TargetStateProperty =
        DependencyProperty.Register("TargetState", typeof(WindowState), typeof(SetWindowStateAction));

    public Window TargetWindow
    {
        get => (Window)GetValue(TargetWindowProperty);
        set => SetValue(TargetWindowProperty, value);
    }

    public WindowState TargetState
    {
        get => (WindowState)GetValue(TargetStateProperty);
        set => SetValue(TargetStateProperty, value);
    }

    protected override void Invoke(object parameter)
    {
        if (TargetWindow != null)
        {
            TargetWindow.WindowState = TargetState;
        }
    }
}

步骤2:在XAML中使用

替换原来的CallMethodAction,用这个自定义Action:

<!-- 先引入命名空间,假设你的自定义类在local命名空间下 -->
xmlns:local="clr-namespace:你的项目命名空间"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

<!-- 最大化按钮 -->
<Button Content="□" Height="20" Width="20">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <local:SetWindowStateAction 
                TargetWindow="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
                TargetState="Maximized"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

<!-- 最小化按钮 -->
<Button Content="−" Height="20" Width="20">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <local:SetWindowStateAction 
                TargetWindow="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
                TargetState="Minimized"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

<!-- 还原按钮(如果需要) -->
<Button Content="▭" Height="20" Width="20">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <local:SetWindowStateAction 
                TargetWindow="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
                TargetState="Normal"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

方案2:MVVM完全解耦(ViewModel控制,通过服务/附加属性)

如果希望ViewModel能控制窗口状态(比如根据业务逻辑自动最大化),可以用依赖注入或附加属性实现完全解耦。

方式A:窗口服务接口解耦

  1. 定义服务接口:ViewModel只依赖接口,不直接引用Window
public interface IWindowService
{
    void MinimizeWindow();
    void MaximizeWindow();
    void RestoreWindow();
    void CloseWindow();
}
  1. 实现服务(View层):在窗口类中实现这个接口
public partial class MainWindow : Window, IWindowService
{
    public MainWindow()
    {
        InitializeComponent();
        // 把服务注入ViewModel,比如通过构造函数
        DataContext = new MainViewModel(this);
    }

    public void MinimizeWindow() => WindowState = WindowState.Minimized;
    public void MaximizeWindow() => WindowState = WindowState.Maximized;
    public void RestoreWindow() => WindowState = WindowState.Normal;
    public void CloseWindow() => Close();
}
  1. ViewModel中使用服务:
public class MainViewModel
{
    private readonly IWindowService _windowService;

    public ICommand MinimizeCommand { get; }
    public ICommand MaximizeCommand { get; }

    public MainViewModel(IWindowService windowService)
    {
        _windowService = windowService;
        MinimizeCommand = new RelayCommand(_windowService.MinimizeWindow);
        MaximizeCommand = new RelayCommand(_windowService.MaximizeWindow);
    }
}

(注:RelayCommand是WPF中常见的命令实现类,如果没有自己的,可以写一个简单版本,或者用Prism等框架的命令)

  1. XAML绑定命令:
<Button Content="−" Height="20" Width="20" Command="{Binding MinimizeCommand}"/>
<Button Content="□" Height="20" Width="20" Command="{Binding MaximizeCommand}"/>

方式B:附加属性绑定(更轻量)

如果不想用服务,可以用附加属性把Window的WindowState绑定到ViewModel的属性:

  1. 创建附加属性类:
public static class WindowStateBehavior
{
    public static readonly DependencyProperty BoundWindowStateProperty =
        DependencyProperty.RegisterAttached(
            "BoundWindowState",
            typeof(WindowState),
            typeof(WindowStateBehavior),
            new PropertyMetadata(WindowState.Normal, OnBoundWindowStateChanged));

    public static WindowState GetBoundWindowState(DependencyObject obj)
    {
        return (WindowState)obj.GetValue(BoundWindowStateProperty);
    }

    public static void SetBoundWindowState(DependencyObject obj, WindowState value)
    {
        obj.SetValue(BoundWindowStateProperty, value);
    }

    private static void OnBoundWindowStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is Window window)
        {
            window.WindowState = (WindowState)e.NewValue;
        }
    }
}
  1. ViewModel中添加属性:
private WindowState _currentWindowState;
public WindowState CurrentWindowState
{
    get => _currentWindowState;
    set => SetProperty(ref _currentWindowState, value); // 假设实现了INotifyPropertyChanged
}

// 命令示例
public ICommand MinimizeCommand => new RelayCommand(() => CurrentWindowState = WindowState.Minimized);
public ICommand MaximizeCommand => new RelayCommand(() => CurrentWindowState = WindowState.Maximized);
  1. XAML绑定附加属性:
<Window ...
        local:WindowStateBehavior.BoundWindowState="{Binding CurrentWindowState, Mode=TwoWay}">

    <Button Content="−" Command="{Binding MinimizeCommand}"/>
    <Button Content="□" Command="{Binding MaximizeCommand}"/>
</Window>

内容的提问来源于stack exchange,提问作者Tamal Banerjee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 13:05:25