我有一个关于如何优雅地覆盖控件视觉树中任意元素的问题。我已经尝试过几种方法来解决它,但每种方法都遇到了一些问题。通常当我尝试三条不同的路径并在每一条路径上失败时,我会去楼下喝杯咖啡,问比我聪明的人。所以我来到这里。
具体而言:
我想要使组合框(ComboBox)的样式扁平化,使其不会引起注意。我希望它与Windows.Forms.ComboBox的FlatStyle类似,并且在Windows 7和XP上看起来相同。
主要是,我想改变ComboBox的ToggleButton的外观。
我可以使用Blend并拆开控件模板,然后手动更改它们。但那对我来说听起来并不吸引人。
我尝试使用样式来覆盖ToggleButton的背景,但事实证明整个ComboBox控件实际上是ToggleButton的前端。
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ComboBoxExpiriment2.MainWindow"
x:Name="Window"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Classic" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="204" Height="103">
<Grid x:Name="LayoutRoot">
<ComboBox HorizontalAlignment="Left" Margin="32,26.723,0,0" Width="120" VerticalAlignment="Top" Height="21.277">
<ComboBox.Style>
<Style>
<Setter Property="ToggleButton.Background" Value="Green" />
</Style>
</ComboBox.Style>
</ComboBox>
</Grid>
所以我放弃了,改用Blend来提取它。我发现它实际上是一个名为ComboBoxTransparentButtonStyle的样式,其目标类型为ToggleButton。该样式设置了一个ControlTemplate,使用了一个DockPanel,其中“Microsoft_Windows_Themes:ClassicBorderDecorator”类型被设置到右侧,而这正是我们实际想要控制的东西。(到目前为止,你跟上我了吗?)以下是图片:
<Style x:Key="ComboBoxTransparentButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="Height" Value="Auto"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="{x:Static Microsoft_Windows_Themes:ClassicBorderDecorator.ClassicBorderBrush}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<DockPanel SnapsToDevicePixels="true" Background="{TemplateBinding Background}" LastChildFill="false">
<Microsoft_Windows_Themes:ClassicBorderDecorator x:Name="Border" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" DockPanel.Dock="Right" Background="Green" BorderBrush="{TemplateBinding BorderBrush}" BorderStyle="None" BorderThickness="{TemplateBinding BorderThickness}">
<Path Fill="{TemplateBinding Foreground}" HorizontalAlignment="Center" VerticalAlignment="Center" Data="{StaticResource DownArrowGeometry}"/>
</Microsoft_Windows_Themes:ClassicBorderDecorator>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="BorderStyle" TargetName="Border" Value="AltPressed"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/>
</Trigger>
</Style.Triggers>
</Style>
哎呀。WPF不是很有趣吗?
我提取了样式ComboBoxTransparentButtonStyle,并将其放入另一个项目的application.resources中。问题是,我无法将该样式应用于ComboBox,因为我提取的样式的targetType是ToggleButton,所以TargetTypes不匹配。
总之,你们会怎么做呢?