我在WPF中创建自定义窗口样式。到目前为止,我已经能够在纯XAML中完成几乎可以工作的东西。
<ControlTemplate TargetType="{x:Type Window}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<DockPanel LastChildFill="True">
<Border Height="40" Padding="5" DockPanel.Dock="Top" BorderBrush="#7FA0A0A0"
BorderThickness="0,0,0,1">
<Grid WindowChrome.IsHitTestVisibleInChrome="True">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Image Source="Resources/Logo/f-dark.png" />
<TextBlock Margin="0,0,0,0" Text="{TemplateBinding Title}" VerticalAlignment="Center"
FontSize="16" Foreground="#AF000000"/>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"
WindowChrome.IsHitTestVisibleInChrome="True" Background="Transparent">
<Button Width="{x:Static SystemParameters.WindowCaptionButtonWidth}"
Command="{x:Static SystemCommands.MinimizeWindowCommand}"
Style="{StaticResource LinkButton}"
WindowChrome.IsHitTestVisibleInChrome="True"
IsEnabled="True">
<TextBlock Style="{StaticResource Icon}" FontSize="18"></TextBlock>
</Button>
<Button Width="{x:Static SystemParameters.WindowCaptionButtonWidth}"
Command="{x:Static SystemCommands.RestoreWindowCommand}"
Style="{StaticResource LinkButton}"
WindowChrome.IsHitTestVisibleInChrome="True"
IsEnabled="True">
<TextBlock Style="{StaticResource Icon}" FontSize="18"></TextBlock>
</Button>
<Button Width="{x:Static SystemParameters.WindowCaptionButtonWidth}"
Command="{x:Static SystemCommands.CloseWindowCommand}"
Style="{StaticResource LinkButton}"
WindowChrome.IsHitTestVisibleInChrome="True"
IsEnabled="True">
<TextBlock Style="{StaticResource Icon}" FontSize="18"></TextBlock>
</Button>
</StackPanel>
</Grid>
</Border>
<Border>
<ContentPresenter/>
</Border>
</DockPanel>
</Border>
</ControlTemplate>
但是,窗口中的chrome按钮不会突出显示或更改光标(并且具有相同样式的按钮的行为与预期相同)。点击它们没有任何效果。为什么是这样?如何让按钮互动?
我也希望能够修复黑色边框,但我的主要问题是字幕按钮是非交互式的。
答案 0 :(得分:2)
我已经解决了这两个问题。事实证明,SystemCommands
没有实现,而只是RoutedCommand
。 (他们为什么那样做?)
所以,我创建了一个附加属性,为我应用此样式的每个窗口设置CommandBindings
。
public class Helper
{
public static bool GetUseWindowCommandBindings(DependencyObject obj)
{
return (bool)obj.GetValue(UseWindowCommandBindingsProperty);
}
public static void SetUseWindowCommandBindings(DependencyObject obj, bool value)
{
obj.SetValue(UseWindowCommandBindingsProperty, value);
}
public static readonly DependencyProperty UseWindowCommandBindingsProperty =
DependencyProperty.RegisterAttached("UseWindowCommandBindings", typeof(bool), typeof(Helper), new PropertyMetadata(false, UseWindowCommandBindingsChanged));
private static void UseWindowCommandBindingsChanged(DependencyObject d, DependencyPropertyChangedEventArgs dpce)
{
if (d is Window w && dpce.NewValue is bool b && b)
{
w.CommandBindings.Add(
new CommandBinding(
SystemCommands.MinimizeWindowCommand,
(s, e) => SystemCommands.MinimizeWindow(w),
(s, e) => e.CanExecute = true
));
w.CommandBindings.Add(
new CommandBinding(
SystemCommands.RestoreWindowCommand,
(s, e) => SystemCommands.RestoreWindow(w),
(s, e) => e.CanExecute = true
));
w.CommandBindings.Add(
new CommandBinding(
SystemCommands.MaximizeWindowCommand,
(s, e) => SystemCommands.MaximizeWindow(w),
(s, e) => e.CanExecute = true
));
w.CommandBindings.Add(
new CommandBinding(
SystemCommands.CloseWindowCommand,
(s, e) => SystemCommands.CloseWindow(w),
(s, e) => e.CanExecute = true
));
}
}
}
我必须将CommandBindings
的附件放在属性更改处理程序中,因为WPF直接调用SetValue()
。现在,按照我的风格,我添加了一行:
<Setter Property="view:Helper.UseWindowCommandBindings" Value="True" />
现在按钮按预期工作。要修复黑色边框,我将模板中最外层Border
的宽度设置为{TemplateBinding Width}
。但是如果我最大化窗口,这会产生一个巨大的全方位黑色边框的问题: