Metro app - ListView - how to alternate background colour of ListViewItems
Asked Answered
L

4

8

In my Metro style app for Windows 8, I'm binding a Listview to an ObservableCollection and I would like the background color of each ListViewItem to alternate (white, gray, white, etc)

   <ListView x:Name="stopsListView" ItemsSource="{Binding}" >
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid Height="66" >
                    <TextBlock Text="{Binding Title}" />
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>

In WPF, this is done using a Style with Triggers - see this page.

How do you accomplish this in a Metro app?

Update:

After the correct answer was given below, I went away and actually coded it. Here's some code for anyone who needs it:

Code for value converter class:

public class AltBackgroundConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (!(value is int)) return null;
        int index = (int)value;

        if (index % 2 == 0)
            return Colors.White;
        else
            return Colors.LightGray;
    }

    // No need to implement converting back on a one-way binding
    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

Code for XAML listview:

    <ListView x:Name="stopsListView" ItemsSource="{Binding}">

        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid Width="250" Height="66" Margin="5">
                    <Grid.Background>
                        <SolidColorBrush Color="{Binding IndexWithinParentCollection, Mode=OneWay, Converter={StaticResource AltBGConverter}}" />
                    </Grid.Background>

...and, when adding items to the collection, or modifying the collection, remember to set their Index within the collection:

myCollection.add(item);
item.IndexWithinParentCollection = myCollection.Count;

Of course, if your collection changes often this approach will be costly to maintain, since you'll have to re-index your items, so I found it easier to store a reference to the parent collection within each item, then calculate the Index on-the-fly using .IndexOf() to avoid having to constantly update the index values every time the collection changes.

Lowerclassman answered 17/8, 2012 at 17:7 Comment(0)
M
5

You can use a converter - grab a row index from an item and convert it to a brush. Also - if ItemTemplate does not give you enough control - use ItemContainerStyle to modify the brush at the ListViewItem template level.

Another option might be to specify an ItemTemplateSelector that gives you a different template with a different brush depending on an item. You would still need to generate row indices though or somehow enable the selector to determine if the item is at an even or odd position.

Magnetograph answered 17/8, 2012 at 17:18 Comment(4)
I wondered about that myself, but how would you pass the row index into the converter? Is there some XAML syntax to do that, or would I have to explicitly tell each object what its index in the collection is?Lowerclassman
You would need to add a property to the object, yes. Then do something like Background="{Binding ItemIndex, Converter={StaticResource ItemIndexToBackgroundConverter}}"Magnetograph
This is the correct answer, thanks. It's a real shame that there's no XAML syntax to pass the item index into the converter. Perhaps I could set up the items to reference their own parent collection and just use .indexOf - this approach feels like it probably breaks all sorts of rules though.Lowerclassman
There are no rules here - you should use what works for you. :) You could create some sort of a view over your data if you don't want to change the model. Or create an attached behavior to the list that does what you want automagically.Magnetograph
R
3

I believe the code sample here is useful https://msdn.microsoft.com/en-us/library/ms750769(v=vs.85).aspx

Roughcast answered 30/3, 2015 at 16:10 Comment(0)
A
1

Never tried to do styling like this but what if:

you bind a background color to some property and that property will be set via IValueConverter according to maybe index of current item in listview.

If I make any sense.

Edit:

Funny thing, while i was writing my answer, Filip Skakun came with exactly same idea.

Aridatha answered 17/8, 2012 at 17:21 Comment(2)
Well i was typing my thoughts, too slowly coz of stress (what if i was wrong), then i noticed that popup with 'someone has already answered while you're playing slowpoke' :)Aridatha
Funny thing that StackOverflow is. :)Magnetograph
S
0

I search online and found a technique that included adding an index property to the model in question and then adding a converter to the DataTemplate. This wasn’t ideal because it only changed the contents of the list item, so depending on padding and content alignment you’d see gaps around the row background. I also didn’t like the code smell of modifying my data model objects with UI code.

Try this it will help, http://www.bendewey.com/index.php/523/alternating-row-color-in-windows-store-listview

Splasher answered 8/6, 2015 at 13:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.