WPF ListBox stands out in Windows 10

I am new to WPF, but to .NET (Winforms). I am trying to manipulate the list highlighting style to control the focused and unfocused color of the selected item. Every single tutorial on this subject that I found uses its own style to assign a new value to SystemColors.HighlightBrushKey and SystemColors.ControlBrushKey. But it does not work. After countless hours trying to get this to work, it occurred to me that this might be due to the OS. I tried this on Windows 10. I ran the same code in the Windows 7 setup, and now it works!

Thus, apparently, the old method does not work on Windows 10 (at least as it seems to me). Has anyone found an alternative? In the end, I just want the list to support bright highlighting, even if it has no focus. The default gray icon is hard to see and does not seem appropriate in some use cases. I have a scenario in the real world where it is very unnatural that the main point disappears when the focus is removed from the list.

Below is the XAML code that I used on Windows 7 but not on Windows 10. (By the way, I also tried replacing SystemColors.ControlBrushKey with SystemColors.InactiveSelectionHighlightBrushKey - the results were the same).

<Window x:Class="TestApp.TestWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:TestApp" mc:Ignorable="d" Title="TestWindow" Height="300" Width="300" Loaded="Window_Loaded"> <Window.Resources> <Style x:Key="myListboxStyle"> <Style.Resources> <!-- Background of selected item when focused --> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red" /> <!-- Background of selected item when not focused --> <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Green" /> </Style.Resources> </Style> </Window.Resources> <Grid> <ListBox x:Name="listBox" Style="{StaticResource myListboxStyle}" HorizontalAlignment="Left" Height="100" Margin="22,18,0,0" VerticalAlignment="Top" Width="237"> <ListBoxItem>Test 1</ListBoxItem> <ListBoxItem>Test 2</ListBoxItem> <ListBoxItem>Test 3</ListBoxItem> </ListBox> <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="50,165,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/> </Grid> </Window> 
+5
source share
4 answers

If you really want to change the default settings for your application, you can always change the style by creating a copy of the template. In this case, the ListBoxItem style.

In the designer, click ListBoxItem, right-click Edit Template and Edit Copy.

Below is what I got on my machine, and a screenshot of an application working with Red / Green that demonstrates the style applied to the affected elements. Of course you would apply this to all points ...

 <Window.Resources> <Style x:Key="FocusVisual"> <Setter Property="Control.Template"> <Setter.Value> <ControlTemplate> <Rectangle Margin="2" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/> </ControlTemplate> </Setter.Value> </Setter> </Style> <SolidColorBrush x:Key="Item.MouseOver.Background" Color="#1F26A0DA"/> <SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da"/> <SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="#3DDADADA"/> <SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="#FFDADADA"/> <SolidColorBrush x:Key="Item.SelectedActive.Background" Color="#3D26A0DA"/> <SolidColorBrush x:Key="Item.SelectedActive.Border" Color="#FF26A0DA"/> <Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}"> <Setter Property="SnapsToDevicePixels" Value="True"/> <Setter Property="Padding" Value="4,1"/> <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="Transparent"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Border> <ControlTemplate.Triggers> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsMouseOver" Value="True"/> </MultiTrigger.Conditions> <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/> <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="Selector.IsSelectionActive" Value="False"/> <Condition Property="IsSelected" Value="True"/> </MultiTrigger.Conditions> <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/> <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="Selector.IsSelectionActive" Value="True"/> <Condition Property="IsSelected" Value="True"/> </MultiTrigger.Conditions> <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/> <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/> </MultiTrigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style x:Key="ListBoxItemStyle2" TargetType="{x:Type ListBoxItem}"> <Setter Property="SnapsToDevicePixels" Value="True"/> <Setter Property="Padding" Value="4,1"/> <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/> <Setter Property="Background" Value="Transparent"/> <Setter Property="BorderBrush" Value="Transparent"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Border> <ControlTemplate.Triggers> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsMouseOver" Value="True"/> </MultiTrigger.Conditions> <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/> <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="Selector.IsSelectionActive" Value="False"/> <Condition Property="IsSelected" Value="True"/> </MultiTrigger.Conditions> <Setter Property="Background" TargetName="Bd" Value="Red"/> <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="Selector.IsSelectionActive" Value="True"/> <Condition Property="IsSelected" Value="True"/> </MultiTrigger.Conditions> <Setter Property="Background" TargetName="Bd" Value="Green"/> <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/> </MultiTrigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </Window.Resources> <Grid x:Name="LayoutRoot" Opacity="{Binding MainWindowOpacity}"> <StackPanel> <TextBlock Text="WPF" FontSize="36" Margin="20" Foreground="Orange" HorizontalAlignment="Center"/> <ListBox x:Name="listBox" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="237"> <ListBoxItem Style="{DynamicResource ListBoxItemStyle1}">Test 1</ListBoxItem> <ListBoxItem Style="{DynamicResource ListBoxItemStyle2}">Test 2</ListBoxItem> <ListBoxItem>Test 3</ListBoxItem> </ListBox> </StackPanel> </Grid> 

And the application in action:

ACTIVE:

Active

ACTIVELY:

Not active

Caution emptor.

+5
source

Microsoft broke it for Windows 10, but we can fix it!

Here's what the template looks like in windows 10 (only the parts that I care about):

  <ControlTemplate TargetType="{x:Type ListBoxItem}"> ... <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True"> <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Border> <ControlTemplate.Triggers> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsMouseOver" Value="True"/> </MultiTrigger.Conditions> <Setter Property="Background" TargetName="Bd" Value="#1F26A0DA"/> <Setter Property="BorderBrush" TargetName="Bd" Value="#A826A0DA"/> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="Selector.IsSelectionActive" Value="False"/> <Condition Property="IsSelected" Value="True"/> </MultiTrigger.Conditions> <Setter Property="Background" TargetName="Bd" Value="#3DDADADA"/> <Setter Property="BorderBrush" TargetName="Bd" Value="#FFDADADA"/> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="Selector.IsSelectionActive" Value="True"/> <Condition Property="IsSelected" Value="True"/> </MultiTrigger.Conditions> <Setter Property="Background" TargetName="Bd" Value="#3D26A0DA"/> <Setter Property="BorderBrush" TargetName="Bd" Value="#FF26A0DA"/> </MultiTrigger> <Trigger Property="IsEnabled" Value="False"> <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> 

Note that they have hardcoded values ​​for colors, for example, "# 1F26A0DA".

On Windows 7, a built-in template for ListBoxItems:

  <ControlTemplate TargetType="{x:Type ListBoxItem}"> ... <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsSelected" Value="true"> <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelected" Value="true"/> <Condition Property="Selector.IsSelectionActive" Value="false"/> </MultiTrigger.Conditions> <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/> </MultiTrigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> 

So, basically Microsoft used resources such as "SystemColors.InactiveSelectionHighlightBrushKey" on Windows 7. But now they have done it, so we cannot do this without redefining the template; as they are hardcoded in all values.

So, to fix this, simply override the template for ListBoxItem in your App.Xaml file; so everyone gets the patch.

  <Style TargetType="{x:Type ListBoxItem}"> <Style.Resources> <!-- Use your own colors here if you want, or do it per class --> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#FFFFA500"/> <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey }" Color="#FFFFA500"/> </Style.Resources> <Setter Property="Template"> <!-- Revert the Template in Windows 10 to match the Windows 7 template that used "SystemColors.HighlightBrushKey" and such--> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"> <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsSelected" Value="true"> <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelected" Value="true"/> <Condition Property="Selector.IsSelectionActive" Value="false"/> </MultiTrigger.Conditions> <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/> </MultiTrigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> 
+3
source

I had a similar problem with ListBoxes highlighting style under Windows 10 ... again the old SystemColors.HighlightBrushKey and SystemColors.ControlBrushKey solution worked only for me under Windows 7. In my case, I just wanted to remove any WPF -drawn highlighting at all, so I could would replace it with yours.

To do this, I simply replaced the ControlTemplate with the following brief style in my resources:

  <Style 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> </Style> 

I generally don't like replacing verbose ControlTemplates, but for me it was a great solution, hoping this could help someone else.

0
source

I’m afraid that I don’t have the opportunity to verify this in Windows 10 specifically, but I had a similar problem only in Windows 7. The definition of “ControlBrushKey” in resources simply did not work.

Setting "InactiveSelectionHighlightBrushKey" worked for me:

 <ListBox.Resources> <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="DodgerBlue" /> </ListBox.Resources> 

Dodger blue - a very close match to the default Aero selection; it's just the hair is darker. I am still working on how to match it with the actual value of the selection, and not with a specific color.

0
source

Source: https://habr.com/ru/post/1244460/


All Articles