14

I have an application that's been running happily on windows 7 and below targeting the .net 4 framework.
If the application is now installed in windows 8 (Running .net 4.5 but still targeting .net 4) it shows a blue background for a selected item in a listbox or combobox and a white background for a focused item. Is there anyway to remove this?
I'm using the following in my XAML to set the style in question which seemed to resolve the issue before 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>
H.B.
  • 166,899
  • 29
  • 327
  • 400
Oli
  • 2,996
  • 3
  • 28
  • 50
  • 1
    Did you ever find an answer for this? – Anders Rune Jensen Aug 27 '12 at 22:28
  • 1
    I did not test this with windows 8, so the aero2 might be the problem, but on windows 7, I had to use InactiveSelectionHighlightBrushKey instead of ControlBrushKey from .NET 4.5. – Mike Fuchs May 21 '13 at 15:46
  • Just wanted to say that many of the colors in Aero2 templates are hard-coded. Sadly. This includes things like the ComboBoxItem and MenuItem. It will be obvious if you use Blend or VS to Edit Copy the template. – tofutim Aug 20 '15 at 04:20

6 Answers6

10

I forgot to come back with how I solved this.... Turns out that all you need to do it create a blank Item Container Style and assign it to your listbox/combobox etc.... You can use this as well as keeping the current style you may be using such as ListBox Style="{StaticResource CurrentStyle}" ItemContainerStyle="{StaticResource BlankListBoxContainerStyle}" /> Where BlankListBoxContainerStyle would be something like.....

<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>
Oli
  • 2,996
  • 3
  • 28
  • 50
6

Your application overrides the value of SystemColors.HighlightBrushKey (and other system keys). This works for controls that define their foreground/background colors by referring to system colors, as they do in the Win7 default theme (Aero).
But Win8 default theme (Aero2) defines colors differently. So your override has no effect.

Themes are not required to use system colors. They happened to do so in Win7/Aero, but only because the system colors were deemed adequate.

Hope this helps.

Anand
  • 1,440
  • 8
  • 11
  • 2
    Thanks that makes sense. Do you know how I'd stop Aero2 from colouring in my application? – Oli Aug 22 '12 at 23:05
  • Strangely the Aero2 controls do not reference the SystemColors but have the colors hard coded in. A way to do it, as annoying as it is, is to override the template. – tofutim Aug 12 '15 at 15:57
4

Rereading the documentation for frameworkcompatibility I found that it shouldn't actually be needed when compiling for .NET 4 and running on Windows 8.

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

But I was still having the blue background that wasn't there in Windows 7 and I finally tracked the problem down to a list view which was not styled the same way as my list boxes. I found that I didn't actually need the ability to select elements for the elements, so changing the list view to a itemscontrol solved the problem for me.

See also:

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

Anders Rune Jensen
  • 3,758
  • 2
  • 42
  • 53
  • Good find, sadly that property is only available in .net 4.5 and I'm targeting 4.0. I'll keep an eye on that post and see if a workaround other than forcing all clients to 4.5 appears. – Oli Aug 29 '12 at 10:28
  • I revised the post as I finally found a solution that works perfectly in .NET 4 as well. Hopefully it helps you solve your problem as well. – Anders Rune Jensen Sep 05 '12 at 07:08
0

It's called a default theme which is system dependent, you are not really meant to mess with it. You can overwrite it whole by setting another Control.Template.

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • @Oli: Scratch what i said, a whole theme is hardly ever a good idea, it may be irritating to some users. Anyway, you can change the apperance by setting the template, the control then will look the same on every system (unless you set it dependent on the system). – H.B. Aug 17 '12 at 14:48
  • I have a Listbox.ItemsPanel,Listbox.Template,Listbox.ItemTemplate and Listbox.itemcontainerstyle already defined.It worked and had identical visual style on every version of windows I've tested it on but not windows 8. Anything I've missed? – Oli Aug 17 '12 at 14:55
  • Templates are often made up of templated components themselves. Maybe one the controls used inside the Template now has a different template. – H.B. Aug 17 '12 at 15:00
  • I presume that is true or at the very least the colour brushes used have changed. I just can't find out what and where? Remember .net 4.5 changes all the .net 4 assemblies so anything could have changed. – Oli Aug 17 '12 at 15:20
  • How about listing all `SystemColors.*Brush` for both versions and comparing them? – H.B. Aug 17 '12 at 15:24
0
<Style.Triggers>
                <Trigger Property="IsSelected" Value="true">
                    <Setter Property="Effect">
                        <Setter.Value>
                            <DropShadowEffect Color="Red"
                              BlurRadius="0"
                              ShadowDepth="0" />
                        </Setter.Value>
                    </Setter>
                </Trigger>
Andreas
  • 3,843
  • 3
  • 40
  • 53
0

Here's what I came up with that doesn't involve changing system colors or control templates. Simply wrap the ListBox in a new 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>

Then simply use the wrapper UserControl as if it were a ListBox. Any other ListBox properties you want to control can simply be added to the wrapper in the same manner as ItemsSource and SelectedItem from my example.

bugged87
  • 3,026
  • 2
  • 26
  • 42
  • this change the color of the border inside datatemplate, not the entire line (unlike the listbox selection does)...even setting `````` doesn't help... – Giacomo Pirinoli Mar 19 '20 at 09:24