Alexandre Huot
Alexandre Huot

Reputation: 517

Change selection color of ListBox Item

I have a normal ListBox and I want to change the selection color to Red. Here's what I've got so far.

<Style x:Key="myLBStyle" TargetType="{x:Type ListBoxItem}">
    <Style.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" 
                         Color="red" />
        <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
                         Color="red" />
    </Style.Resources>
</Style>

It's working. The SelectedItem is Red and stay Red even if it's out of focus.

Here's my real problem: In my grid I also have a CheckBox and I want the above style to apply only if the CheckBox is checked.

So if the CheckBox is checked i want the selection color to be Red and to be Blue (or default color) if the CheckBox is unchecked.

I went through the web and i can't find anything, so i'm looking for help.

Upvotes: 0

Views: 507

Answers (2)

Rohit Vats
Rohit Vats

Reputation: 81253

You can have two separate styles -

  1. Default style with all your setter and triggers.

  2. Blank style with resources defined in it and make this style to be BasedOn default style so that all setters and triggers gets inherited from default style.

And then you can swap ItemContainerStyle based on checkBox checked state.


Sample :

<StackPanel>
    <StackPanel.Resources>
        <Style x:Key="myLBStyleDefault">
          <!-- All setters and triggers go here -->
        </Style>
        <Style x:Key="myLBStyleWithRed"
               BasedOn="{StaticResource myLBBaseStyle}"
               TargetType="{x:Type ListBoxItem}">
            <Style.Resources>
                <SolidColorBrush
                    x:Key="{x:Static SystemColors.HighlightBrushKey}" 
                    Color="Red" />
                <SolidColorBrush
                    x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
                    Color="Red" />
            </Style.Resources>
        </Style>
    </StackPanel.Resources>
    <CheckBox x:Name="chk"/>
    <ListBox>
        <ListBox.Style>
            <Style TargetType="ListBox">
                <Setter Property="ItemContainerStyle"
                        Value="{StaticResource myLBStyleDefault}"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsChecked, ElementName=chk}" 
                                 Value="True">
                        <Setter Property="ItemContainerStyle"
                                Value="{StaticResource myLBStyleWithRed}"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ListBox.Style>
    </ListBox>
</StackPanel>

Upvotes: 1

Sheridan
Sheridan

Reputation: 69959

You'll need to do that in code by handling the CheckBox.Checked and CheckBox.Unchecked events as I don't believe that you can add or remove Resources using a Trigger in XAML. However, the properties of the SystemColors class are read only, so you can't set them directly either.

There is one way that I found, but that involves importing the kkk method from the user32.dll, so it might not be for the feint hearted. For more information, please see the SetSysColors (user32) page on the pinvoke.net website. From the linked page:

[DllImport("user32.dll", SetLastError=true)]
 public static extern bool SetSysColors(int cElements, int [] lpaElements, int [] lpaRgbValues);
 public const int COLOR_DESKTOP = 1;

 //example color
 System.Drawing.Color sampleColor = System.Drawing.Color.Lime;

 //array of elements to change
 int[] elements = {COLOR_DESKTOP};

 //array of corresponding colors
 int[] colors = {System.Drawing.ColorTranslator.ToWin32(sampleColor)};

 //set the desktop color using p/invoke
 SetSysColors(elements.Length, elements, colors);

 //save value in registry so that it will persist
 Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Control Panel\\Colors", true);
 key.SetValue(@"Background", string.Format("{0} {1} {2}", sampleColor.R, sampleColor.G, sampleColor.B));

Upvotes: 0

Related Questions