为什么 WPF 应用程序在 Windows 7 和 Windows 8 之间看起来不同,这可以修复吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21727468/
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
Why do WPF Applications look different between Windows 7 and Windows 8 and can this be fixed?
提问by Sheridan
I'm really surprised that this question does not appear to have been asked yet... if it has, but I just couldn't find it, apologies.
我真的很惊讶这个问题似乎还没有被问过......如果有,但我找不到它,抱歉。
Ok, so my work computer has just been upgraded from Windows 7 to Windows 8. To my absolute horror, my WPF Application looks different in several ways... by different, I mean worse, uglier, controls not lined up correctly, etc. Here is an example:
好的,所以我的工作计算机刚刚从 Windows 7 升级到 Windows 8。令我绝对震惊的是,我的 WPF 应用程序在几个方面看起来不同......下面是一个例子:
Windows 7:
Windows 7的:
Windows 8:
视窗 8:
Windows 8 problems (just from this image):
Windows 8 问题(仅来自此图像):
- Wrong title bar including buttons (Minimise, Close, etc.)
- Wrong size Font in title bar
- Wrong FontWeight in headings (Windows 7 SemiBold setting = Windows 8 Bold setting)
- Icon (or text) misaligned in title bar
- Icon in title bar is veryblurry
- Wrong Padding and/or Margin settings spacing out items on left
- Wrong Padding and/or Margin settings reducing Textbox Heights on right
- 'Hidden' default selection colour on items on left no longer hidden
- Back to front Checkbox tick
- Images on some Buttons are very blurry
- 错误的标题栏,包括按钮(最小化、关闭等)
- 标题栏中的字体大小错误
- 标题中的 FontWeight 错误(Windows 7 SemiBold 设置 = Windows 8 Bold 设置)
- 标题栏中的图标(或文本)未对齐
- 标题栏中的图标非常模糊
- 错误的填充和/或边距设置将左侧的项目隔开
- 错误的填充和/或边距设置减少了右侧的文本框高度
- 左侧项目的“隐藏”默认选择颜色不再隐藏
- 回到前面 复选框勾选
- 某些按钮上的图像非常模糊
So, my question is this:
所以,我的问题是:
Why do WPF Applications look different between Windows 7 and Windows 8 and can this be fixed?
为什么 WPF 应用程序在 Windows 7 和 Windows 8 之间看起来不同,这可以修复吗?
To clarify this, I'm notafter a list of differences between WPF on the two operating systems. I'm also notafter fixes for the individual points listed above. I would like for someone to explain whythese UIs look different, eg. what is causing these differences. I have also heard talk of some system settings in WPF that would enable me to make the PC render the application as if it were on Windows 7, but I don't know how truthful that was.
为了澄清这一点,我不是在列出两个操作系统上 WPF 之间的差异列表。我也没有针对上面列出的各个点进行修复。我希望有人解释为什么这些 UI 看起来不同,例如。是什么导致了这些差异。我还听说过 WPF 中的一些系统设置,这将使我能够让 PC 呈现应用程序,就像它在 Windows 7 上一样,但我不知道这是多么真实。
UPDATE >>>
更新 >>>
As @AndrasSeb? kindly pointed out, there is a StackOverflow question named Windows 7 theme for WPF?, which fixes a similar problem for Windows XP. Unfortunately, it doesn't seem to have any effect on Windows 8. Are there any Microsoft users out there that actuallyknow what differences were implemented to cause this problem? Or anyone?
作为@AndrasSeb?善意地指出,WPF有一个名为Windows 7 主题的 StackOverflow 问题?,它修复了 Windows XP 的类似问题。不幸的是,它似乎对 Windows 8 没有任何影响。是否有任何 Microsoft 用户实际上知道实施了哪些差异来导致此问题?或者任何人?
UPDATE 2 >>>
更新 2 >>>
Ok, so after some more testing, I'm beginning to think that this problem is notrelated to the Windows Theme. Using the code provided in @Gusdor's answer, I tried changing the theme to Aero
and there was no visible difference... that got me thinking. I then changed it to Luna
to test that code and it worked.
好了,经过这么一些更多的测试,我开始认为这个问题是不相关的Windows主题。使用@Gusdor 的回答中提供的代码,我尝试将主题更改为Aero
并且没有明显的差异......这让我开始思考。然后我将其更改Luna
为测试该代码并且它起作用了。
By 'worked', I mean that the Windows Theme changed, but the UI controls, or more accurately, the incorrect Padding
and Margin
remained. I then tried changing the Theme to Luna
using the XAML method mentioned by @AndrasSeb? and the same thing happened... the ScrollBar
s looked different, so I could see that the Theme had changed, but the problem remained.
通过“有效”,我的意思是 Windows 主题改变了,但 UI 控制,或者更准确地说,不正确Padding
并且Margin
仍然存在。然后我尝试将主题更改为Luna
使用@AndrasSeb 提到的 XAML 方法?同样的事情发生了...... ScrollBar
s 看起来不同,所以我可以看到主题已经改变,但问题仍然存在。
So now I'm thinking that this might have something to do with the fact that this is a brand new computer that I'm working on... might there be some dll or setting that I need to install? I'm really just guessing here - I have the whole Microsoft .NET Framework installed to version 4.5.1 as I'm on Windows 8.1.
所以现在我在想,这可能与我正在使用的全新计算机有关...是否有一些 dll 或我需要安装的设置?我真的只是在这里猜测 - 我将整个 Microsoft .NET Framework 安装到版本 4.5.1,因为我在 Windows 8.1 上。
This is an absolute nightmare as I don't have time to go and fix every view in this large application. Please help if you can.
这绝对是一场噩梦,因为我没有时间去修复这个大型应用程序中的每个视图。如果可以的话请帮忙。
采纳答案by Sheridan
Ok, so unfortunately, there was no quick fix for this problem. If you are in a similar situation and the answers supplied here do not work for you either, then here is a summary of the changes that I manually needed to make in order to make the UI on Windows 8 appear the same as the UI on Windows 7.
好吧,很遗憾,这个问题没有快速解决方案。如果您处于类似的情况并且此处提供的答案也不适合您,那么这里是我手动需要进行的更改的摘要,以使 Windows 8 上的 UI 看起来与 Windows 上的 UI 相同7.
TextBox
: Needed to add Padding
to default Style
:
TextBox
:需要添加Padding
到默认值Style
:
<Setter Property="Padding" Value="1.5,2" />
ListBoxItem
: Needed to provide new ControlTemplate
to hide selection and mouse over background colours:
ListBoxItem
:需要提供新ControlTemplate
的隐藏选择和鼠标悬停在背景颜色上:
<Style x:Key="DefaultListBoxItem" TargetType="{x:Type ListBoxItem}">
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="2,0,1,0" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="Local" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="Opacity" Duration="0" To=".55" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected" />
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Visibility" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="contentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}"/>
<Rectangle x:Name="FocusVisualElement" Fill="{x:Null}" Stroke="{x:Null}" StrokeThickness="0" Visibility="Collapsed" RadiusX="1" RadiusY="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
ComboBoxItem
: Needed to provide new ControlTemplate
to change selection and mouse over background colours:
ComboBoxItem
:需要提供新ControlTemplate
的更改选择和鼠标悬停背景颜色:
<Style x:Key="{x:Type ComboBoxItem}" TargetType="{x:Type ComboBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<Border x:Name="Border" Padding="2" SnapsToDevicePixels="true" Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="#FF47484C" /> <!-- Background mouse over colour -->
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="White" /> <!-- Foreground mouse over colour -->
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="#FF47484C" /> <!-- Background selection colour -->
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="White" /> <!-- Foreground selection colour -->
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="Red" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
CheckBox
: Needed to provide new ControlTemplate
to stop tick from appearing back to front when Bullet
is to the right of the Content
(thanks to Fredrik's answer to the Default ControlTemplate for CheckBoxquestion here on Stack Overflow:
CheckBox
:需要提供新的ControlTemplate
以阻止刻度线出现Bullet
在右侧时Content
(感谢 Fredrik对 Stack Overflow 上CheckBox问题的默认 ControlTemplate问题的回答:
<SolidColorBrush x:Key="CheckBoxFillNormal" Color="#F4F4F4" />
<SolidColorBrush x:Key="CheckBoxStroke" Color="#8E8F8F" />
<Style x:Key="EmptyCheckBoxFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="1" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CheckRadioFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="14,0,0,0" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Type CheckBox}" TargetType="{x:Type CheckBox}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="{StaticResource CheckBoxFillNormal}"/>
<Setter Property="BorderBrush" Value="{StaticResource CheckBoxStroke}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource EmptyCheckBoxFocusVisual}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<BulletDecorator Background="Transparent" SnapsToDevicePixels="true">
<BulletDecorator.Bullet>
<Aero:BulletChrome BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" IsChecked="{TemplateBinding IsChecked}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}"/>
</BulletDecorator.Bullet>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</BulletDecorator>
<ControlTemplate.Triggers>
<Trigger Property="HasContent" Value="true">
<Setter Property="FocusVisualStyle" Value="{StaticResource CheckRadioFocusVisual}"/>
<Setter Property="Padding" Value="4,0,0,0"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
To remove the horrendous title bar and display the default Windows 8 one: Needed to upgrade to .NET 4.5 and utilise the included System.Windows.Controls.Ribbon
namespace library instead of the separate 'Microsoft Ribbon for WPF' (RibbonControlsLibrary) dll previously used.
删除可怕的标题栏并显示默认的 Windows 8: 需要升级到 .NET 4.5 并利用包含的System.Windows.Controls.Ribbon
命名空间库,而不是以前使用的单独的“Microsoft Ribbon for WPF”(RibbonControlsLibrary)dll。
Unfortunately, I never found out how to reproduce the SemiBold
setting of the FontWeight
property on Windows 8. If anyone knows how to do this, please let me know.
不幸的是,我从来没有发现如何在 Windows 8 上重现属性的SemiBold
设置FontWeight
。如果有人知道如何做到这一点,请告诉我。
On the whole, the move to Windows 8 has been a painful and troubling experience. I hope this information will help others in a slightly less painful manner.
总的来说,迁移到 Windows 8 是一次痛苦而令人不安的经历。我希望这些信息能以稍微减轻痛苦的方式帮助其他人。
回答by Gusdor
The problem (as described in other answers) is that WPF picks a default theme determined by the operating system version.
问题(如其他答案中所述)是 WPF 选择由操作系统版本确定的默认主题。
You need to overridethis behavior. THIS ARTICLEdescribes how:
您需要覆盖此行为。这篇文章描述了如何:
WPF comes with a few theme assemblies, one for each Windows theme (Luna, Royale and Aero and the fallback theme, Classic.) Usually the theme is loaded according to your current system theme, but if you want to create a consistent look for your application, you may want to force-load a specific one.
To accomplish that, simply add the following code in your Application Startup event (this example shows how to use the Aero theme):
WPF 附带了一些主题程序集,每个 Windows 主题(Luna、Royale 和 Aero 以及后备主题、Classic)一个。通常主题是根据您当前的系统主题加载的,但是如果您想为您的应用程序,您可能想要强制加载特定的应用程序。
为此,只需在您的应用程序启动事件中添加以下代码(此示例展示了如何使用 Aero 主题):
Uri uri = new Uri(“PresentationFramework.Aero;V3.0.0.0;31bf3856ad364e35;component\themes/aero.normalcolor.xaml”, UriKind.Relative);
Resources.MergedDictionaries.Add(Application.LoadComponent(uri) as ResourceDictionary);
It's important to specify the version and the public key token. Otherwise you'll have to copy the theme assembly to the folder of your executable. The reason I'm adding it to the merged dictionaries collection is that I don't want to lose other resources I added to the App.xaml file.
指定版本和公钥令牌很重要。否则,您必须将主题程序集复制到可执行文件的文件夹中。我将它添加到合并词典集合的原因是我不想丢失我添加到 App.xaml 文件的其他资源。
回答by Andras Sebo
If you use WPF without custom (explicit) style it is going to use standard windows 7 aero style. In case of windows 8 it is different (aero2).
如果您使用没有自定义(显式)样式的 WPF,它将使用标准的 windows 7 航空样式。在 windows 8 的情况下是不同的 (aero2)。
If you would like to make sure, your application appears same on windows7 and on windows8 as well I recommend to create custom style where you define margin, paddings, fonts, etc by yourself.
如果您想确保您的应用程序在 windows7 和 windows8 上显示相同,我建议您创建自定义样式,您可以自己定义边距、填充、字体等。
回答by A. Wieser
Your problem may be related to this
您的问题可能与此有关
There is currently a bug within the WPF ribbon library, which causes the Windows 8 theme not to apply if a ribbonwindow is being used.
WPF 功能区库中当前存在一个错误,如果使用功能区窗口,该错误会导致 Windows 8 主题不适用。
Furthermore Windows 7 and 8 use simply different styles for their Controls such as Textboxes. When developing for multiple platforms, be it only Windows, you must be aware that sizes, margins and paddings change. Instead of absolute values you should let the controls dictate their need for space by avoiding setting explicit heights or widths altogether.
此外,Windows 7 和 8 对其控件(例如文本框)使用不同的样式。在为多个平台开发时,无论是仅 Windows,您必须意识到大小、边距和填充会发生变化。您应该通过避免完全设置明确的高度或宽度来让控件决定它们对空间的需求,而不是绝对值。