3

Silverlight does not support Alternating Item Templates in an ItemsControl. I have a few ideas in mind as to how to accomplish this, but to avoid polluting the potential answers, I'll leave them out.

The idea is the same as a normal ItemTemplate in that it won't depend on anything in the bound data context to function. I would like the functionality to remain in the View (assuming MVVM)

If you had to design a method of providing alternating templates (and I mean a full data template) for an ItemsControl, how would you accomplish this?

Ray Booysen
  • 28,894
  • 13
  • 84
  • 111

3 Answers3

3

Extend ItemsControl and in the PrepareContainerForItemOverride override you can apply alternating templates.

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        if (!object.ReferenceEquals(element, item))
        {
            ContentPresenter presenter = element as ContentPresenter;
            ContentControl control = null;
            if (presenter == null)
            {
                control = element as ContentControl;
                if (control == null)
                {
                    return;
                }
            }
            DataTemplate itemTemplate = null;
            if ((this.ItemTemplate != null) && (this.DisplayMemberPath != null))
            {
                throw new InvalidOperationException("Cannot set ItemTemplate and DisplayMemberPath simultaneously");
            }
            if (!(item is UIElement))
            {
                if (this.ItemTemplate != null)
                {
                    if(this.AlternateItemTemplate != null && ((alternationIndex % 2)) == 1)
                        itemTemplate = this.AlternateItemTemplate;
                    else
                    itemTemplate = this.ItemTemplate;
                    alternationIndex++;
                }
            }
            if (presenter != null)
            {
                if (itemTemplate != null)
                {
                    presenter.Content = item;
                    presenter.ContentTemplate = itemTemplate;
                }
                else
                {
                    presenter.SetBinding(ContentControl.ContentProperty, new Binding(this.DisplayMemberPath));
                }
            }
            else
            {
                control.Content = item;
                control.ContentTemplate = itemTemplate;
            }
        }
    }

The way I'm using alternationIndex is not very accurate and would need to be changed, but otherwise this should work.

Stephan
  • 5,430
  • 2
  • 23
  • 31
3

I got stuck on the same problem recently. I eventually decided that attached properties are the way to go, and ended up with functionality that works somewhat like this:

<Grid x:Name="LayoutRoot" Background="White">
    <ListBox x:Name="ListItems">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Border>
                    <Border.Style>
                        <Style TargetType="Border">
                            <Setter Property="Background" Value="White" />
                        </Style>
                    </Border.Style>
                    <local:ItemsControlAlternation.AlternateStyle>
                        <Style TargetType="Border">
                            <Setter Property="Background" Value="LightBlue" />
                        </Style>
                    </local:ItemsControlAlternation.AlternateStyle>
                    <ContentPresenter Content="{Binding}" />
                </Border>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

I posted about it here: http://www.philsversion.com/2010/11/22/alternating-row-styles-in-silverlight/

Phil

P.s. Sorry for the blatant self promotion :)

Phil Cox
  • 103
  • 5
1

I would put a Bool property in the Item ViewModel class and write DataTrigger on the ItemTemplate to give a different look. In the collection we can loop through and set that bool appropriately

Jobi Joy
  • 49,102
  • 20
  • 108
  • 119
  • Hi Jobi Thanks for this, I updated the question to be clearer. I don't want this solution to depend on the VM to function. – Ray Booysen Jun 07 '10 at 16:44
  • 2
    The ViewModel should never determine how the data is presented – Rick Kierner Oct 07 '10 at 18:57
  • 1
    Thats a bit of a misnomer as the whole point of a VM is to determine how the data is presented. Booleans representing Visiblity, enums representing states, it occurs all the time. – Ray Booysen Dec 02 '10 at 09:51