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

WPF中如何根据点击条件切换按钮的Path Data(窗口状态切换)

Hey there! Let's get that window icon toggling between Min and Max when the button is clicked. Here's how to adjust your existing WPF code to make this work seamlessly:

Solution: Toggle Window Icon Between Min/Max on Button Click

We can handle this in two straightforward ways—either by leveraging the window's built-in WindowState property (no extra ViewModel needed) or using an MVVM-friendly approach if that's your preferred architecture.


Option 1: Use Window's WindowState Property (Simplest)

This approach uses data triggers to switch the icon based on whether the window is maximized or not, and a custom command to toggle the window state.

Step 1: Update the Button XAML

Modify your button to bind the icon's data to the window's state, and swap out the MaximizeCommand for a toggle command:

<Button DockPanel.Dock="Right" 
        Command="{StaticResource ToggleWindowStateCommand}"
        CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">
    <Path x:Name="WindowIconPath" Data="{Binding Data, Source={StaticResource WindowMax}}" />
    <!-- Inherit your existing WindowButton style and add the toggle trigger -->
    <Button.Style>
        <Style TargetType="Button" BasedOn="{StaticResource WindowButton}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" 
                             Value="Maximized">
                    <Setter TargetName="WindowIconPath" Property="Data" Value="{Binding Data, Source={StaticResource WindowMin}}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

Step 2: Create the ToggleWindowStateCommand

Replace your MaximizeCommand with this command that toggles between maximized and normal window states:

public class ToggleWindowStateCommand : ICommand
{
    public bool CanExecute(object parameter)
    {
        return parameter is Window;
    }

    public void Execute(object parameter)
    {
        if (parameter is Window window)
        {
            window.WindowState = window.WindowState == WindowState.Maximized 
                ? WindowState.Normal 
                : WindowState.Maximized;
        }
    }

    public event EventHandler CanExecuteChanged
    {
        add => CommandManager.RequerySuggested += value;
        remove => CommandManager.RequerySuggested -= value;
    }
}

Register this command as a static resource in your XAML (just like you did with MaximizeCommand):

<Window.Resources>
    <local:ToggleWindowStateCommand x:Key="ToggleWindowStateCommand" />
    <!-- Keep your existing WindowMax, WindowMin, and WindowButton resources here -->
</Window.Resources>

Option 2: MVVM-Friendly Approach

If you're using MVVM and want to bind to a ViewModel property instead of the window's direct state, follow these steps:

Step 1: Add a Property to Your ViewModel

Add a boolean property to track the window state, and implement INotifyPropertyChanged:

private bool _isWindowMaximized;
public bool IsWindowMaximized
{
    get => _isWindowMaximized;
    set
    {
        _isWindowMaximized = value;
        OnPropertyChanged(nameof(IsWindowMaximized));
    }
}

// Implement INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Step 2: Update the Toggle Command

Modify the command to update the ViewModel property when toggling the window state:

public class ToggleWindowStateCommand : ICommand
{
    private readonly YourViewModel _viewModel;

    public ToggleWindowStateCommand(YourViewModel viewModel)
    {
        _viewModel = viewModel;
    }

    public bool CanExecute(object parameter) => parameter is Window;

    public void Execute(object parameter)
    {
        if (parameter is Window window)
        {
            var newState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
            window.WindowState = newState;
            _viewModel.IsWindowMaximized = newState == WindowState.Maximized;
        }
    }

    public event EventHandler CanExecuteChanged
    {
        add => CommandManager.RequerySuggested += value;
        remove => CommandManager.RequerySuggested -= value;
    }
}

Step 3: Bind the Icon with a Converter

Use a BooleanToObjectConverter to switch the icon based on the ViewModel property:

<Window.Resources>
    <BooleanToObjectConverter x:Key="BoolToWindowIconConverter">
        <BooleanToObjectConverter.TrueValue>
            <Binding Data, Source={StaticResource WindowMin} />
        </BooleanToObjectConverter.TrueValue>
        <BooleanToObjectConverter.FalseValue>
            <Binding Data, Source={StaticResource WindowMax} />
        </BooleanToObjectConverter.FalseValue>
    </BooleanToObjectConverter>
</Window.Resources>

<!-- Updated Button XAML -->
<Button DockPanel.Dock="Right" 
        Style="{StaticResource WindowButton}"
        Command="{Binding ToggleWindowStateCommand}"
        CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">
    <Path Data="{Binding IsWindowMaximized, Converter={StaticResource BoolToWindowIconConverter}}" />
</Button>

Notes

  • Your existing WindowButton style works perfectly with both options—no changes needed there unless you want to tweak hover/pressed states further.
  • Ensure your WindowMin and WindowMax static resources are valid Geometry objects (since we're binding to their Data property).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:45:05