【问题标题】:List/Combo Box Background And Selected Colours Under .net 4.5.net 4.5 下的列表/组合框背景和选定颜色
【发布时间】:2012-08-17 14:42:13
【问题描述】:

我有一个应用程序在 Windows 7 及更低版本上运行良好,针对 .net 4 框架。
如果应用程序现在安装在 Windows 8 中(运行 .net 4.5,但仍以 .net 4 为目标),它会为列表框或组合框中的选定项目显示蓝色背景,为焦点项目显示白色背景。无论如何要删除它吗?
我在我的 XAML 中使用以下内容来设置有问题的样式,这似乎解决了 Windows 8 之前的问题。

<ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
                    <Style.Resources>
                        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
                        <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent"/>
                    </Style.Resources>
                </Style>
            </ListBox.ItemContainerStyle>

【问题讨论】:

  • 你找到答案了吗?
  • 我没有在 windows 8 上测试这个,所以 aero2 可能是问题所在,但在 windows 7 上,我不得不使用 InactiveSelectionHighlightBrushKey 而不是 .NET 4.5 中的 ControlBrushKey。
  • 只是想说 Aero2 模板中的许多颜色都是硬编码的。可悲的是。这包括 ComboBoxItem 和 MenuItem 之类的东西。如果你使用 Blend 或 VS 来编辑复制模板会很明显。

标签: .net wpf windows-8


【解决方案1】:

我忘了回到我是如何解决这个问题的......原来你需要做的就是创建一个空白的项目容器样式并将它分配给你的列表框/组合框等......你可以使用它作为以及保持您可能正在使用的当前样式,例如 ListBox Style="{StaticResource CurrentStyle}" ItemContainerStyle="{StaticResource BlankListBoxContainerStyle}" /> 其中 BlankListBoxContainerStyle 类似于.....

<Style x:Key="BlankListBoxContainerStyle" TargetType="{x:Type ListBoxItem}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="FocusVisualStyle"
            Value="{x:Null}"/>
</Style>

【讨论】:

  • 查看我的答案以获得不涉及更改 ListBox 控件模板的解决方案。
【解决方案2】:

您的应用程序会覆盖 SystemColors.HighlightBrushKey(和其他系统键)的值。这适用于通过引用系统颜色来定义其前景色/背景色的控件,就像它们在 Win7 默认主题 (Aero) 中所做的那样。
但是 Win8 默认主题 (Aero2) 对颜色的定义不同。所以你的覆盖没有效果。

主题不需要使用系统颜色。他们碰巧在 Win7/Aero 中这样做了,但这只是因为系统颜色被认为是足够的。

希望这会有所帮助。

【讨论】:

  • 谢谢,这是有道理的。你知道我将如何阻止 Aero2 在我的应用程序中着色吗?
  • 奇怪的是,Aero2 控件没有引用 SystemColors,而是硬编码了颜色。尽管很烦人,但一种方法是覆盖模板。
【解决方案3】:

重新阅读有关框架兼容性的文档,我发现在为 .NET 4 编译并在 Windows 8 上运行时实际上不需要它。

http://msdn.microsoft.com/en-us/library/system.windows.frameworkcompatibilitypreferences%28v=vs.110%29.aspx

但我仍然有 Windows 7 中不存在的蓝色背景,我最终将问题归结为列表视图,该列表视图的样式与我的列表框不同。我发现我实际上并不需要为元素选择元素的能力,因此将列表视图更改为项目控件解决了我的问题。

另见:

http://connect.microsoft.com/VisualStudio/feedback/details/750655/selected-listboxitem-does-not-have-a-background-of-controlbrushkey-when-app-is-unfocused

【讨论】:

  • 很好的发现,遗憾的是该属性仅在 .net 4.5 中可用,而我的目标是 4.0。我会密切关注那个帖子,看看是否出现了除强制所有客户端使用 4.5 之外的解决方法。
  • 我修改了这篇文章,因为我终于找到了一个在 .NET 4 中也能完美运行的解决方案。希望它也能帮助您解决问题。
【解决方案4】:

它被称为系统依赖的默认主题,你并不是真的要搞砸它。你可以通过设置另一个Control.Template来覆盖它。

【讨论】:

  • @Oli:别提我说的了,一个完整的主题几乎不是一个好主意,它可能会激怒一些用户。无论如何,您可以通过设置模板来更改外观,然后控件在每个系统上看起来都一样(除非您将其设置为依赖于系统)。
  • 我已经定义了一个 Listbox.ItemsPanel、Listbox.Template、Listbox.ItemTemplate 和 Listbox.itemcontainerstyle。它在我测试过但不是 windows 的每个版本的 windows 上都有效并且具有相同的视觉风格8. 我错过了什么?
  • 模板通常由模板化组件本身组成。也许模板中使用的一个控件现在具有不同的模板。
  • 我认为这是真的,或者至少使用的颜色画笔发生了变化。我只是不知道什么和在哪里?请记住 .net 4.5 更改了所有 .net 4 程序集,因此任何事情都可能发生变化。
  • 列出两个版本的所有SystemColors.*Brush 并进行比较如何?
【解决方案5】:
<Style.Triggers>
                <Trigger Property="IsSelected" Value="true">
                    <Setter Property="Effect">
                        <Setter.Value>
                            <DropShadowEffect Color="Red"
                              BlurRadius="0"
                              ShadowDepth="0" />
                        </Setter.Value>
                    </Setter>
                </Trigger>

【讨论】:

    【解决方案6】:

    这是我想出的不涉及更改系统颜色或控制模板的方法。只需将 ListBox 包装在新的 UserControl 中即可。

    public partial class StyledListBox : UserControl
    {
        public DataTemplate ItemTemplate
        {
            get { return (DataTemplate)GetValue(ItemTemplateProperty); }
            set { SetValue(ItemTemplateProperty, value); }
        }
    
        public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }
    
        public object SelectedItem
        {
            get { return GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }
    
        public StyledListBox()
        {
            InitializeComponent();
        }
    
        public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(StyledListBox), new FrameworkPropertyMetadata(null));
        public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(StyledListBox), new FrameworkPropertyMetadata(null));
    
        public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(StyledListBox), new FrameworkPropertyMetadata(null)
        {
            BindsTwoWayByDefault = true,
            DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
        });
    }
    

    XAML:

    <UserControl x:Class="StyledListBox"
    
         <ListBox ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type common:StyledListBox}}}"
                  SelectedItem="{Binding SelectedItem, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type common:StyledListBox}}}">
    
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border>
                        <Border.Style>
                            <Style TargetType="{x:Type Border}">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"
                                                 Value="True">
                                        <Setter Property="Background" Value="Red" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Border.Style>
    
                        <ContentPresenter ContentTemplate="{Binding ItemTemplate, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type StyledListBox}}}" />
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </UserControl>
    

    然后只需像使用 ListBox 一样使用包装器 UserControl。您想要控制的任何其他 ListBox 属性都可以简单地以与我的示例中的 ItemsSourceSelectedItem 相同的方式添加到包装器中。

    【讨论】:

    • 这会改变数据模板内边框的颜色,而不是整行(与列表框选择不同)...即使设置 &lt;Setter Property="HorizontalAlignment" Value="Stretch"/&gt; 也无济于事...
    猜你喜欢
    • 2018-12-27
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 2015-05-17
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多