Search code examples
wpfbindingcolorsbackgroundpropertychanged

wpf update ListViewItem background property


I have a listview that is binded to a ThreadSafeObservableCollection. The background of each of these items is set to an enum that is run through a color converter, here's the code for these 2 settings.

<UserControl.Resources>
    <EncoderView:EncoderStatusToColorConverter x:Key="ColorConverter"/>
    <Style x:Key="ItemContStyle" TargetType="{x:Type ListViewItem}">
        <Setter Property="Background" Value="{Binding Converter={StaticResource ColorConverter}}" />
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
    </Style>
</UserControl.Resources>

what I want to have happen is that the background color of the listviewItem will change from Red - Yellow - Green based on an enum value. Which is updated based on business logic rules. This is currently working, but only for the initial display of the item. When I make a change to the "Status" property of the object that the listItemView is bound to, the background does not update. If I remove the object from the collection, change the status, and then add it to the collection again, the background IS updated.
I've tried making the object IPropertyNotify, and throwing the event on the status property changed setter, but that didn't work.

does anyone know if there is something special I have to do in order to get the background of a listview item to update. I'm also open for other ideas on how to solve this problem, thanks. here's the XAML for the ListView. EncoderService.Encoders is my ThreadSafeObservableCollection of Encoder objects.

        <ListView  AutomationProperties.AutomationId="FinishScreen"  
                   ItemsSource="{Binding Path=EncoderService.Encoders}" 
                   x:Name="DataListView" Grid.RowSpan="1" Grid.Row="1" Margin="5"
                   ItemContainerStyle="{StaticResource ItemContStyle}"
                   Background="Azure">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="MAC">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <ContentControl Content="{Binding Path=MAC}" ToolTip="{Binding Path=MAC}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="IDF">...

Solution

  • The issue is that the Binding to Background is taking the entire Encoder object, which doesn't change unless you remove and add it. Even if Encoder implements INotifyPropertyChanged, the Binding is still looking at the whole Encoder object and has no way of knowing which properties of Encoder are relevant to your EncoderStatusToColorConverter, so it won't update itself.

    The solution in your case is to narrow the scope of the Binding on Background to just the property (or properties) relevant to EncoderStatusToColorConverter. Any properties in the Path of your Binding will be watched for updates. So, for example, if you only need Status:

    <Style x:Key="ItemContStyle" TargetType="{x:Type ListViewItem}">
        <Setter Property="Background" Value="{Binding Path=Status, Converter={StaticResource ColorConverter}}" />
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
    </Style>
    

    In this case, if you implement INotifyPropertyChanged on Encoder and notify whenever Status changes, the Binding should update for you. This also means you'll need to update your EncoderStatusToColorConverter so it only takes a Status type.