自定义窗口类和装饰层



出于设计目的,我实现了一个带有样式的自定义窗口类。StyleableWindow继承自Window,主要实现一些依赖属性(例如标题栏背景色(,执行一些边框大小调整逻辑,并处理图标、标题栏和附加菜单栏上的鼠标交互。

当我试图获得一个AdornerLayer(使用AdornerLayer.GetAdornerLayer(uiElement(方法(时,我总是得到null作为结果。

经过一番调查,我试着用普通的窗户代替我的定制窗户,瞧,我的装饰物按预期工作了。

不,我的问题是:我在自定义窗口实现中做错了什么,以至于WPF找不到任何AdornerLayer

这是我的风格实现。由于StyleableWindow.cs主要由依赖属性和交互逻辑组成,我认为代码对此没有太大帮助。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:stylableWindow="clr-namespace:StylableWindow">
<!--Base style for title bar buttons-->
<Style x:Key="CaptionButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="LayoutRoot" Background="Transparent" Width="44" Height="30">
<TextBlock x:Name="txt" Text="{TemplateBinding Content}" FontFamily="Segoe MDL2 Assets" FontSize="10" 
Foreground="{TemplateBinding Foreground}" HorizontalAlignment="Center" VerticalAlignment="Center"
RenderOptions.ClearTypeHint="Auto" TextOptions.TextRenderingMode="Aliased"  TextOptions.TextFormattingMode="Display"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="LayoutRoot" Property="Background" Value="#E5E5E5"/>
<Setter TargetName="txt" Property="Foreground" Value="#000000"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--Minimize-->
<Style x:Key="MinimizeButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyle}">
<Setter Property="Content" Value="&#xE949;"/>
</Style>
<!--Maximize-->
<Style x:Key="MaximizeButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyle}">
<Setter Property="Content" Value="&#xE739;"/>
</Style>
<!--Restore-->
<Style x:Key="RestoreButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyle}">
<Setter Property="Content" Value="&#xE923;"/>
</Style>
<!--Close-->
<Style x:Key="CloseButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyle}">
<Setter Property="Content" Value="&#xE106;"/>
</Style>
<Style TargetType="stylableWindow:StylableWindow" x:Key="StylableWindowStyle">
<Setter Property="Background" Value="{Binding Background}"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="MinHeight" Value="10"/>
<Setter Property="MinWidth" Value="200"/>
<Setter Property="RenderOptions.BitmapScalingMode" Value="HighQuality"/>
<Setter Property="Title" Value="{Binding Title}"/>
<Setter Property="Icon" Value="{Binding Icon}"/>
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome GlassFrameThickness="1" 
ResizeBorderThickness="4"
CaptionHeight="0"/>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type stylableWindow:StylableWindow}">
<Grid Background="Transparent" x:Name="WindowRoot">
<Grid x:Name="LayoutRoot"
Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitleBar-->
<Grid x:Name="PART_HeaderBar"
Background="{TemplateBinding HeaderBarBackground}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentControl Grid.Column="0"
x:Name="AppIcon"
ContentTemplate="{TemplateBinding HeaderBarIcon}"
Margin="6 0 10 0">
</ContentControl>
<ContentControl Grid.Column="1" 
Content="{TemplateBinding HeaderBarMenu}">
</ContentControl>
<Rectangle Grid.Column="2" Width="Auto" Height="20" Stroke="{TemplateBinding HeaderBarForeground}" Visibility="{TemplateBinding TitleBorderVisibility}" Margin="0 2 0 0"/>
<TextBlock Text="{TemplateBinding Title}" 
Grid.Column="2"
TextTrimming="CharacterEllipsis"
FontSize="14"
TextAlignment="Center"
VerticalAlignment="Center"
Padding="10 0 10 0"
Foreground="{TemplateBinding HeaderBarForeground}"
Panel.ZIndex="0"
IsEnabled="{TemplateBinding IsActive}"/>
<Grid x:Name="WindowControlsGrid" Grid.Column="4" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button x:Name="MinimizeButton"
Foreground="{TemplateBinding HeaderBarForeground}"
Style="{StaticResource MinimizeButtonStyle}" 
Visibility="{TemplateBinding MinMaxVisibility}"
Grid.Column="0"/>
<Button x:Name="MaximizeButton" 
Foreground="{TemplateBinding HeaderBarForeground}"
Style="{StaticResource MaximizeButtonStyle}" 
Visibility="{TemplateBinding MinMaxVisibility}"
Grid.Column="1"/>
<Button x:Name="RestoreButton" 
Foreground="{TemplateBinding HeaderBarForeground}"
Style="{StaticResource RestoreButtonStyle}" 
Visibility="Collapsed"
Grid.Column="1"/>
<Button x:Name="CloseButton" 
Foreground="{TemplateBinding HeaderBarForeground}"
Style="{StaticResource CloseButtonStyle}" 
Grid.Column="2"/>
</Grid>
</Grid>
<Grid x:Name="PART_MainContentGrid"
Grid.Row="1"
Panel.ZIndex="10">
<ContentPresenter x:Name="PART_MainContentPresenter" Grid.Row="0"/>
</Grid>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--<Style TargetType="{x:Type Window}" BasedOn="{StaticResource StylableWindowStyle}"/>-->
</ResourceDictionary>
<StylableWindow Style="{StaticResource StylableWindowStyle}">
<StylableWindow.HeaderBarMenu>
<!-- a menu bar for the title -->
</StylableWindow.HeaderBarMenu>
<Grid>
<!-- content goes here -->
</Grid>
</StylableWindow>

在控制模板中,用AdornerDecorator包装ContentPresenter,如下所示:

...
<Grid x:Name="PART_MainContentGrid"
Grid.Row="1"
Panel.ZIndex="10">
<AdornerDecorator>
<ContentPresenter x:Name="PART_MainContentPresenter" Grid.Row="0"/>
</AdornerDecorator>
</Grid>
...

相关内容

  • 没有找到相关文章

最新更新