views:

1599

answers:

2

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.

A: 

Use ItemContainerStyle:

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

HTH, Kent

Kent Boogaart
Thanks, this worked like a charm for me.
Some One
+1  A: 

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.

Bubblewrap
I've fixed the issue with Kent's solution, but I will try yours as well. It might be useful in some outher situation, of course. The purpose of using the AlternationConverter was that it easily interprets integer data we had in LogMessage. Your aproach is more general, so it will be applicable in more situations. Thanks!
Some One