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>