首页 > 解决方案 > WPF 仅在特定条件下应用样式

问题描述

由于从 Win7 迁移到 Win10,我不得不调整组合框的视觉风格,所以这是我目前自定义组合框的风格:

<Style TargetType="{x:Type av:XComboBox}">
                <Setter Property="UIElement.SnapsToDevicePixels" Value="True"/>
                <Setter Property="FrameworkElement.OverridesDefaultStyle" Value="True"/>
                <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
                <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
                <Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
                <Setter Property="TextElement.Foreground" Value="Black"/>
                <Setter Property="FrameworkElement.FocusVisualStyle" Value="{x:Null}"/>
                <Setter Property="Control.Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ComboBox">
                            <Grid>
                                <ToggleButton Name="ToggleButton" Grid.Column="2"
                                    ClickMode="Press" Focusable="False"
                                    IsChecked="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                                    Template="{StaticResource ComboBoxToggleButtonTemplate}"/>
                                <ContentPresenter Name="ContentSite" Margin="5, 3, 23, 3" IsHitTestVisible="False"
                                  HorizontalAlignment="Left" VerticalAlignment="Center"                              
                                  Content="{TemplateBinding ComboBox.SelectionBoxItem}" 
                                  ContentTemplate="{TemplateBinding ComboBox.SelectionBoxItemTemplate}"
                                  ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>
                                <TextBox Name="PART_EditableTextBox" Margin="1, 3, 23, 3" IsReadOnly="{TemplateBinding IsReadOnly}" Visibility="Hidden" Background="Transparent" HorizontalAlignment="Left" VerticalAlignment="Center" Focusable="True" >
                                    <TextBox.Template>
                                        <ControlTemplate TargetType="TextBox" >
                                            <Border Name="PART_ContentHost" Focusable="False" />
                                        </ControlTemplate>
                                    </TextBox.Template>
                                </TextBox>
                                <!-- Popup showing items -->
                                <Popup Name="Popup" Placement="Bottom" Focusable="False" AllowsTransparency="True" IsOpen="{TemplateBinding ComboBox.IsDropDownOpen}" PopupAnimation="Slide">
                                    <Grid Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding FrameworkElement.ActualWidth}" MaxHeight="{TemplateBinding ComboBox.MaxDropDownHeight}">
                                        <Border Name="DropDownBorder" Background="White" Margin="0, 1, 0, 0" CornerRadius="0" BorderThickness="1,1,1,1" BorderBrush="{StaticResource ComboBoxNormalBorderBrush}"/>
                                        <ScrollViewer Margin="4" SnapsToDevicePixels="True">
                                            <ItemsPresenter KeyboardNavigation.DirectionalNavigation="Contained" />
                                        </ScrollViewer>
                                    </Grid>
                                </Popup>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="ItemsControl.HasItems" Value="False">
                                    <Setter Property="FrameworkElement.MinHeight" TargetName="DropDownBorder" Value="95"/>
                                </Trigger>
                                <Trigger Property="UIElement.IsEnabled" Value="False">
                                    <Setter Property="TextElement.Foreground" Value="{StaticResource ComboBoxDisabledForegroundBrush}"/>
                                </Trigger>
                                <Trigger Property="ComboBox.IsVisible" Value="True">
                                    <Setter Property="Border.BorderBrush" TargetName="DropDownBorder" Value="#878787"/>
                                </Trigger>                                
                                <Trigger Property="ItemsControl.IsGrouping" Value="True">
                                    <Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
                                </Trigger>
                                <Trigger Property="ComboBox.IsEditable" Value="True">
                                    <Setter Property="KeyboardNavigation.IsTabStop" Value="False"/>
                                    <Setter Property="UIElement.Visibility" TargetName="PART_EditableTextBox" Value="Visible"/>
                                    <Setter Property="UIElement.Visibility" TargetName="ContentSite" Value="Hidden"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

由于该应用程序同时在 Win7 和 Win10 上运行,我将只在 Win10 上应用该样式。有没有办法做到这一点?我对此无能为力。我想过一个转换器,但如何应用它?

标签: wpfcomboboxwindows-10

解决方案


你可以给你Style一个x:Key并实现一个自定义标记扩展:

public class Windows10StyleExtension : MarkupExtension
{
    private readonly string _key;

    public Windows10StyleExtension(string key)
    {
        _key = key;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (!IsWindows7OrLower)
            return new StaticResourceExtension(_key).ProvideValue(serviceProvider);
        return null;
    }

    private bool IsWindows7OrLower =>
        (Environment.OSVersion.Version.Major + (double)Environment.OSVersion.Version.Minor / 10) <= 6.1;
}

XAML:

<Style x:Key="style" TargetType="{x:Type av:XComboBox}">
...
<av:XComboBox Style="{local:Windows10Style style}" />

推荐阅读