在ListView不同的项目模板,第一和最后一个项目 [英] Distinct item template for first and last item in a ListView

查看:193
本文介绍了在ListView不同的项目模板,第一和最后一个项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要不同风格的列表的第一个和最后一个项目。为了实现这一目标,我开始基于这个答案的解决方案的工作:<一href=\"http://stackoverflow.com/questions/7767097/use-different-template-for-last-item-in-a-wpf-itemscontrol/7767131#7767131\">Use在WPF ItemsControl的

不同的模板,最后一个项目

基本上,我有一个模板上决定采取基于列表视图中的项目。

项目的指数(code以下)的自定义ItemsTemplateSelector

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

 公共类FirstLastTemplateSelector:DataTemplateSelector
{
    公众的DataTemplate DefaultTemplate {搞定;组; }
    公众的DataTemplate FirstItemTemplate {搞定;组; }
    公众的DataTemplate LastItemTemplate {搞定;组; }
    公众的DataTemplate SingleItemTemplate {搞定;组; }    公众覆盖的DataTemplate SelectTemplate(对象项目,DependencyObject的容器)
    {
        ListView控件LV = VisualTreeHelperEx.FindParentOfType&LT;&的ListView GT;(容器);
        如果(LV!= NULL)
        {
            如果(lv.Items.Count == 1)
            {
                返回SingleItemTemplate;
            }            INT I = lv.Items.IndexOf(项目);
            如果(我== 0)
            {
                返回FirstItemTemplate;
            }
            否则如果(ⅰ== lv.Items.Count - 1)
            {
                返回LastItemTemplate;
            }
        }
        返回DefaultTemplate;
    }
}


解决方案

作为一个替代方法,我建议结合 AlternationCount 你的的ItemsControl的到您的收藏中的项目数量(如计数属性)。这将然后分配给每个容器在的ItemsControl 唯一的 AlternationIndex (0,1,2,...伯爵-1)。在这里看到更多的信息:

<一个href=\"http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.alternationcount.aspx\">http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.alternationcount.aspx

在每个容器都有一个唯一的 AlternationIndex 您可以使用 DataTrigger 在你的容器风格基于的ItemTemplate 来衬托指数。这可以做到用一个 MultiBinding 与返回转换器如果指数等于计数,其它。当然,你也可以围绕这个方法的选择也是如此。与转换器之外,这种方法是很好的,因为它是一个XAML唯一解决方案。

用一个例子的的ListBox

 &LT;窗​​口x:类=WpfApplication4.MainWindow
        的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
        的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
        的xmlns:集合=CLR的命名空间:System.Collections中;装配= mscorlib程序
        的xmlns:系统=CLR的命名空间:系统;装配= mscorlib程序
        的xmlns:L =CLR的命名空间:WpfApplication4
        标题=主窗口HEIGHT =350WIDTH =525&GT;
    &LT;网格和GT;
        &LT; Grid.Resources&GT;
            &LT;类别:ArrayList的X:键=MyCollection的&GT;
                &lt;系统:字符串&GT;项目的One&LT; /系统:字符串&GT;
                &lt;系统:字符串&GT;项目二&LT; /系统:字符串&GT;
                &lt;系统:字符串&GT;项目三&LT; /系统:字符串&GT;
            &LT; /类别:ArrayList的&GT;            &LT; L:MyAlternationEqualityConverter X:键=MyAlternationEqualityConverter/&GT;            &LT;风格X:键=MyListBoxItemStyle的TargetType ={X:输入一个ListBoxItem}&GT;
                &LT; Style.Triggers&GT;
                    &LT; D​​ataTrigger值=真&GT;
                        &LT; D​​ataTrigger.Binding&GT;
                            &LT; MultiBinding转换器={StaticResource的MyAlternationEqualityConverter}&GT;
                                &LT;绑定的RelativeSource ={的RelativeSource FindAncestor,AncestorType = {X:类型列表框}}路径=Items.Count/&GT;
                                &LT;绑定的RelativeSource ={自我的RelativeSource}PATH =(ItemsControl.AlternationIndex)/&GT;
                            &LT; / MultiBinding&GT;
                        &LT; /DataTrigger.Binding>
                        &LT;! - 能设置的ItemTemplate而不是 - &GT;
                        &LT; setter属性=背景VALUE =红/&GT;
                    &LT; / DataTrigger&GT;
                &LT; /Style.Triggers>
            &LT; /样式和GT;
        &LT; /Grid.Resources>        &LT; ListBox中的ItemsSource ={绑定源= {StaticResource的MyCollection的}}
                 AlternationCount ={绑定的RelativeSource = {自我的RelativeSource},路径= Items.Count}
                 ItemContainerStyle ={StaticResource的MyListBoxItemStyle}/&GT;
    &LT; /网格和GT;

如果转换器可能看起来是这样的:

 类MyAlternationEqualityConverter:IMultiValueConverter
{
    IMul​​tiValueConverter的#区域实施    公共对象转换(对象[]值类型TARGETTYPE,对象参数,CultureInfo的文化)
    {
        如果(值=空&放大器;!&放大器; values​​.Length == 2和;&放大器;
            值[0]为int&放大器;&安培;值[1]为int)
        {
            返回等于((int)的值[0],(int)的值[1] + 1);
        }        返回DependencyProperty.UnsetValue;
    }    公用对象[] ConvertBack(对象的值,类型[] targetTypes,对象参数,CultureInfo的文化)
    {
        抛出新NotSupportedException异常();
    }    #endregion
}

I need to style the first and last items of a list view differently. To achieve that, I started working on a solution based on that answer: Use different template for last item in a WPF itemscontrol

Basically, I have a custom ItemsTemplateSelector that decide on the template to apply based on the item's index in the list view items (code below).

It works properly except that when the list gets updated (an item is added or removed), the templates do not get selected again (for instance, initially, the SingleItemTemplate gets selected because there is a single item. When I add an item to the list, that first item's template does not get switched to FirstItemTemplate). How to force template selection for all items?

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;
    }
}

解决方案

As an alternative approach, I would suggest binding the AlternationCount of your ItemsControl to the number of items in your collection (e.g. the Count property). This will then assign to each container in your ItemsControl a unique AlternationIndex (0, 1, 2, ... Count-1). See here for more information:

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

Once each container has a unique AlternationIndex you can use a DataTrigger in your container Style to set the ItemTemplate based off of the index. This could be done using a MultiBinding with a converter that returns True if the index is equal the count, False otherwise. Of course you could also build a selector around this approach as well. With the exception of the converter, this approach is nice since it is a XAML only solution.

An example using a 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>

Where the converter might look something like:

class MyAlternationEqualityConverter : IMultiValueConverter
{
    #region Implementation of IMultiValueConverter

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values != null && values.Length == 2 &&
            values[0] is int && values[1] is int)
        {
            return Equals((int) values[0], (int) values[1] + 1);
        }

        return DependencyProperty.UnsetValue;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }

    #endregion
}

这篇关于在ListView不同的项目模板,第一和最后一个项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆