0

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.

Cleve
  • 1,273
  • 1
  • 13
  • 26
  • If your ItemCount isn't excessive, you could use the `AlternationIndex` in a converter. An example use of the AlternationIndex can be found [here](http://stackoverflow.com/a/6512032/302677) – Rachel Nov 03 '16 at 13:27
  • @Rachel, thanks for your response. I was hoping for a 'cleaner' approach that didn't have pitfalls with it. – Cleve Nov 03 '16 at 13:44
  • 1
    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 Nov 03 '16 at 14:05
  • @Rachel, could I take you up on your offer of some example code please? Not sure how I'd use the `IMultiValueConverter`. Thanks. – Cleve Nov 03 '16 at 14:33
  • 1
    Just saw your comment now, looks like [Ed's already posted a sample MultiValueConverter](http://stackoverflow.com/a/40405997/302677). Only difference between his suggestion and mine is you'd pass in the CurrentItem (``) and the current data object (`` I think... could have syntax wrong), and your converter would just check if the two objects are equal. – Rachel Nov 03 '16 at 20:37
  • @Rachel, appreciate your response. Thank you. – Cleve Nov 03 '16 at 20:59

1 Answers1

1

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>
Lupu Silviu
  • 1,145
  • 11
  • 23
  • Hi Lupu Silviu, in my original post I said I'd tried to use the SelectedIndex property of the ListView. The problem with that, and presumably also the SelectedItem (or SelectedValue) is that the user could click on the Listivew which would then change these properties from the intended CurrentIndex value. Please post code if you feel I've misinterpreted your answer. Thanks – Cleve Nov 03 '16 at 13:57
  • So you actually want to change the color of the background, for a specific element, that is being processed in the ViewModel, right? It is not neccesarelly associated with the Selected element in the View. – Lupu Silviu Nov 03 '16 at 13:58
  • Basically my model does some processing of a list of items. The item that it is currently on is given by CurrentIndex in the viewmodel. The view show all the items via a listView. I want the item in the view that is being processed to have its background changed to be different from the rest. – Cleve Nov 03 '16 at 14:03
  • @Cleve I added a new solution above. You can use either, Style of Converter implementation, but the flag ShouldChangeBackground has to be updated from the ViewModel. – Lupu Silviu Nov 03 '16 at 14:10
  • Hi Lupu Silviu, thank you for your ideas and code. I'm trying both yours and @Rachel ideas. – Cleve Nov 03 '16 at 15:50