23

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:

enter image description here

Windows 8:

enter image description here

Windows 8 problems (just from this image):

  • 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 very blurry
  • 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

So, my question is this:

Why do WPF Applications look different between Windows 7 and Windows 8 and can this be fixed?

To clarify this, I'm not after a list of differences between WPF on the two operating systems. I'm also not after fixes for the individual points listed above. I would like for someone to explain why these 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.


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 actually know what differences were implemented to cause this problem? Or anyone?


UPDATE 2 >>>

Ok, so after some more testing, I'm beginning to think that this problem is not related 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.

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 ScrollBars looked different, so I could see that the Theme had changed, but the problem remained.

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.

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.

Community
  • 1
  • 1
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • 1
    "system settings in WPF that would enable me to make the PC render the application as if it were on Windows 7" I believe that is accomplished by adding a reference to the OS-specific PresentationFramework (Aero for Windows 7, Aero2 for 8) or something along those lines. I remember trying it before, however I don't recall the details of how I did it, or how well it would work with the rest of your customizations. – BoltClock Feb 12 '14 at 12:08
  • Ok, I can look into that, thanks. – Sheridan Feb 12 '14 at 12:16

4 Answers4

10

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.

TextBox: Needed to add Padding to default Style:

<Setter Property="Padding" Value="1.5,2" />

ListBoxItem: Needed to provide new ControlTemplate to hide selection and mouse over background colours:

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

<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 CheckBox question here on Stack Overflow:

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

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.

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.

Community
  • 1
  • 1
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • Still not able to make Main Window Buttons (Close, Maximise, Minimise) look like default Windows 8 Window buttons. Could you please post the template for those buttons as well? – deathrace Nov 23 '15 at 09:52
  • I have the same problem it works well in windows 7 but when its running in windows 10 label are partially clipped. Did it solve the problem by changing the padding manually? – Prince Jea Jun 09 '16 at 09:48
  • It did on Windows 8. Just try it and see. :) – Sheridan Jun 10 '16 at 07:58
  • What I did is I change the margin and padding's manually on code and it solved the problem. Did you try the OS specific presentation framework? how did that go? I reference aero on my app and still the margins and padding's looks different on windows 8 and 10. – Prince Jea Jun 14 '16 at 06:20
  • 1
    @PrinceJea, any styles that you define will override the specific theme styles, so just explicitly define styles for the properties that look different. – Sheridan Jun 22 '16 at 07:50
3

The problem (as described in other answers) is that WPF picks a default theme determined by the operating system version.

You need to override this behavior. THIS ARTICLE describes 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):

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.

Gusdor
  • 14,001
  • 2
  • 52
  • 64
  • Thanks @Gusdor, but I don't think that this problem *does* relate to Windows Themes... please see my updated question. – Sheridan Feb 13 '14 at 13:24
  • @Sheridan very strange. I make a habit of explicitly styling margins to avoid surprises like this. Nice UI btw. – Gusdor Feb 13 '14 at 13:27
  • I think that I'm going to have to do that... it's almost like they changed the previous defaults for the UI controls... for example, it seems as though they changed the default `TextBox.Padding` property from `3` or `5` or something more than `0` to `0` in Windows 8. And thanks... well it *is* nice, but only on Windows 7. – Sheridan Feb 13 '14 at 13:36
  • @Sheridan the only difference i can see is the vertical alignment of textbox content :D – Gusdor Feb 13 '14 at 13:52
  • I wish that was the only difference. The main window surround (including the Close Button) definitely *does* have the look of an old Window and is probably the worst part, but Fonts are different sizes, Images are blurred, there's much more to this than just that. – Sheridan Feb 13 '14 at 14:37
2

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

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.

Andras Sebo
  • 1,120
  • 8
  • 19
  • Thanks for your response... I'm not sure that I fully understand what you're saying though. Could you please explain again if possible? – Sheridan Feb 12 '14 at 12:16
  • 1
    If you create a WPF application on Windows 7 you have to include PresentationFramework.dll as reference. This dll includes a few themes, like PresentationFramework.Aero.dll. In case of Windows 8 it is different, it will include PresentationFramework.Aero2.dll. So the appearance will be different. If you insist you can replace this include and use your own, copy them explicitly to the output folder and reference them or you can create custom theme which overrides default behavior / look & feel anyway. – Andras Sebo Feb 12 '14 at 12:32
  • Oh thanks, that's much clearer. I can't try right now, but I will as soon as I can and I'll get back to you. Do you know of any written resource, maybe on MSDN, that mentions this topic? I couldn't find any. – Sheridan Feb 12 '14 at 13:23
  • It's not MSDN, but shows how to solve it. LINK: http://www.kennethham.com/wp/2010/11/force-wpf-to-use-windows-7aero-theming-in-classic-mode/ – Andras Sebo Feb 12 '14 at 14:36
  • Nope... unfortunately, that link made no difference to the appearance of the app on Windows 8. How would copying the dll to the output folder improve the situation? Surely, I have the dll embedded within the application already? – Sheridan Feb 13 '14 at 11:00
  • You have to add this theme to the app.xaml resources: http://stackoverflow.com/questions/2075720/windows-7-theme-for-wpf . After you added you get back your Windows 7 styled controls, however the window's style is not gonna be changed. – Andras Sebo Feb 13 '14 at 12:06
  • No, thanks for your response, but this doesn't appear to work for Windows 8 for some reason... Your linked page also linked to a page which linked to another and I tried *all* of their suggestions, but there has been no change in the look of the controls. – Sheridan Feb 13 '14 at 12:32
  • Should I upload a "hello wpf" demo for you? It has Windows 7 style controls on Windows 8.1. – Andras Sebo Feb 13 '14 at 12:53
  • If you're sure that it works, then yes please... maybe I'm missing something, but it had no effect on my application. If the fix is *really* that simple, that would be great. – Sheridan Feb 13 '14 at 12:58
  • 1
    Here you go: https://drive.google.com/file/d/0B5xvzd9hZ6fzOFBvdGo3QWlDZ3c/edit?usp=sharing – Andras Sebo Feb 13 '14 at 13:05
  • Hi Andras, thanks for that, but if you look at my updated question, you'll see that I don't think that this *is* related to the Windows Themes. I'll try your code just in case, but I'm not expecting success. – Sheridan Feb 13 '14 at 13:26
0

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.

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.

A. Wieser
  • 1
  • 1
  • Thanks, but your link points to a post that had problems on Windows 8 RT which made the `Ribbon` controls disappear... I am not having that problem. Your *you must be aware that sizes, margins and paddings change* comment also does not help, as that is what this question states is the problem. – Sheridan Feb 28 '14 at 10:09
  • I'm afraid you are mistaken, the platform in question is Windows 8 RC (release candidate) not Windows 8 RT. While the user notes, as you stated, that his ribbon is gone, the first answer does infact describe your problem exactly and links to the following page on [MSDN Connect](https://connect.microsoft.com/VisualStudio/feedback/details/747820/net-4-5-wpf-ribbonwindow-broken-in-vs2012#details) which is about the WPF ribbon theme being broken on Windows 8. – A. Wieser Mar 03 '14 at 11:02
  • I asked one of our WPF developers and it seems the issue persists till now when using C# 4.0, however it now seems fixed using C# 4.5. – A. Wieser Mar 03 '14 at 11:09
  • It is not corrected on .NET 4.5. I have some controls presenting alignment differences between Windows 10 and Windows 7. On Windows 10 everything is okay. But I run my software on Windows 7... some controls are unaligned. – quicoli Apr 23 '16 at 14:28