这个问题很有趣。原来窗口的样式存在一个 bug:如果系统被定义为具有
IsGlassEnabled == true
(在 Win7 Aero 主题中使其为
true
),则窗口依赖于 Microsoft.Windows.Shell.WindowChrome(来自 Microsoft.Windows.Shell 程序集)来绘制边框和窗口的顶部按钮;而这个 WindowChrome 的
GlassFrameThickness
属性与设置为
Bottom
的
NonClientFrameEdges
结合使用,将其设置为
8,30,8,8
。
发生的情况是,由于
AllowsTransparency == true
,玻璃边框是透明的,但窗口仍然从整体窗口大小中“削减”其厚度,因为
WindowChrome
定义了
NonClientFrameEdges="Bottom"
,从而将
ResizeGrip
从视图中裁剪出去。
如果你(疯狂地)将窗口拖动到屏幕上,你就会看到
ResizeGrip
闪烁。
要解决这个问题,我们需要定义一个新的
WindowChrome
,并将其设置为
NonClientFrameEdges="None"
(或者将
GlassFrameThickness = 0
或两者都设置为),并只在
IsGlassEnabled == true && AllowsTransparency == true
时将其分配给窗口(我正在使用在 App.xaml 中定义的应用程序资源,并仅定义了
NonClientFrameEdges="None"
)。
1. Add these namespaces to App.xaml:
xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
xmlns:ribbonPrimitives="clr-namespace:Microsoft.Windows.Controls.Ribbon.Primitives;assembly=RibbonControlsLibrary"
xmlns:shell="clr-namespace:Microsoft.Windows.Shell;assembly=Microsoft.Windows.Shell"
2. Add these resources:
<ribbonPrimitives:RibbonWindowSmallIconConverter x:Key="RibbonWindowSmallIconConverter" />
<shell:WindowChrome x:Key="WindowChromeWithGlassAndTransparency"
NonClientFrameEdges="None" />
<Style x:Key="MyStyle"
TargetType="{x:Type ribbon:RibbonWindow}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsGlassEnabled, Source={x:Static shell:SystemParameters2.Current}}"
Value="True" />
<Condition Binding="{Binding AllowsTransparency, RelativeSource={RelativeSource Mode=Self}}"
Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="shell:WindowChrome.WindowChrome"
Value="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type ribbon:Ribbon}, ResourceId=WindowChromeAeroWithGlass}}" />
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsGlassEnabled, Source={x:Static shell:SystemParameters2.Current}}"
Value="True" />
<Condition Binding="{Binding AllowsTransparency, RelativeSource={RelativeSource Mode=Self}}"
Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="shell:WindowChrome.WindowChrome"
Value="{DynamicResource WindowChromeWithGlassAndTransparency}" />
</MultiDataTrigger>
<DataTrigger Binding="{Binding Path=IsGlassEnabled, Source={x:Static shell:SystemParameters2.Current}}"
Value="True">
<!--This is the original setter of the chrome that makes all the trouble-->
<!--<Setter Property="shell:WindowChrome.WindowChrome"
Value="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type ribbon:Ribbon}, ResourceId=WindowChromeAeroWithGlass}}" />-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ribbon:RibbonWindow}">
<Grid>
<Border Name="PART_ClientAreaBorder"
Background="{TemplateBinding Control.Background}"
BorderBrush="{TemplateBinding Control.BorderBrush}"
BorderThickness="{TemplateBinding Control.BorderThickness}"
Margin="{Binding Path=WindowNonClientFrameThickness, Source={x:Static shell:SystemParameters2.Current}}" />
<Border BorderThickness="{Binding Path=(shell:WindowChrome.WindowChrome).ResizeBorderThickness, RelativeSource={RelativeSource TemplatedParent}}">
<Grid>
<Image Name="PART_Icon"
shell:WindowChrome.IsHitTestVisibleInChrome="True"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Icon, Converter={StaticResource RibbonWindowSmallIconConverter }}"
Width="{Binding Path=SmallIconSize.Width, Source={x:Static shell:SystemParameters2.Current}}"
Height="{Binding Path=SmallIconSize.Height, Source={x:Static shell:SystemParameters2.Current}}" />
<AdornerDecorator>
<ContentPresenter Name="PART_RootContentPresenter" />
</AdornerDecorator>
<ResizeGrip Name="WindowResizeGrip"
shell:WindowChrome.ResizeGripDirection="BottomRight"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Visibility="Collapsed"
IsTabStop="False" />
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Value="{x:Null}"
Property="Icon">
<Setter TargetName="PART_Icon"
Property="Source"
Value="/RibbonControlsLibrary;component/Images/GlassyDefaultSystemIcon.png" />
</Trigger>
<Trigger Property="WindowState"
Value="Maximized">
<Setter TargetName="PART_Icon"
Property="Margin"
Value="0,2,0,0" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ResizeMode"
Value="CanResizeWithGrip" />
<Condition Property="WindowState"
Value="Normal" />
</MultiTrigger.Conditions>
<Setter TargetName="WindowResizeGrip"
Property="Visibility"
Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
3. In your window use the new style:
<rib:RibbonWindow ....
Style="{StaticResource MyStyle}">
....
</rib:RibbonWindow>
DataTrigger
几乎与原始样式相同,只有一个修改:我已经注释了
WindowChrome
的 setter。
MultiDataTrigger
是我添加的。它们检查
AllowsTransparency
属性的值并应用正确的 WindowChrome:如果值为
false
,则使用原始 WindowChrome;如果值为
true
,则使用
NonClientFrameEdges="None"
(也可以使用
GlassFrameThickness = 0
)。
注意:此解决方案删除了使用边缘调整窗口大小的功能,仅通过 ResizeGrip
调整窗口大小。