none
如何实现ListView中ListViewItem颜色的间隔变化 RRS feed

  • 问题

  • 我参考了 https://msdn.microsoft.com/library/ms750769(v=vs.90).aspx

    但是里面的内容并不全部适用于 uwp 的 xaml

    希望有人能够为我解答使用 IValueConverter 和 ItemContainerStyleSelector 的方案

    谢谢

    2015年12月15日 3:42

全部回复

  • 手头没有开发环境,不是太方便直接给你写个例子,不过 你可以看看这篇帖子 http://stackoverflow.com/questions/27607886/alternating-colors-of-rows-in-listview-in-windows-phone-8-1

    对于我来说,我比较倾向使用ItemContainerStyleSelector  他与WPF中的原理是一样的,在你的ListView.ItemContainerStyleSelector指定了你的Selector对象后,在你的selector对象中就可以基于当前container来返回不同的Style。


    Bob Bao

    Do you still use the same Windows 8 LockScreen always? Download Chameleon Win8 App quickly, that changes your LockScreen constantly.
    你是否还在看着一成不变的Windows 8锁屏而烦恼,赶紧下载这个 百变锁屏 应用,让你的锁屏不断地变化起来。

    2015年12月15日 8:09
  • 建议使用DataTemplateSelector。

    自己的模板选择器类继承DataTemplateSelector,重写其SelectTemplateCore方法。

    根据自定义的Model字段判断返回的模板对象。


    专注于Windows Phone

    2015年12月15日 10:03
    版主
  • ?????
    • 已建议为答案 Jie Bao 2015年12月16日 3:09
    • 已编辑 [-] 2018年1月11日 13:47
    2015年12月15日 13:22
  • 楼主这种方式不属于动态模板。

    我也将使用DataTemplateSelector的方式贴出,这种方式我觉得在样式实现上更为灵活,推荐使用。

    仅供参考:

        public class ColorTemplateSelector : DataTemplateSelector
        {
            public DataTemplate TemplateRed { get; set; }
            public DataTemplate TemplateGreen { get; set; }
    
            protected override DataTemplate SelectTemplateCore
                (object item, DependencyObject container)
            {
                SampleData listData = item as SampleData;
    
                if (listData.IsPremium == true)
                {
                    return TemplateGreen;
                }
                else if (listData.IsPremium == false)
                {
                    return TemplateRed;
                }
                else
                {
                    return base.SelectTemplate(item, container);
                }
            }
        }

     <Page.Resources>
            <DataTemplate x:Key="GreenColor">
                <Border Background="Green" Height="200" Width="200">
                    <TextBlock Text="{Binding Title}" />
                </Border>
            </DataTemplate>
            <DataTemplate x:Key="RedColor">
                <Border Background="Red" Height="200" Width="200">
                    <TextBlock Text="{Binding Title}" />
                </Border>
            </DataTemplate>
            <local:ColorTemplateSelector x:Key="colorTemplateSelector" TemplateGreen="{StaticResource GreenColor}" TemplateRed="{StaticResource RedColor}" />
        </Page.Resources>
        
        <ListBox x:Name="list" ItemTemplateSelector="{StaticResource colorTemplateSelector}" />
        public class SampleData
        {
            public string Title
            {
                get;
                set;
            }
    
            public bool IsPremium
            {
                get;
                set;
            }
        }
    
     
           public MainPage()
            {
                this.InitializeComponent();
                List<SampleData> data = new List<SampleData>{
                new SampleData(){Title="Item1", IsPremium = true},
                new SampleData(){Title="Item2", IsPremium = false},
                new SampleData(){Title="Item3", IsPremium = true},
                new SampleData(){Title="Item4", IsPremium = false},
                new SampleData(){Title="Item5", IsPremium = true},
                new SampleData(){Title="Item6", IsPremium = false},
                new SampleData(){Title="Item7", IsPremium = true}};
    
                this.list.ItemsSource = data;
    
            }



    专注于Windows Phone


    2015年12月16日 3:01
    版主
  • 世外涛缘,你好,你的方法在实际使用中是不可行的。为什么?因为数据源可能需要插入删除(不需要插入删除的数据源就更不需要“动态模板”了,直接在生成数据时赋值然后使用转换器不就行了么)。所以必须处理容器,而不是数据项。需要支持插入删除时使用如下方式。

    MainPage.xaml

    <Page x:Class="App1.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    	<ListView x:Name="listView" ContainerContentChanging="listView_ContainerContentChanging">
    		<ListView.Resources>
    			<SolidColorBrush x:Key="Item0" Color="#FFAAEEEE"/>
    			<SolidColorBrush x:Key="Item1" Color="#FFCCFFFF"/>
    		</ListView.Resources>
    	</ListView>
    </Page>

    MainPage.xaml.cs

    namespace App1
    {
        public sealed partial class MainPage : Windows.UI.Xaml.Controls.Page
        {
            public MainPage()
            {
                this.InitializeComponent();
                listView.ItemsSource = new System.Collections.ObjectModel.ObservableCollection<System.String> { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" };
                listView.Items.VectorChanged += items_VectorChanged;
                listView.SelectionChanged += listView_SelectionChanged;
            }
            private void items_VectorChanged(Windows.Foundation.Collections.IObservableVector<object> sender, Windows.Foundation.Collections.IVectorChangedEventArgs @event)
            {
                for (var index = 0; index != sender.Count; ++index)
                {
                    ((Windows.UI.Xaml.Controls.ListViewItem)listView.ContainerFromIndex(index)).Background = (Windows.UI.Xaml.Media.SolidColorBrush)listView.Resources["Item" + (index % 2).ToString()];
                }
            }
            private void listView_SelectionChanged(object sender, Windows.UI.Xaml.Controls.SelectionChangedEventArgs e)
            {
                ((System.Collections.ObjectModel.ObservableCollection<System.String>)listView.ItemsSource).RemoveAt(1);
            }
            private void listView_ContainerContentChanging(Windows.UI.Xaml.Controls.ListViewBase sender, Windows.UI.Xaml.Controls.ContainerContentChangingEventArgs args)
            {
                args.ItemContainer.Background = (Windows.UI.Xaml.Media.SolidColorBrush)sender.Resources["Item" + (args.ItemIndex % 2).ToString()];
            }
        }
    }

    因为ListView是虚拟化的,所以容器是很少量的,而数据项可能是容器的几十甚至几百倍。还有如果处理的是数据项,那么数据项还必须实现支持动态绑定的属性。况且背景色属于UI呈现问题,不可能把这个问题延伸到数据模板和数据源中去,所以你的这种方法在实际项目中不可行。

    顺便问一下,你这种方式和转换器有什么区别呢?还不如转换器高效。



    无法认同你的观点:

    1. 动态模板选择,当然可以动态的更新数据源。

    2. 这两种方式各有优缺点,根据自己的实际需要选择就好。

    3. 你认同的转换器方式,相对模板选择器要高效一些。但模板选择器没有你想的那么不堪,至少我在项目中使用过,手机里显示也没有性能问题。

    4. 模板选择器的方式,对应复杂的模板变化(而不仅仅是简单的背景色变换),就体现出它的优势了。

    你可以试想一下这个例子:一个人员列表,里面有两种不同的人员,职工和管理者,职工的显示外观为A,管理者显示外观为B,A和B外观差异较大(不只是颜色,自行脑补好了)

    这样的场景用值转换器实现是不是就复杂了?

    问题不要都往极端考虑,每种方案都有其各自的使用场景。

    另外建议不要动辄强调高效(性能),个人觉得应该优先考虑业务实现,性能问题通常可以放到后面解决。

    而目前的硬件性能已经很好了,大多数以前我们担心的性能问题往往没有出现。



    专注于Windows Phone

    2015年12月16日 9:24
    版主