wpf 组合框背景未在 Windows 8 中应用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16183746/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:39:49  来源:igfitidea点击:

Combobox background not being applied in windows 8

wpfthemeswpf-4.0

提问by Jatin

I am a little confused with wpf themes. I would like to have the wpf screens look the same on Vista, Windows 7 and Windows 8. So I have styled the components accordingly and they don't pose problems except when run on Windows 8. For example I have a combobox and I am changing its default background in xaml like this.

我对 wpf 主题有点困惑。我想让 wpf 屏幕在 Vista、Windows 7 和 Windows 8 上看起来相同。所以我相应地对组件进行了样式设置,除了在 Windows 8 上运行时,它们不会造成问题。例如,我有一个组合框,我是像这样在 xaml 中更改其默认背景。

<Style TargetType="{x:Type ComboBox}" >
    <Setter Property="FontStyle" Value="Normal"/>
    <Setter Property="Height" Value="24" />
    <Setter Property="Background" Value="{StaticResource GradientButtonBackgroundBrush}"/>
</Style>

The combobox Background property has no effect in windows 8 and all I get is a flat rectangle with a arrow on right (the default windows 8 combobox, which is rather poorly designed!).

组合框背景属性在 windows 8 中没有任何影响,我得到的只是一个带有右侧箭头的扁平矩形(默认的 windows 8 组合框,设计相当糟糕!)。

So, my question is that how do I get the combobox look the same on all version of windows. I tried adding windows Aero theme in my App.xaml like below, but it has no effect on the combobox display. Here is how I added Aero theme

所以,我的问题是如何让组合框在所有版本的 Windows 上看起来都一样。我尝试在我的 App.xaml 中添加 windows Aero 主题,如下所示,但它对组合框显示没有影响。这是我添加 Aero 主题的方法

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/PresentationFramework.Aero;component/themes/aero.normalcolor.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>

There is also another doubt regarding themes. I am building the wpf application on a windows 7 machine, which by default (I believe) has Aero Theme set. So, all my styles are based on the Aero theme when viewed on Windows 7 machine. What happens if I run the application on say XP. Then do I need to add an entry for the resource dictionary (Aero theme) in App.xaml as listed in code above?

关于主题还有另一个疑问。我正在 Windows 7 机器上构建 wpf 应用程序,默认情况下(我相信)设置了 Aero Theme。因此,在 Windows 7 机器上查看时,我所有的样式都基于 Aero 主题。如果我在 XP 上运行应用程序会发生什么。那么我是否需要在 App.xaml 中为资源字典(Aero 主题)添加一个条目,如上面代码中所列?

I know my question is a bit vague, but believe me, I am really confused with default themes of wpf on different Windows versions.

我知道我的问题有点含糊,但相信我,我真的对不同 Windows 版本上 wpf 的默认主题感到困惑。

EDIT:I still can't get combobox to style according to my needs. The combobox still appears like a gray rectangle.

编辑:我仍然无法根据我的需要设置组合框的样式。组合框仍然看起来像一个灰色矩形。

Here is what I did. I downloaded the Aero.NormalColor.xaml from microsoft's site and included in themes folder of application. Then I added the following in App.xaml

这是我所做的。我从微软的网站下载了 Aero.NormalColor.xaml 并包含在应用程序的主题文件夹中。然后我在 App.xaml 中添加了以下内容

    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Themes/Aero.NormalColor.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>

Then I Compiled the application and deployed on Windows 8. Still the same combobox as was shown previously. Note that all other elements get styled properly according to the theme. I did the same with Luna.Metallic.xaml and every element gets styled except the ComboBox.

然后我编译了应用程序并部署在 Windows 8 上。仍然是之前显示的相同组合框。请注意,所有其他元素都会根据主题正确设置样式。我对 Luna.Metallic.xaml 做了同样的事情,除了ComboBox之外,每个元素都被设置了样式。

I believe that when I load a particular theme, which defines styles with ControlTemplate, then it should be picked by wpf. I am confused as to why only the ComboBoxeven after giving it a Aero (or Luna) Control Template doesn't change its appearance. Any ideas ?

我相信当我加载一个特定的主题时,它定义了ControlTemplate 的样式,那么它应该由 wpf 选择。我很困惑为什么只有ComboBox即使给它一个 Aero(或 Luna)控制模板也不会改变它的外观。有任何想法吗 ?

EDIT-2Screen shot of combobox appearance on Windows 8 enter image description here

EDIT-2Windows 8 上组合框外观的屏幕截图 在此处输入图片说明

采纳答案by Viv

Well the ComboBoxclickable area is actually a ToggleButton

那么ComboBox可点击区域实际上是一个ToggleButton

and if you look at the Stylefor that ToggleButtonin Windows-8, you see something like:

如果你看一下Style对于ToggleButton在Windows 8,你看到的是这样的:

<ControlTemplate TargetType="{x:Type ToggleButton}">
  <Border x:Name="templateRoot"
          Background="{StaticResource ComboBox.Static.Background}"
          BorderBrush="{StaticResource ComboBox.Static.Border}"
          BorderThickness="{TemplateBinding BorderThickness}"
          SnapsToDevicePixels="true">
...

As you can see from above, Backgroundused is not a {TemplateBinding Background}but {StaticResource ComboBox.Static.Background}. Hence why you see no effect when you set the Backgroundproperty in Windows-8 for that ComboBox

从上面可以看出,Backgroundused 不是 a {TemplateBinding Background}but {StaticResource ComboBox.Static.Background}。因此,为什么Background在 Windows-8 中为此设置属性时看不到任何效果ComboBox

If your looking to carry a Styleacross the different OS Versions(Without having to backtrack and keep checking if new versions screwed up your over-rides), simple rule is Createit yourself.

如果您希望Style跨不同的操作系统版本(无需回溯并不断检查新版本是否搞砸了您的覆盖),简单的规则是自己创建

Create a Styleand set it to be applied by TargetTypeand without a Keyto get applied automatically. That way in any OS it's your Stylethat gets used and not the default underlying one.

创建 aStyle并将其设置为由TargetType和不应用 aKey以自动应用。这样在任何操作系统中都是您Style使用的,而不是默认的底层操作系统。

This thus guarantees your code run's as you expect on every single OS. Base your Style on the default's of any OS and tweak it to your heart's content.

因此,这可以保证您的代码在每个操作系统上都按照您的预期运行。以任何操作系统的默认风格为基础,并根据您的喜好进行调整。

side-note:

旁注

From a usability POV giving the user a Windows-7 ComboBoxin an app that run's on Windows-8 is not very nice(unless your entire app looks like a Windows-7 app which is even worse). Your expecting the user to get used to your app's Style's and forget what he's used to from every other app he uses in his OS that use default Styles based on OS. If you have specific reasons for doing so, go ahead but do consider the implications.

从可用性 POVComboBox来看,在 Windows-8 上运行的应用程序中为用户提供 Windows-7并不是很好(除非您的整个应用程序看起来像一个更糟糕的 Windows-7 应用程序)。您希望用户习惯您的应用程序的样式并忘记他在他的操作系统中使用的使用基于操作系统的默认样式的每个其他应用程序中习惯的内容。如果您有这样做的具体原因,请继续,但要考虑其影响。

Just for example you stated the Windows-8 Style is something your not a fan of, well I'm the opposite. I actually do like the Windows-8 clean and simple look. No distractions to the UserExperience with flashing gradients and things that throw you off the content your putting in front of them. This is an argument that goes on forever. Just be warned abt what the end-user expects and thinks than just what you think is good while writing your program.

举个例子,你说 Windows-8 风格是你不喜欢的东西,我正好相反。实际上,我确实喜欢 Windows-8 干净简单的外观。不会通过闪烁的渐变和让您远离摆在他们面前的内容的事物分散用户体验的注意力。这是一个永远持续下去的争论。请注意最终用户的期望和想法,而不仅仅是您在编写程序时认为好的。

Update:

更新:

Firstly comment on the relevant answer please. Your answer and your comment update has no relation.

请首先评论相关答案。你的回答和你的评论更新没有关系。

Ok and as for your question edit, what you tried has not worked in windows-8 because PresentationFramework.Aero.dlldoes not exist in Windows-8 which is what holds Aero.NormalColor.xaml. In Windows-8 your options are PresentationFramework.Aero2.dllwhich is default and PresentationFramework.AeroLite.dllwhich I think is used by Windows Server 2012(Not Sure)

好的,至于您的问题编辑,您尝试的方法在 windows-8 中PresentationFramework.Aero.dll不起作用,因为 在 Windows-8 中不存在,这就是Aero.NormalColor.xaml. 在 Windows-8 中,您的选项PresentationFramework.Aero2.dll是默认的PresentationFramework.AeroLite.dll,我认为是 Windows Server 2012(不确定)

Try to compile your program on Windows-8 and you'll see it does not even want to compile.

尝试在 Windows-8 上编译您的程序,您会发现它甚至不想编译。

You'll have to explicitly add a reference to PresentationFramework.Aeroand also PresentationUI(which i think is part of .net3) to your project.

您必须显式地向您的项目添加对PresentationFramework.AeroPresentationUI(我认为这是 .net3 的一部分)的引用。

Then you'll have to edit your Aero.NormalColor.xamlto something like:

然后,您必须将您的内容编辑Aero.NormalColor.xaml为:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
                    xmlns:ui="clr-namespace:System.Windows.Documents;assembly=PresentationUI">
...

^^ we explicitly state the assembly for Aero Theme. I don't use Windows-7 so Am not sure if that's all that's needed. but you can give that a try.

^^ 我们明确说明了 Aero Theme 的程序集。我不使用 Windows-7,所以我不确定这是否是全部需要的。但你可以试一试。

Try to compile your code in Windows-8 to make sure it will work fine on Windows-8

尝试在 Windows-8 中编译您的代码以确保它可以在 Windows-8 上正常工作

回答by Jatin

Finally, after hours of frustration, I came accross an explanation post here. Scroll for the LONG ANSWER. It explains exactly the scenario I have been facing particularly Aero style not getting applied to my Combobox. The link explains very well why we need to add a BasedOnattribute to every element that we style if we dont want the default OS style being picked up. So adding this BasedOn for the Combobox got it working for me.

最后,经过几个小时的沮丧之后,我在这里看到了一个解释帖子。滚动查看长答案。它准确地解释了我一直面临的情况,特别是Aero 风格没有应用于我的 Combobox。该链接很好地解释了为什么如果我们不想选择默认的操作系统样式,我们需要为我们设置样式的每个元素添加一个BasedOn属性。所以为 Combobox 添加这个 BasedOn 让它对我来说有效。

<Style TargetType="{x:Type ComboBox}" BasedOn="{StaticResource {x:Type ComboBox}}">

Now the Aero theme style is used for the combobox. As @Viv pointed out it may also require copying of PresentationFramework.Aero.dll and PresentationUI.dllto the windows 8 machine as they are not supplied with the OS.

现在,组合框使用 Aero 主题样式。正如@Viv 指出的那样,它可能还需要将PresentationFramework.Aero.dll 和 PresentationUI.dll复制 到 Windows 8 机器,因为它们不随操作系统一起提供。

Thanks, Nirvan

谢谢,尼尔文

回答by Matstar

I did a bit of a hack on the built-in template. Not the cleanest solution, but removes the headache of having to roll my own template. The code behind basically binds the built-in template border's properties with the combo box's properties.

我对内置模板做了一些修改。不是最干净的解决方案,但消除了不得不滚动我自己的模板的麻烦。后面的代码基本上将内置模板边框的属性与组合框的属性绑定在一起。

<Style TargetType="ComboBox">
    <Setter Property="Border.Background" Value="White"/>
    <EventSetter Event="Loaded" Handler="ComboBox_Loaded"/>
    <Style.Triggers>
        <Trigger Property="IsReadOnly" Value="True">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
        </Trigger>
        <Trigger Property="IsFocused" Value="True">
            <Setter Property="Background" Value="{StaticResource ResourceKey=FocusedControlBackcolorBrush}"/>
            <Setter Property="BorderBrush" Value="{StaticResource ResourceKey=FocusedControlBorderBrush}"/>
        </Trigger>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="BorderBrush" Value="{StaticResource ResourceKey=FocusedControlBorderBrush}"/>
        </Trigger>
    </Style.Triggers>
</Style>


    private void ComboBox_Loaded(object sender, RoutedEventArgs e)
    {
        var comboBox = sender as ComboBox;
        var toggleButton = comboBox.Template?.FindName("toggleButton", comboBox) as ToggleButton;
        var border = toggleButton?.Template.FindName("templateRoot", toggleButton) as Border;
        if (border != null)
        {
            Binding b = new Binding("Background");
            b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ComboBox), 1);
            BindingOperations.SetBinding(border, Control.BackgroundProperty, b);

            b = new Binding("BorderBrush");
            b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ComboBox), 1);
            BindingOperations.SetBinding(border, Control.BorderBrushProperty, b);
        }
    }

回答by CRice

The newer template has a Grid->ToggleButton->Border with a hardcoded background colour which does not respect any background styles. Based on the answer from @Matstar I made a way to sync the background colour across.

较新的模板有一个 Grid->ToggleButton->Border,带有硬编码的背景颜色,不考虑任何背景样式。根据@Matstar 的回答,我找到了一种同步背景颜色的方法。

You can still set the binding to background colour and the code will pick this up and reapply this when needed:

您仍然可以将绑定设置为背景颜色,代码将选择它并在需要时重新应用它:

<ComboBox ItemsSource="{Binding Values}" x:Name="Cbo2"
Background="{Binding Path=SelectedValueBgColor}" ... />

Then in xaml.cs

然后在 xaml.cs

cbo.Loaded += (sender, args) =>
{
    var comboBox = sender as ComboBox;
    if (comboBox != null)
    {
        var toggleButton = comboBox.Template?.FindName("toggleButton", comboBox) as ToggleButton;
        var border = toggleButton?.Template.FindName("templateRoot", toggleButton) as Border;
        if (border != null)
        {
            var existing = BindingOperations.GetBinding(comboBox, BackgroundProperty);
            BindingOperations.SetBinding(border, BackgroundProperty, existing);
        }
    }
};

Make sure your background binding never returns null

确保您的后台绑定永远不会返回 null

If you have no meaningful value return transparent or white or some other default. If binding to a background that returns null the combobox will stop working.

如果您没有有意义的值,则返回透明或白色或其他一些默认值。如果绑定到返回 null 的背景,则组合框将停止工作。

Make sure you notify property changed on your background binding if it needs refreshing when an event happens.

如果在事件发生时需要刷新,请确保在后台绑定上通知属性已更改。

回答by Jatin

In Response to @Viv

回应@Viv

@Viv, I feel that your answer was very clear, but somehow your views/suggestions aren't digestable to me and I will briefly mention why

@Viv,我觉得你的回答很清楚,但不知何故你的观点/建议我无法消化,我将简要说明原因

Your Suggestion

您的建议

If your looking to carry a Style across the different OS Versions(Without having to backtrack and keep checking if new versions screwed up your over-rides), simple rule is Create it yourself.

如果您希望在不同的 OS 版本中使用 Style(无需回溯并不断检查新版本是否搞砸了您的覆盖),简单的规则是自己创建。

It seems impracticable. The very idea of themes is creation of consistent look for all elements in the application and accross all platforms. So, if I use a particular theme provided by the framework, no matter what, I should be able to achieve a satisfactory level of consistency, atleast on major current platforms. Above all, not every one has the expertise to create all the styles and templates from scratch. The concept of themes should be,

似乎是行不通的。主题的想法是为应用程序中的所有元素和所有平台创建一致的外观。所以,如果我使用框架提供的特定主题,无论如何,我应该能够达到令人满意的一致性水平,至少在当前的主要平台上是这样。最重要的是,并非每个人都具备从头开始创建所有样式和模板的专业知识。主题的概念应该是,

"The framework provider is providing the themes that will work well for normal scenarios and if anyone wishing to roll out his themes he is welcome to do so".

“框架提供商正在提供适用于正常场景的主题,如果有人希望推出他的主题,欢迎他这样做”

Instead here the concept seems like

相反,这里的概念似乎

"The framework provider is providing theme and it is not guranted that it will be consistent and work without breaking. So always roll out your themes"

“框架提供商正在提供主题,并不能保证它会保持一致并且不会中断。所以总是推出你的主题”

Your quote

您的报价

As you can see from above, Background used is not a {TemplateBinding Background} but {StaticResource ComboBox.Static.Background}. Hence why you see no effect when you set the Background property in Windows-8 for that ComboBox

从上面可以看出,使用的背景不是 {TemplateBinding Background},而是 {StaticResource ComboBox.Static.Background}。因此,当您在 Windows-8 中为该 ComboBox 设置背景属性时,为什么看不到效果

I don't know whose idea it was to make a template that way! Must be out of his minds or I am too dumb to understand the advantages. Just imagine that I am using some Bluecolored theme in my application and tommorrow, on Windows 9, somebody defines a Redas {StaticResource ComboBox.Static.Background}. So, guess what, I have a fancy window screen now with all my elements themed "Blue"and only the combobox's appear "Red". I mean the very idea of theme is broken here!

我不知道这样制作模板是谁的主意!一定是他脑子进水了,不然我太笨了看不懂优点。想象一下,我在我的应用程序中使用了一些蓝色主题,明天,在 Windows 9 上,有人将红色定义为{StaticResource ComboBox.Static.Background}。所以,你猜怎么着,我现在有一个漂亮的窗口屏幕,我的所有元素都以"Blue"为主题,只有组合框出现"Red"。我的意思是主题的想法在这里被打破了!

Your side note

你的旁注

Just for example you stated the Windows-8 Style is something your not a fan of, well I'm the opposite. I actually do like the Windows-8 clean and simple look.

举个例子,你说 Windows-8 风格是你不喜欢的东西,我正好相反。实际上,我确实喜欢 Windows-8 干净简单的外观。

My combobox looks like a disabled button and I couldn't even change its background! The buttons don't look like they are clickable! Any way as you said this is a personal choice, ofcourse.

我的组合框看起来像一个禁用的按钮,我什至无法改变它的背景!按钮看起来不像是可点击的!无论如何,正如你所说,这当然是个人选择。

My ConclusionI will wait for some time if some one has any suggestions on how I get the combobox working on windows 8. Your answer brings forward the truth, so I would be happy to mark it a correct if I don't get any alternative solution.

我的结论如果有人对我如何让组合框在 Windows 8 上工作有任何建议,我会等待一段时间。你的回答提出了事实,所以如果我没有其他选择,我很乐意将其标记为正确解决方案。

Nirvan

涅槃