Silv开发者_如何学Cerlight 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?
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.
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 :)
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
精彩评论