当然,是不依赖于数据源的。
先上个最终效果图给大家看一下。。。
方法一 依赖于数据源与ItemTemplate,放弃
第一个想到的时在数据源上指定一些数值,或直接加个Color字段让前台XAML中的ItemTemplate前台绑定。
但瞬间被否定,
这么样做的话每个次这个场景数据源都得改,ItemTemplate也得改,没有任何可重用性。
用此方法简直2到无极限,虽然实现起来挺简单,可真的不敢写出那样的丢人代码.....
方法二 重载ListBox
核心思想:在绑定显示每行的时候,拿当前行的数据与数据源求index,判断奇偶数,然后设置颜色
由于做过多年的Web编程,想到Web中GirdView在绑定每一条数据的时候都会激发RowDataBound事件,想到ListBox应该与也有这种绑定单条数据的事件吧!
然后我找啊找,找啊找....
在此先说明一下ListBox类继承关系
ItemsControl,ISupportInitialize=>Selector=>ListBox
终于在ItemsControl类中中发现了PrepareContainerForItemOverride方法,当数据项需要在UI中渲染展现时,就会调用到它.
注意:并不是在绑定数据源,只是在UI展现时才会调用
PrepareContainerForItemOverride 的官方说明:准备指定元素以显示指定项
它有两个参数element与item,在这里element是ListBoxItem, item是你的数据项
先上代码
public class ZListBox : ListBox
{
///
/// 奇行背景色
///
SolidColorBrush OneColorBrush = new SolidColorBrush(Color.FromArgb(20, 255, 255, 255));
///
/// 偶行背景色
///
SolidColorBrush TwoColorBrush = new SolidColorBrush(Color.FromArgb(20, 0, 0, 0));
///
/// 准备指定元素以显示指定项
///
/// 用于显示指定项的元素
/// 要显示的项
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
int index = 0;
//返回一个循环访问集合的枚举器
var enumerator = ItemsSource.GetEnumerator();
//取得当前项的Index
while (enumerator.MoveNext())
{
if (enumerator.Current == item)
break;
index++;
}
ListBoxItem boxItem = element as ListBoxItem;
boxItem.Background = Convert.ToBoolean(index % 2) ? OneColorBrush : TwoColorBrush;//判断奇偶数并设置背景
base.PrepareContainerForItemOverride(element, item);
}
}
代码应该很简单,就不做更多的说明了。
但有一点需要注意,你若是ItemTemplate自己设置了背景色,在下这厢可就无能为力啦。。。
说一点题外的:
虚拟化与 PrepareContainerForItemOverride
“虚拟化”是指一种技术,通过该技术,可根据屏幕上所显示的项来从大量数据项中生成 UI 元素的子集。
PrepareContainerForItemOverride 只提取需要UI渲染的那部分据,比如我绑定了四十多条数据,它激发16次,因为它只准备显示UI相应的数据。在滚动列表时,才会进步一激发。
它可以取得你当前UI渲染了哪些数据,哪些内存中。