首页 > 代码库 > WPF数据视图学习
WPF数据视图学习
当你绑定集合到ItemsControl,数据视图被安静地在幕后创造。视图位于数据源和绑定控件之间。数据视图是通往数据源的一个窗口。它跟踪当前项目,它支持诸如排序,过滤,和分组特征。这些特征独立于数据对象本身,意味着你能以不同的方式、在窗口的不同部分(或应用的不同部分)绑定相同的数据。例如,你能绑定相同的产品集合到两个不同的列表但是过滤他们显示不同的记录。
视图对象依赖于数据对象的类型。所有的视图派生自CollectionView,但是两个特殊的实现派生自CollectionView:ListCollectionView和BindingListCollectionView。这是它如何工作:
- 如果数据源实现IBindingList,一个BindingListCollectionView被创造。当你绑定一个ADO.NET DataTable时发生。
- 如果数据源没有实现IBindingList但是它实现IList,一个ListCollectionView被创造。当你绑定一个ObservableCollection,如同产品的列表。
- 如果你的数据源没有实现IBindingList或IList但是它实现IEnumerable,你获得一个基本CollectionView。
取回一个视图对象
为获得一个目前在使用的视图对象,你使用System.Windows.Data.CollectionViewSource类的GetDefaultView()静态方法。当你调用GetDefaultView(),并传递数据源,就是你正使用的集合。这是一个例子,获得绑定到列表的产品集合的视图:
ListCollectionView lcv = CollectionViewSource.GetDefaultView(list) as ListCollectionView;
有了视图对象,就可以导航、排序、过滤和分组了。
视图导航
视图对象决定列表项目的数目(Count属性)和获得当前的数据对象一个引用(CurrentItem)或当前的位置索引(CurrentPosition)。也能使用几个方法从一记录移动到另一个,诸如MoveCurrentToFirst(),MoveCurrentToLast(),MoveCurrentToNext(),MoveCurrentToPrevious(),和MoveCurrentToPosition()。
private void Button_Click_2(object sender, RoutedEventArgs e) { lcv.MoveCurrentToNext(); lv.ScrollIntoView(lv.SelectedItem); }
<ListView Height="200" Name="lv" IsSynchronizedWithCurrentItem="True" >
要注意对ListView一定要加IsSynchronizedWithCurrentItem="True"这句,在对视图对象操作时同步发生,否则操作视频不起作用。
排序
<StackPanel Orientation="Horizontal"> <RadioButton Content="姓名" Click="RadioButton_Click"></RadioButton> <RadioButton Content="年龄" Click="RadioButton_Click_1"></RadioButton> </StackPanel>
注意在排序前先清空以前的排序,否则排序不起作用。
private void RadioButton_Click(object sender, RoutedEventArgs e) { lcv.SortDescriptions.Clear(); lcv.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); }
过滤
过滤允许你显示满足特定条件的一个子集。当带有一个集合作为数据源工作时,你使用视图对象的Filter属性设置过滤。
Filter属性的实现有点笨拙。它接受一个Predicate委托指向一个自定义过滤方法
private void Button_Click_5(object sender, RoutedEventArgs e) { if (key.Text.Trim() == "") lcv.Filter = null; lcv.Filter = item => { var p = item as Person; if (p.Name.Contains(key.Text)) { return true; } else return false; }; }
分组
当你使用分组,你的列表为每个分组创造一个独立的GroupItem对象,并且它添加这些GroupItem对象到列表。GroupItem是一个内容控件,所以每个GroupItem持有合适的容器(好像ListBoxItem对象),容器带有你的实际的数据。显示你的分组的关键是格式化GroupItem元素所以它脱颖而出。
分组是比较麻烦,但一定要掌握,下面以一个实例完成分组功能
1、首先绑定数据 ,获取视图ListCollectionView lcv,接下来实现分组依据-创建值转换器分组类,比如姓名长度分组,还有按年龄大小分组:
public class SizeGroup : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { int p = (int)value; if (p > 50) return "老年组"; else return "青年组"; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } public class LengthGroup : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var p = value.ToString(); if (p.Length > 6) { return "三个字的"; } else return "二个字的"; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
2、添加分组样式ListView.GroupStyle,这里就确定了分组标题具体样式,添加HeaderTemplate模板,如下 ,其binging Name 和ItemCount是CollectionViewGroup对象提供的属性。
<ListView Height="200" Name="lv" IsSynchronizedWithCurrentItem="True" > <ListView.View> <GridView> <GridView.Columns> <GridViewColumn Header="姓名" DisplayMemberBinding="{Binding Name}"></GridViewColumn> <GridViewColumn Header="年龄" DisplayMemberBinding="{Binding Age}"></GridViewColumn> </GridView.Columns> </GridView> </ListView.View> <ListView.GroupStyle> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <Border BorderThickness="3" BorderBrush="Green"> <StackPanel> <TextBlock Text="{Binding Name}"></TextBlock> <TextBlock> <Run>(共有</Run> <Run Text="{Binding ItemCount}"></Run> <Run>个文件)</Run> </TextBlock> </StackPanel> </Border> </DataTemplate> </GroupStyle.HeaderTemplate> </GroupStyle> </ListView.GroupStyle> </ListView>
3、对分组按钮添加事件:
<StackPanel Orientation="Horizontal"> <RadioButton Content="按年龄大小分组" Click="RadioButton_Click_2"></RadioButton> <RadioButton Content="按姓名长度分组" Click="RadioButton_Click_3"></RadioButton> </StackPanel>
private void RadioButton_Click_2(object sender, RoutedEventArgs e) { lcv.GroupDescriptions.Clear(); lcv.GroupDescriptions.Add(new PropertyGroupDescription("Age", new SizeGroup())); } private void RadioButton_Click_3(object sender, RoutedEventArgs e) { lcv.GroupDescriptions.Clear(); lcv.GroupDescriptions.Add(new PropertyGroupDescription("Name", new LengthGroup())); }
事件中对视图添加相应的分组条件并传入值转换器。实现完毕
WPF数据视图学习