优雅地重写 WPF 中 ComboBox 的 ToggleButton 的样式

发布于 2024-08-12 23:04:10 字数 4276 浏览 5 评论 0原文

我有一个关于如何优雅地覆盖控件可视树深处的任意元素的问题。我还尝试以几种不同的方式解决它,但每种方式都遇到了几个问题。通常,当我尝试三种不同的路径并且每一种都失败时,我会下楼,喝杯咖啡,然后询问比我更聪明的人。所以我在这里。

具体细节:

我想扁平化组合框的样式,这样它就不会引起人们的注意。我希望它类似于 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。该样式设置一个使用 DockPanel 的 ControlTemplate,该 DockPanel 的右侧设置了“Microsoft_Windows_Themes:ClassicBorderDecorator”类型,这就是我们实际想要控制的内容。 (到目前为止你还和我在一起吗?)
这是图片:

Example

<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>

Arg。 WPF 不是很火爆吗?

因此,我提取了 ComboBoxTransparentButtonStyle 样式并将其放入另一个项目的 application.resources 中。问题是我无法将该样式应用于 ComboBox,因为我提取的样式的 targetType 为 ToggleButton,因此 TargetType 不匹配。

tl;dr 你们会怎么做呢?

I have a question regarding how to elegantly override an arbitrary element deep inside a control's visual tree. I also have attempted to resolve it in a few different ways, but I've run into several problems with each. Usually when I try three different paths and fail at each one I go downstairs, have a coffee, and ask someone smarter than myself. So here I am.

Specifics:

I want to flatten the style of a combo box so that it will not draw attention to itself. I want it to be similar to Windows.Forms.ComboBox's FlatStyle I want it to look the same on Windows 7 and XP.

Mainly, I want to change the look of a ComboBox's ToggleButton.

I could just use Blend and rip the control template's guts out and manually change them. That doesn't sound very appetizing to me.

I tried using a style to override the ToggleButton's background, but it turns out that the whole ComboBox control is actually a front for a 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>

So I gave up and ripped it using Blend. I found that it's actually a Style called ComboBoxTransparentButtonStyle with a target type of ToggleButton. The style sets a ControlTemplate that uses a DockPanel that has a "Microsoft_Windows_Themes:ClassicBorderDecorator" type set to the right, and that's what we're actually trying to control. (Are you with me so far?)
Here's the pic:

Example

<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>

Arg. Isn't WPF a blast?

So I extracted the style ComboBoxTransparentButtonStyle and dropped it into another project's application.resources. Problem is I can't apply that style to a ComboBox because the style I extracted has a targetType of ToggleButton, so the TargeTypes don't match.

tl;dr how would you guys do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

明月夜 2024-08-19 23:04:10

对此没有一个优雅的解决方案。您能做的最好的事情就是覆盖整个 ComboBox 的样式,以便您可以更改它为 ToggleButton 设置的样式。

您可以使用 Blend 来获取样式,但这可能不是最简单的方法。如果安装了 Blend,请转到“[程序文件或安装 Blend 的位置]\SystemThemes\WPF\areo.normalcolor.xaml”。

There isn't an elegant solution for this. The best you can do is override the style for the entire ComboBox so that you can change the style it sets for the ToggleButton.

You can use Blend to get the styles, however that probabliy isn't the easiest way. If you have Blend installed, go to "[Program files or where Blend is installed]\SystemThemes\WPF\areo.normalcolor.xaml".

落花浅忆 2024-08-19 23:04:10

一个可行的解决方案


嗨,这个样式可以满足您的需求,请随意根据需要进行编辑:

    <SolidColorBrush x:Key="WindowBackgroundBrush" Color="White" />

<SolidColorBrush x:Key="MainColor" Color="DeepSkyBlue"/>
<SolidColorBrush x:Key="MainColorLight" Color="LightSkyBlue"/>
<SolidColorBrush x:Key="MainColorDark" Color="#00A7DF"/>

<SolidColorBrush x:Key="BorderMainBrush" Color="LightGray"/>
<SolidColorBrush x:Key="BorderDarkMainBrush" Color="#C0C0C0"/>

<SolidColorBrush x:Key="BackgroundGrayDark" Color="#FFEFEFEF"/>
<SolidColorBrush x:Key="BackgroundGrayLight" Color="#F5F5F5"/>

<SolidColorBrush x:Key="ForegroundDisabledBrush" Color="DimGray"/>
<SolidColorBrush x:Key="ForegroundBrush" Color="Black"/>


<LinearGradientBrush x:Key="FormBackgroundBrush"
                             EndPoint="0.5,1" StartPoint="0.5,0">
    <GradientStop Color="#FFFFFD" Offset="0.31" />
    <GradientStop Color="#FFF8F8F8" Offset="1" />
</LinearGradientBrush>


<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="ToggleButton">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="20" />
        </Grid.ColumnDefinitions>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Normal"/>
                <VisualState x:Name="MouseOver"/>
                <VisualState x:Name="Pressed"/>
                <VisualState x:Name="Disabled"/>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Border x:Name="Border" SnapsToDevicePixels="True" Grid.ColumnSpan="2" Background="{DynamicResource BackgroundGrayDark}" BorderBrush="{DynamicResource BorderDarkMainBrush}" BorderThickness="1"  />
        <Border x:Name="Border2" Grid.Column="0" SnapsToDevicePixels="True" Margin="1" Background="{StaticResource WindowBackgroundBrush}" BorderBrush="{DynamicResource BorderDarkMainBrush}" BorderThickness="0,0,1,0" />
        <Path x:Name="Arrow" Grid.Column="1" Data="M 0 0 L 4 4 L 8 0 Z" Fill="DimGray" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="ToggleButton.IsMouseOver" Value="true">
            <Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColor}" />
            <Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColor}" />
            <Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColor}" />
            <Setter Property="Fill" TargetName="Arrow" Value="White" />
        </Trigger>
        <Trigger Property="ToggleButton.IsChecked" Value="true">
            <Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorDark}" />
            <Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorDark}" />
            <Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorDark}" />
            <Setter Property="Fill" TargetName="Arrow" Value="White" />
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Background" TargetName="Border" Value="{DynamicResource BackgroundGrayLight}" />
            <Setter Property="BorderBrush" TargetName="Border" Value="{StaticResource BorderMainBrush}" />
            <Setter Property="Foreground" Value="{StaticResource ForegroundDisabledBrush}" />
        </Trigger>
        <DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay}" Value="True">
            <Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorLight}" />
            <Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorLight}" />
            <Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorLight}" />
            <Setter Property="Fill" TargetName="Arrow" Value="White" />
        </DataTrigger >
    </ControlTemplate.Triggers>
</ControlTemplate>

<ControlTemplate x:Key="ComboBoxTextBox" TargetType="TextBox">
    <Border x:Name="PART_ContentHost" Background="{TemplateBinding Background}" Focusable="False" />
</ControlTemplate>

<Style TargetType="ComboBox">
    <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
    <Setter Property="VerticalAlignment" Value="Center" />
    <Setter Property="OverridesDefaultStyle" Value="true" />
    <Setter Property="IsEditable" Value="True"/>
    <Setter Property="SnapsToDevicePixels" Value="true" />
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
    <Setter Property="ScrollViewer.CanContentScroll" Value="true" />
    <Setter Property="Margin" Value="2" />
    <Setter Property="MinHeight" Value="20" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ComboBox">
                <Grid>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver"/>
                            <VisualState x:Name="Disabled"/>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <ToggleButton x:Name="ToggleButton" Grid.Column="2" ClickMode="Press" Focusable="false"
                        IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                        Template="{StaticResource ComboBoxToggleButton}"/>

                    <ContentPresenter Margin="3,3,23,3" Content="{TemplateBinding SelectionBoxItem}"
                        ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
                        ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                        HorizontalAlignment="Left" IsHitTestVisible="False" x:Name="ContentSite"
                        VerticalAlignment="Center" />

                    <TextBox Style="{x:Null}" x:Name="PART_EditableTextBox" Margin="3,3,23,3" Background="Transparent"
                        Focusable="True" HorizontalAlignment="Left" IsReadOnly="{TemplateBinding IsReadOnly}"
                        Template="{StaticResource ComboBoxTextBox}" VerticalAlignment="Center" Visibility="Hidden" />

                    <Popup AllowsTransparency="True" Focusable="False" IsOpen="{TemplateBinding IsDropDownOpen}" x:Name="Popup" Placement="Bottom" PopupAnimation="Fade">
                        <Grid MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" x:Name="DropDown" SnapsToDevicePixels="True">
                            <Border x:Name="DropDownBorder" Background="White" BorderBrush="{StaticResource BorderDarkMainBrush}" BorderThickness="1" CornerRadius="0" />
                            <ScrollViewer Margin="2" SnapsToDevicePixels="True">
                                <StackPanel KeyboardNavigation.DirectionalNavigation="Contained" IsItemsHost="True" TextBlock.Foreground="Black" />
                            </ScrollViewer>
                        </Grid>
                    </Popup>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="HasItems" Value="false">
                        <Setter Property="MinHeight" TargetName="DropDownBorder" Value="95" />
                    </Trigger>
                    <Trigger Property="IsGrouping" Value="true">
                        <Setter Property="ScrollViewer.CanContentScroll" Value="false" />
                    </Trigger>
                    <Trigger Property="IsEditable" Value="true">
                        <Setter Property="IsTabStop" Value="false" />
                        <Setter Property="Visibility" TargetName="PART_EditableTextBox" Value="Visible" />
                        <Setter Property="Visibility" TargetName="ContentSite" Value="Hidden" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
    </Style.Triggers>
</Style>

请注意切换按钮样式内的DataTrigger部分,它挂钩到其模板化父级的IsKeyboardFocusWithin 属性而不是 IsFocused 属性,因为如果将 ComboBox.IsEditable 设置为 True,最后一个属性将不起作用code> 就像我以这种风格所做的那样。

<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay}" Value="True">
    <Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorLight}" />
    <Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorLight}" />
    <Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorLight}" />
    <Setter Property="Fill" TargetName="Arrow" Value="White" />
</DataTrigger >

A Working Solution


Hi, this style satisfies your needs, feel free to edit it as you need:

    <SolidColorBrush x:Key="WindowBackgroundBrush" Color="White" />

<SolidColorBrush x:Key="MainColor" Color="DeepSkyBlue"/>
<SolidColorBrush x:Key="MainColorLight" Color="LightSkyBlue"/>
<SolidColorBrush x:Key="MainColorDark" Color="#00A7DF"/>

<SolidColorBrush x:Key="BorderMainBrush" Color="LightGray"/>
<SolidColorBrush x:Key="BorderDarkMainBrush" Color="#C0C0C0"/>

<SolidColorBrush x:Key="BackgroundGrayDark" Color="#FFEFEFEF"/>
<SolidColorBrush x:Key="BackgroundGrayLight" Color="#F5F5F5"/>

<SolidColorBrush x:Key="ForegroundDisabledBrush" Color="DimGray"/>
<SolidColorBrush x:Key="ForegroundBrush" Color="Black"/>


<LinearGradientBrush x:Key="FormBackgroundBrush"
                             EndPoint="0.5,1" StartPoint="0.5,0">
    <GradientStop Color="#FFFFFD" Offset="0.31" />
    <GradientStop Color="#FFF8F8F8" Offset="1" />
</LinearGradientBrush>


<ControlTemplate x:Key="ComboBoxToggleButton" TargetType="ToggleButton">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="20" />
        </Grid.ColumnDefinitions>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Normal"/>
                <VisualState x:Name="MouseOver"/>
                <VisualState x:Name="Pressed"/>
                <VisualState x:Name="Disabled"/>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Border x:Name="Border" SnapsToDevicePixels="True" Grid.ColumnSpan="2" Background="{DynamicResource BackgroundGrayDark}" BorderBrush="{DynamicResource BorderDarkMainBrush}" BorderThickness="1"  />
        <Border x:Name="Border2" Grid.Column="0" SnapsToDevicePixels="True" Margin="1" Background="{StaticResource WindowBackgroundBrush}" BorderBrush="{DynamicResource BorderDarkMainBrush}" BorderThickness="0,0,1,0" />
        <Path x:Name="Arrow" Grid.Column="1" Data="M 0 0 L 4 4 L 8 0 Z" Fill="DimGray" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="ToggleButton.IsMouseOver" Value="true">
            <Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColor}" />
            <Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColor}" />
            <Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColor}" />
            <Setter Property="Fill" TargetName="Arrow" Value="White" />
        </Trigger>
        <Trigger Property="ToggleButton.IsChecked" Value="true">
            <Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorDark}" />
            <Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorDark}" />
            <Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorDark}" />
            <Setter Property="Fill" TargetName="Arrow" Value="White" />
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Background" TargetName="Border" Value="{DynamicResource BackgroundGrayLight}" />
            <Setter Property="BorderBrush" TargetName="Border" Value="{StaticResource BorderMainBrush}" />
            <Setter Property="Foreground" Value="{StaticResource ForegroundDisabledBrush}" />
        </Trigger>
        <DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay}" Value="True">
            <Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorLight}" />
            <Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorLight}" />
            <Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorLight}" />
            <Setter Property="Fill" TargetName="Arrow" Value="White" />
        </DataTrigger >
    </ControlTemplate.Triggers>
</ControlTemplate>

<ControlTemplate x:Key="ComboBoxTextBox" TargetType="TextBox">
    <Border x:Name="PART_ContentHost" Background="{TemplateBinding Background}" Focusable="False" />
</ControlTemplate>

<Style TargetType="ComboBox">
    <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
    <Setter Property="VerticalAlignment" Value="Center" />
    <Setter Property="OverridesDefaultStyle" Value="true" />
    <Setter Property="IsEditable" Value="True"/>
    <Setter Property="SnapsToDevicePixels" Value="true" />
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
    <Setter Property="ScrollViewer.CanContentScroll" Value="true" />
    <Setter Property="Margin" Value="2" />
    <Setter Property="MinHeight" Value="20" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ComboBox">
                <Grid>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver"/>
                            <VisualState x:Name="Disabled"/>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <ToggleButton x:Name="ToggleButton" Grid.Column="2" ClickMode="Press" Focusable="false"
                        IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                        Template="{StaticResource ComboBoxToggleButton}"/>

                    <ContentPresenter Margin="3,3,23,3" Content="{TemplateBinding SelectionBoxItem}"
                        ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
                        ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                        HorizontalAlignment="Left" IsHitTestVisible="False" x:Name="ContentSite"
                        VerticalAlignment="Center" />

                    <TextBox Style="{x:Null}" x:Name="PART_EditableTextBox" Margin="3,3,23,3" Background="Transparent"
                        Focusable="True" HorizontalAlignment="Left" IsReadOnly="{TemplateBinding IsReadOnly}"
                        Template="{StaticResource ComboBoxTextBox}" VerticalAlignment="Center" Visibility="Hidden" />

                    <Popup AllowsTransparency="True" Focusable="False" IsOpen="{TemplateBinding IsDropDownOpen}" x:Name="Popup" Placement="Bottom" PopupAnimation="Fade">
                        <Grid MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{TemplateBinding ActualWidth}" x:Name="DropDown" SnapsToDevicePixels="True">
                            <Border x:Name="DropDownBorder" Background="White" BorderBrush="{StaticResource BorderDarkMainBrush}" BorderThickness="1" CornerRadius="0" />
                            <ScrollViewer Margin="2" SnapsToDevicePixels="True">
                                <StackPanel KeyboardNavigation.DirectionalNavigation="Contained" IsItemsHost="True" TextBlock.Foreground="Black" />
                            </ScrollViewer>
                        </Grid>
                    </Popup>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="HasItems" Value="false">
                        <Setter Property="MinHeight" TargetName="DropDownBorder" Value="95" />
                    </Trigger>
                    <Trigger Property="IsGrouping" Value="true">
                        <Setter Property="ScrollViewer.CanContentScroll" Value="false" />
                    </Trigger>
                    <Trigger Property="IsEditable" Value="true">
                        <Setter Property="IsTabStop" Value="false" />
                        <Setter Property="Visibility" TargetName="PART_EditableTextBox" Value="Visible" />
                        <Setter Property="Visibility" TargetName="ContentSite" Value="Hidden" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
    </Style.Triggers>
</Style>

Note the DataTrigger part inside the toggle button style, it hooks to its templated parent's IsKeyboardFocusWithin property istead of IsFocused property, because the last one won't work if you set the ComboBox.IsEditable to True as I did in this style.

<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay}" Value="True">
    <Setter Property="Background" TargetName="Border" Value="{DynamicResource MainColorLight}" />
    <Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource MainColorLight}" />
    <Setter Property="BorderBrush" TargetName="Border2" Value="{DynamicResource MainColorLight}" />
    <Setter Property="Fill" TargetName="Arrow" Value="White" />
</DataTrigger >
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文