I have a situation where I need to style the selected item in a ComboBox differently (make the text bold) when it is one of all except one value. For example, in the drop-down box labelled "What is your favourite primary colour?" I would have four options: No Preference
, Red
, Green
, and Blue
. The ComboBox items are just text with default styling, no images or anything else fancy, and are C# classes, not wrapped in ComboBoxItems.
When the user specifies a preference from the list, I want to highlight that choice by setting the text of the selected item in the collapsed list to be bold. If the user chooses No Preference
, the font weight should remain normal.
I have achieved a 90% solution by setting the FontWeight property on the ComboBox to Bold in a Style with a DataTrigger defined as SelectedItem != No Preference
. However, this styles all items in the ComboBox's list of items, including all those in the drop-down list. I would like those items to always be displayed with a normal font weight.
Is this possible?
Edit
I have been trying @crazyarabian's method of styling the ComboBoxItem with a MultiTrigger. The style definition is:
<Style x:Key="SelectedItemStyle">
<Setter Property="ComboBoxItem.FontWeight" Value="Normal" />
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ComboBoxItem.IsSelected" Value="True" />
<Condition Binding="{Binding IsNoPreferenceSelected,Mode=OneWay}" Value="False" />
</MultiTrigger.Conditions>
<Setter Property="ComboBoxItem.FontWeight" Value="Bold" />
</MultiTrigger>
</Style.Triggers>
</Style>
and it is applied to a ComboBox in the following DataTemplate:
<DataTemplate x:Key="PrimaryColoursTemplate" DataType="{x:Type ViewModels:PrimaryColoursViewModel}">
<ComboBox ItemsSource="{Binding PrimaryColours}" SelectedItem="{Binding SelectedPrimaryColour}"
ItemContainerStyle="{StaticResource SelectedItemStyle}" />
</DataTemplate>
Unfortunately, this kills WPF:
System.Windows.Data Error: 8 : Cannot save value from target back to source. BindingExpression:Path=IsDropDownOpen; DataItem='ComboBox' (Name=''); target element is 'ToggleButton' (Name=''); target property is 'IsChecked' (type 'Nullable`1') InvalidOperationException:'System.InvalidOperationException: Must have non-null value for 'Property'.
The application dies with a NullReferenceException
, which is thrown after the InvalidOperationException above (or perhaps leads to it, I can't decipher the output). The only thing I can think of that might be causing this is resolving the property in the binding in my second MultiTrigger condition, but I don't get any binding errors at all. Here's the top of the stack trace in case that helps too:
InvalidOperationException:'System.InvalidOperationException: Must have non-null value for 'Property'.
at System.Windows.Condition.Seal(ValueLookupType type)
at System.Windows.ConditionCollection.Seal(ValueLookupType type)
at System.Windows.MultiTrigger.Seal()
at System.Windows.TriggerCollection.Seal()
at System.Windows.Style.Seal()
at System.Windows.StyleHelper.UpdateStyleCache(FrameworkElement fe, FrameworkContentElement fce, Style oldStyle, Style newStyle, Style& styleCache)
at System.Windows.FrameworkElement.OnStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
at System.Windows.Controls.ItemsControl.ApplyItemContainerStyle(DependencyObject container, Object item)