询问者
如何实现ListView中ListViewItem颜色的间隔变化

问题
全部回复
-
手头没有开发环境,不是太方便直接给你写个例子,不过 你可以看看这篇帖子 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锁屏而烦恼,赶紧下载这个 百变锁屏 应用,让你的锁屏不断地变化起来。 -
楼主这种方式不属于动态模板。
我也将使用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
- 已编辑 世外涛缘MVP, Moderator 2015年12月16日 3:02 补充说明
- 已建议为答案 Jie Bao 2015年12月16日 3:09
-
世外涛缘,你好,你的方法在实际使用中是不可行的。为什么?因为数据源可能需要插入删除(不需要插入删除的数据源就更不需要“动态模板”了,直接在生成数据时赋值然后使用转换器不就行了么)。所以必须处理容器,而不是数据项。需要支持插入删除时使用如下方式。
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