0
votes

I have a ListView whose ItemsSource is set to a collection property of my ViewModel. There is also a property on the ViewModel, say 'CurrentIndex', that changes as the code runs. As this changes I want ONLY the ListViewItem whose index in the ListView that matches 'CurrentIndex' to change, say its Background to change colour. As 'CurrentIndex' changes I want the previously referenced ListViewItem to be 'reset', i.e. its Background changes to it prior colour. Does anyone know how might I achieve this?

I thought of exploiting the SelectedIndex Property of the ListView but this doesn't work as the user can click on the ListView and change the selection thereby changing the background of the wrong item.

The ListViewItems are Templated via ItemTemplate in XAML.

Hope this makes sense.

Many thanks in advance for any help.

1
If your ItemCount isn't excessive, you could use the AlternationIndex in a converter. An example use of the AlternationIndex can be found hereRachel
@Rachel, thanks for your response. I was hoping for a 'cleaner' approach that didn't have pitfalls with it.Cleve
Perhaps change CurrentIndex to CurrentItem which returns ItemCollection[CurrentIndex], and use an IMultiValueConverter to see if CurrentItem == Value? Should be easy enough to pass both values to a Converter. I could probably find some kind of example if you needed it.Rachel
@Rachel, could I take you up on your offer of some example code please? Not sure how I'd use the IMultiValueConverter. Thanks.Cleve
Just saw your comment now, looks like Ed's already posted a sample MultiValueConverter. Only difference between his suggestion and mine is you'd pass in the CurrentItem (<Binding Path="DataContext.CurrentItem" RelativeSource="{RelativeSource AncestorType=ListBox}" />) and the current data object (<Binding Path="." /> I think... could have syntax wrong), and your converter would just check if the two objects are equal.Rachel

1 Answers

1
votes

Second solution:

If you have a array of Item that is bound to the ListView itemsSource, and each Item has INotifyPropertyChanged implemented, when you could do this:

<ListView ItemsSource="{Binding MyItemsList}">
        <ListView.ItemTemplate>
            <ItemContainerTemplate>
                <Grid>
                    <Grid.Style>
                        <Style TargetType="Grid">
                            <Setter Property="Background" Value="Transparent"/>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding ShouldChangeBackground}" Value="true">
                                    <Setter Property="Background" Value="Red"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Grid.Style>

                </Grid>
            </ItemContainerTemplate>
        </ListView.ItemTemplate>
    </ListView>

ShouldChangeBackground is a Boolean inside Item. And you set this Boolean to true, when you want it to changed background color, and then set it to False, when it should be back to normal.

Another solution could be to use a Converter:

    class TrueToBackgroundConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is Boolean && (Boolean)value)
            return Brushes.Red;

        return Brushes.Transparent;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

and in your code:

 <ListView ItemsSource="{Binding Element, FallbackValue=123123213213123213213}">
        <ListView.ItemTemplate>
            <ItemContainerTemplate>
                <Grid Background="{Binding ShouldChangeBackground, Converter={StaticResource TrueToBackgroundConverter}}">
                </Grid>
            </ItemContainerTemplate>
        </ListView.ItemTemplate>
    </ListView>