WPF自定义最大化最小化关闭按钮

WPF自定义最大化最小化关闭按钮

当觉得界面自带的最大化最小化关闭按钮不好看,或者想换个位置的时候,你需要自定义最大化最小化关闭按钮

最大化按钮

最大化按钮有两种状态:最大化,跟还原状态两种显示方式。做法:定义command为SystemCommands.XXXCommand。本次使用了DataTemplateSelector,根据当前window的WindowState状态来判断当前窗体状态(如果没定义window需要在本窗体最开始,定义Name=“window”)
前端xaml代码

<ContentControl Name="MyContentControl" Content="{Binding ElementName=window,Path=WindowState,Mode=TwoWay}">
    <ContentControl.ContentTemplateSelector>
        <local:MaxTemplateSelector MaxTemplate="{StaticResource Max}"  RestoreTemplate="{StaticResource Restore}"/>
    </ContentControl.ContentTemplateSelector>
</ContentControl>

最大化模板

<DataTemplate x:Key="Max">
    <Button x:Name="PART_Max" Background="Transparent" Style="{StaticResource MetroWindowButtonStyle1}" Command="{x:Static SystemCommands.MaximizeWindowCommand}"
        Width="46"
        Focusable="False"
        IsEnabled="{Binding IsMaxRestoreButtonEnabled, RelativeSource={RelativeSource AncestorType={x:Type Controls:MetroWindow}}}"
        ToolTip="最大化"
        UseLayoutRounding="True">
        <!--  normal state  -->
        <Path x:Name="PART_MaxPath"
              Width="10"
              Height="10"
              Data="F1M0,0L0,9 9,9 9,0 0,0 0,3 8,3 8,8 1,8 1,3z"
              Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
              SnapsToDevicePixels="True" >
        </Path>
    </Button>
</DataTemplate>

还原模板

<DataTemplate x:Key="Restore">
    <Button x:Name="PART_Restore" Background="Transparent" Style="{StaticResource MetroWindowButtonStyle1}" Command="{x:Static SystemCommands.RestoreWindowCommand}"
        Width="46"
        Focusable="False"
        IsEnabled="{Binding IsMaxRestoreButtonEnabled, RelativeSource={RelativeSource AncestorType={x:Type Controls:MetroWindow}}}"
        ToolTip="向下还原"
        UseLayoutRounding="True">
        <!--  normal state  -->
        <Canvas Width="12"
            Height="12"
            HorizontalAlignment="Center"
            VerticalAlignment="Center">
            <Path x:Name="PART_RestorePath"
                  Data="F1M0,10L0,3 3,3 3,0 10,0 10,2 4,2 4,3 7,3 7,6 6,6 6,5 1,5 1,10z M1,10L7,10 7,7 10,7 10,2 9,2 9,6 6,6 6,9 1,9z"
                  Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
                  RenderOptions.EdgeMode="Aliased"
                  SnapsToDevicePixels="True"
                  Stretch="Uniform" />
        </Canvas>
    </Button>
</DataTemplate>

后台TemplateSelector代码

/// <summary>
/// 最大化与还原按钮状态模板选择器
/// </summary>
public class MaxTemplateSelector : DataTemplateSelector
{
    public DataTemplate MaxTemplate { get; set; }
    public DataTemplate RestoreTemplate { get; set; }
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        //Window win = Application.Current.MainWindow;
        //WindowState state = win.WindowState;
 //必须判断是否为空,否则设计器无法操作
        if (item == null)
            return null;
        WindowState state = (WindowState)item;
        switch (state)
        {
            case WindowState.Normal:
                return MaxTemplate;
            case WindowState.Maximized:
                return RestoreTemplate;
        }
        return null;
    }
}

window最前面定义CommandBinding。

    <Window.CommandBindings>
        <CommandBinding Command="{x:Static SystemCommands.RestoreWindowCommand}" 
                        Executed="RestoreWindow_Exec" />
        <CommandBinding Command="{x:Static SystemCommands.MaximizeWindowCommand}" 
                        Executed="MaximizeWindow_Exec" />
    </Window.CommandBindings>

定义Executed事件方法

        private void RestoreWindow_Exec(object sender, ExecutedRoutedEventArgs e)
        {
            SystemCommands.RestoreWindow(this);
        }

        private void MaximizeWindow_Exec(object sender, ExecutedRoutedEventArgs e)
        {
            SystemCommands.MaximizeWindow(this);
        }

最小化按钮

<Button x:Name="PART_Min" Background="Transparent" Style="{StaticResource MetroWindowButtonStyle1}" Command="{x:Static SystemCommands.MinimizeWindowCommand}"
                    Width="46"
                    Focusable="False"
                    IsEnabled="{Binding IsMinButtonEnabled, RelativeSource={RelativeSource AncestorType={x:Type Controls:MetroWindow}}}"
                    ToolTip="最小化"
                    UseLayoutRounding="True">
                        <Path Width="10"
                      Height="10"
                      HorizontalAlignment="Center"
                      VerticalAlignment="Center"
                      Data="M0,40 L96,40 96,48 0,48 0,40z"
                      Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
                      RenderOptions.EdgeMode="Aliased"
                      SnapsToDevicePixels="True"
                      Stretch="Uniform" />
                    </Button>

window最前面定义CommandBinding。

<Window.CommandBindings>
    <CommandBinding Command="{x:Static SystemCommands.MinimizeWindowCommand}" 
                    Executed="MinimizeWindow_Exec" />
</Window.CommandBindings>

定义Executed事件方法

private void MinimizeWindow_Exec(object sender, ExecutedRoutedEventArgs e)
{
    SystemCommands.MinimizeWindow(this);
}

关闭按钮

 <Button x:Name="PART_Close" Background="Transparent" Style="{StaticResource MetroWindowButtonStyle1}"
                    Width="46"
                    Focusable="False"
                    IsEnabled="{Binding RelativeSource={RelativeSource AncestorType={x:Type Controls:MetroWindow}}, Path=IsCloseButtonEnabled, Mode=OneWay}"
                    ToolTip="关闭"
                    UseLayoutRounding="True">
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="Click">
                                <ei:CallMethodAction TargetObject="{Binding ElementName=window}" MethodName="Close"/>
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                        <Grid>
                            <Line HorizontalAlignment="Center"
                          VerticalAlignment="Center"
                          SnapsToDevicePixels="True"
                          Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
                          X1="0"
                          X2="10"
                          Y1="0"
                          Y2="10" />
                            <Line HorizontalAlignment="Center"
                          VerticalAlignment="Center"
                          SnapsToDevicePixels="True"
                          Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
                          X1="0"
                          X2="10"
                          Y1="10"
                          Y2="0" />
                        </Grid>
                    </Button>

2022.2.25应评论区要求更新

中间引用的style: MetroWindowButtonStyle1
我这个程序UI框架是依赖于mahapp.metro,所以会引用到mahapp.metro的MetroWindowButtonStyle,然后我自己只是根据业务需求自定义了一下,本质可以直接用MetroWindowButtonStyle

<Style x:Key="MetroWindowButtonStyle1"
               TargetType="{x:Type Button}"
               BasedOn="{StaticResource MetroWindowButtonStyle}">
    <Setter Property="Foreground" Value="White"/>
    <Setter Property="Opacity" Value="1"/>
</Style>

看了下,MetroWindowButtonStyle是这么定义了

<Style x:Key="MetroWindowButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource MetroBaseWindowButtonStyle}">
    <Setter Property="FocusVisualStyle" Value="{x:Null}" />
    <Setter Property="IsTabStop" Value="false" />
    <Setter Property="Width" Value="34" />
    <Setter Property="MaxHeight" Value="34" />
    <Setter Property="Padding" Value="0" />
</Style>
    原文作者:迷惘小书童
    原文地址: https://blog.csdn.net/m0_37080285/article/details/83410663
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞