WPF, XAML: How to style a ListBoxItem using binding on property of ListBox ItemsSource object?

Igor Malin picture Igor Malin · Aug 20, 2009 · Viewed 39.4k times · Source

I have a ListBox which is bound to ObservableCollection of LogMessages.

public ObservableCollection<LogMessage> LogMessages { get; set; }
public LogMessageData()
{
    this.LogMessages = new ObservableCollection<LogMessage>();
}

Each Message has two parameters:

public class LogMessage
{
    public string Msg { get; set; }
    public int Severity { get; set; }
    //code cut...
}

ListBox is getting filled with those Items, and I need to color-code (change a background color of ListBoxItem) list depending on a Severity parameter of a LogMessage item.

Here's what I have now in XAML of user control showing the log:

    <UserControl.Resources>
    <AlternationConverter x:Key="BackgroundSeverityConverter">
        <SolidColorBrush>Green</SolidColorBrush>
        <SolidColorBrush>Yellow</SolidColorBrush>
        <SolidColorBrush>Red</SolidColorBrush>
    </AlternationConverter>
    <Style x:Key="BindingAlternation" TargetType="{x:Type ListBoxItem}">
        <Setter Property="Background" 
                Value="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                Path=Severity, 
                Converter={StaticResource BackgroundSeverityConverter}}"/>
    </Style>
    <DataTemplate x:Key="LogDataTemplate">
        <TextBlock x:Name="logItemTextBlock" Width="Auto" Height="Auto" 
        Text="{Binding Msg}"/>
    </DataTemplate>
</UserControl.Resources>

and an actual ListBox:

<ListBox IsSynchronizedWithCurrentItem="True" 
    ItemTemplate="{DynamicResource LogDataTemplate}" 
    ItemsSource="{Binding LogFacility.LogMessages}" 
    x:Name="logListBox" Grid.Row="1" 
    ItemContainerStyle="{StaticResource BindingAlternation}" />

The AlternationConverter is used because the Severity parameter of message is of type Int (0..3), and we can easily switch between styles using that one.

The concept is clear, but so far it does not work for me. The Background color of ListBoxItem did not change.

Answer

Kent Boogaart picture Kent Boogaart · Aug 20, 2009

Use ItemContainerStyle:

<ListBox ItemsSource="{Binding LogMessages}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Background" Value="{Binding Severity, Converter={StaticResource YourBackgroundConverter}}"/>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>