My WPF window has its foreground brush set to a brush from a resource dictionary, and I want all text in the window to have this color, so I don't touch the foreground brush in anything else.
Textboxes get the color
Textblocks get the color
Buttons get the color
Listboxes do not get the color, and so neither do their contents.
Is there any way to get a Listbox to behave like the other controls in this respect?
Assuming not, and that this is by design, what is the rationale?
Edit:
It seems my question is not clear enough.
I understand how to create styles and resources and apply them to ListBox
es; I'm wondering why I need to do this for certain controls when I do not need to for others -- why some inherit properties and others do not -- and whether there is any way to make them all inherit in the same way.
The reason the ListBox and some other controls are not inheriting the Foreground property is that it is explicitly overridden with a Setter in the default style. Unfortunately even if you assign a custom style to the ListBox that doesn't include the Foreground property setter, it will still fall back to using the default style before attempting to inherit the value of its parent.
The order of precedence for determining the property value is:
- Local value
- Style triggers
- Template triggers
- Style setters
- Theme style triggers
- Theme style setters
- Property value inheritance
- Default value
Since #6 is defined in the default style for the control, WPF does not attempt to determine the value of #7.
here is the style for listbox items:
<Style x:Key="{x:Type ListBoxItem}" TargetType="ListBoxItem">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border
Name="Border"
Padding="2"
SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="Background"
Value="{StaticResource SelectedBackgroundBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground"
Value="{StaticResource DisabledForegroundBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
now, what your going to want to do is modify this so that the static resource "DisabledForegroundBrush" points to your resource brush instead. Add this to your Window.Resource tag and you should be good to go.
You could do something like this:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="root">
<ListBox>
<ListBox.Resources>
<Style TargetType="{x:Type ListBox}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Yellow"/>
<SolidColorBrush x:Key="{x:Static SystemColors.WindowTextBrushKey}" Color="Red"/>
</Style.Resources>
</Style>
</ListBox.Resources>
<ListBoxItem>Item 1</ListBoxItem>
<ListBoxItem>Item 2</ListBoxItem>
</ListBox>
</Page>
Instead of Color="Red"
, you could use a Binding expression to bind to the color resource defined for your application.