Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 984
Igor Malin Avatar asked Aug 20 '09 10:08

Igor Malin


2 Answers

Use ItemContainerStyle:

<ListBox ItemsSource="{Binding LogMessages}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Background" Value="{Binding Severity, Converter={StaticResource YourBackgroundConverter}}"/>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>
like image 51
Kent Boogaart Avatar answered Oct 18 '22 17:10

Kent Boogaart


Like Bojan commented, it's the RelativeSource which shouldnt be there. Use {Binding Path=Severity, Converter={StaticResource BackgroundSeverityConverter}} when you're binding to your data object. RelativeSource.TemplatedParent is for binding to ListBoxItem.

Additionally, something of a pet peeve of mine, you could consider using triggers, for example:

<Style x:Key="BindingAlternation" TargetType="{x:Type ListBoxItem}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Severity}" Value="1">
            <Setter Property="Background" Value="Green"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding Severity}" Value="2">
            <Setter Property="Background" Value="Yellow"/>
        </DataTrigger>
        <!-- etc.. -->
    </Style.Triggers>
<Style x:Key="BindingAlternation" TargetType="{x:Type ListBoxItem}">

But that's just a personal preference....what you have there should work fine if you fix the binding.

like image 20
Bubblewrap Avatar answered Oct 18 '22 19:10

Bubblewrap