ListView中第一个和最后一个项目的不同项目模板

时间:2011-10-20 11:04:41

标签: wpf listview datatemplate

我需要以不同方式设置列表视图的第一个和最后一个项目的样式。为实现这一目标,我开始根据答案开发解决方案:Use different template for last item in a WPF itemscontrol

基本上,我有一个自定义的ItemsTemplateSelector,它根据列表视图项中的项索引决定要应用的模板(下面的代码)。

它正常工作,除了当列表更新(添加或删除项目)时,模板不会再次被选中(例如,最初,SingleItemTemplate被选中,因为有一个项目。当我添加一个项目到列表,第一项的模板没有切换到FirstItemTemplate)。如何强制所有项目的模板选择?

public class FirstLastTemplateSelector : DataTemplateSelector 
{
    public DataTemplate DefaultTemplate { get; set; }
    public DataTemplate FirstItemTemplate { get; set; }
    public DataTemplate LastItemTemplate { get; set; }
    public DataTemplate SingleItemTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        ListView lv = VisualTreeHelperEx.FindParentOfType<ListView>(container);
        if (lv != null)
        {
            if (lv.Items.Count == 1)
            {
                return SingleItemTemplate;
            }

            int i = lv.Items.IndexOf(item);
            if (i == 0)
            {
                return FirstItemTemplate;
            }
            else if (i == lv.Items.Count - 1)
            {
                return LastItemTemplate;
            }
        }
        return DefaultTemplate;
    }
}

1 个答案:

答案 0 :(得分:15)

作为替代方法,我建议将AlternationCount的{​​{1}}绑定到集合中的项目数(例如ItemsControl属性)。然后,这将为Count中的每个容器分配一个唯一的ItemsControl(0,1,2,... Count-1)。有关更多信息,请参见此处:

http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.alternationcount.aspx

每个容器都有一个唯一的AlternationIndex后,您可以在容器AlternationIndex中使用DataTrigger来设置基于索引的Style。这可以使用带有转换器的ItemTemplate来完成,如果索引等于计数,则返回MultiBinding,否则为True。当然,你也可以围绕这种方法构建一个选择器。除转换器外,这种方法很好,因为它只是一个XAML解决方案。

使用False的示例:

ListBox

转换器可能类似于:

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Collections="clr-namespace:System.Collections;assembly=mscorlib"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        xmlns:l="clr-namespace:WpfApplication4"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.Resources>
            <Collections:ArrayList x:Key="MyCollection">
                <System:String>Item One</System:String>
                <System:String>Item Two</System:String>
                <System:String>Item Three</System:String>
            </Collections:ArrayList>

            <l:MyAlternationEqualityConverter x:Key="MyAlternationEqualityConverter" />

            <Style x:Key="MyListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
                <Style.Triggers>
                    <DataTrigger Value="True">
                        <DataTrigger.Binding>
                            <MultiBinding Converter="{StaticResource MyAlternationEqualityConverter}">
                                <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListBox}}" Path="Items.Count" />
                                <Binding RelativeSource="{RelativeSource Self}" Path="(ItemsControl.AlternationIndex)" />
                            </MultiBinding>
                        </DataTrigger.Binding>
                        <!-- Could set the ItemTemplate instead -->
                        <Setter Property="Background" Value="Red"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Grid.Resources>

        <ListBox ItemsSource="{Binding Source={StaticResource MyCollection}}"
                 AlternationCount="{Binding RelativeSource={RelativeSource Self}, Path=Items.Count}"
                 ItemContainerStyle="{StaticResource MyListBoxItemStyle}" />
    </Grid>