WPF进阶技巧和实战03-控件(5-列表、树、网格03)
数据视图
数据视图是在后台工作的,用于协调绑定数据的集合。使用数据视图可以添加导航逻辑、实现数据过滤、排序、分组。
当将集合或者DataTable绑定到ItemsControl控件时,会不加通告地在后台创建数据视图(位于数据源和绑定的控件之间)。数据视图是进入数据源的窗口,可以跟踪当前项,并且支持各种功能(排序、过滤、分组等)。这些功能和数据对象本身是相互独立的,这意味着可以在窗口的不同部分使用不同的方式绑定相同的数据源。例如:可将同一产品集合绑定到两个不同的列表,并对产品进行过滤显示不同的记录。
View对象
使用的视图对象取决于数据对象的类型。所有视图都继承自CollectionView类,比较特殊的两个实现是:ListCollectionView和BindingListCollectionView。
- 如果数据源实现了IBindingList接口,就会创建BindingListCollectionView视图(DataTable对象绑定时)
- 如果数据源没有实现IBindingList接口,但实现了IList接口,就会创建ListCollectionView视图,当绑定ObservableCollection集合时
- 如果数据源没有实现IBindingList或IList接口,但是实现了IEnumerable接口时,就会得到基本的CollectionView视图
检索视图对象
得到当前视图对象的方法
ICollectionView view = CollectionViewSource.GetDefaultView(lstProducts.ItemsSource);
根据需要转换成合适的类即可。
视图导航
- 可使用视图对象进行下列操作:
- 获取列表中的项数(Count属性)
- 获取当前数据对象的引用(CurrentItem属性)
- 当前位置索引(CurrentIndex属性)
- 从一条记录移动到另一条(MoveCurrentToFirst,MoveCurrentToLast,MoveCurrentToNext,MoveCurrentToPrevious,MoveCurrentTo,MoveCurrentToPosition)
以声明方式创建视图
可以在代码中检索视图或者修改视图,还可以在XAML标记中创建CollectionViewSource对象,然后将其绑定到控件上。
CollectionViewSource的两个重要属性就是View和Source,View属性封装了视图的对象,Source属性封装了数据源。还有SortDescriptions和GroupDescriptions
<Window.Resources>
<local:PriceRangeProductGrouper x:Key="Price50Grouper" GroupInterval="50"/>
<CollectionViewSource x:Key="GroupByRangeView">
<CollectionViewSource.SortDescriptions>
<component:SortDescription PropertyName="UnitCost" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="UnitCost" Converter="{StaticResource Price50Grouper}"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
代码中的实现:
CollectionViewSource viewSource = (CollectionViewSource)this.FindResource("GroupByRangeView");
viewSource.Source = products;
过滤、排序、分组
过滤集合
通过过滤可以显示符合特定条件的子集。可使用视图对象的Filter属性设置过滤器。
ListCollectionView view = CollectionViewSource.GetDefaultView(lstProducts.ItemsSource) as ListCollectionView;
if (view != null)
{
filterer = new ProductByPriceFilterer(minimumPrice);
view.Filter = new Predicate<object>(filterer.FilterItem);
view.Refresh();
}
public class ProductByPriceFilterer
{
public decimal MinimumPrice
{
get;
set;
}
public ProductByPriceFilterer(decimal minimumPrice)
{
MinimumPrice = minimumPrice;
}
public bool FilterItem(Object item)
{
Product product = item as Product;
if (product != null)
{
if (product.UnitCost > MinimumPrice)
{
return true;
}
}
return false;
}
}
过滤DataTable对象
通过BindingListCollectionView的CustomFilter 属性
decimal minimumPrice;
if (Decimal.TryParse(txtMinPrice.Text, out minimumPrice))
{
BindingListCollectionView view = CollectionViewSource.GetDefaultView(lstProducts.ItemsSource) as BindingListCollectionView;
if (view != null)
{
view.CustomFilter = "UnitCost > " + minimumPrice.ToString();
}
}
排序
使用视图进行排序,最简单的办法就是根据每个数据项中的一个或者多个属性的值进行排序。使用SortDescriptions对象来确定希望排序的字段。包含了希望排序的字段和排序方向(升序或者降序),按照希望排序的先后进行添加即可。
ICollectionView view = CollectionViewSource.GetDefaultView(lstProducts.ItemsSource);
view.SortDescriptions.Add(new SortDescription("ModelName", ListSortDirection.Ascending));
还可以自定义排序,只能用于ListCollectionView视图(不能用于BindingListCollectionView)。ListCollectionView提供了CustomSort属性来接收一个IComparer对象,这个对象在两个数据项之间进行比较,并且指示较大项。
public class SortByModelNameLength : System.Collections.IComparer
{
public int Compare(object x, object y)
{
Product productX = (Product)x;
Product productY = (Product)y;
return productX.ModelName.Length.CompareTo(productY.ModelName.Length);
}
}
ListCollectionView view = (ListCollectionView)CollectionViewSource.GetDefaultView(lstProducts.ItemsSource);
view.CustomSort = new SortByModelNameLength();
分组
简单方式分组(根据单个属性),复杂方式分组(自定义回调函数)
通过视图的GroupDescriptions属性,添加分组依据。
ICollectionView view = CollectionViewSource.GetDefaultView(lstProducts.It
view.SortDescriptions.Add(new SortDescription("CategoryName", ListSortDir
view.SortDescriptions.Add(new SortDescription("ModelName", ListSortDirect
view.GroupDescriptions.Add(new PropertyGroupDescription("CategoryName"));
当时用分组后,列表为每个分组创建了单独的GroupItem对象,并且为列表添加了这些GroupItem对象。GroupItem是内容控件,所以每个GroupItem对象都包含一个适当的具有实际数据的容器(如ListBoxItem对象),显示分组的秘密是格式化GroupItem对象,使其突出显示。
可以使用样式来为列表中的所有GroupItem对象应用格式。可以通过ItemsControl的GroupStyle属性来实现,GroupStyle类包含了如下属性:
| 名称 | 说明 |
|---|---|
| ContainerStyle | 设置被应用到每个分组生成的GroupItem的样式 |
| ContainerStyleSelector | 通过代码来设置每个分组的GroupItem的正确样式 |
| HeaderTemplate | 允许用户为每个分组的头显示内容并创建模板 |
| headerTemplateSelector | 通过代码来为每个分组的头设置并创建模板 |
| Panel | 改变用于分组的模板,比如使用WrapPanel代替StackPanel,创建从左到右然后向下平铺分组的列表 |
<ListBox Grid.Row="1" Margin="7,3,7,10" Name="lstProducts" DisplayMemberPath="ModelName">
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold"
Foreground="White" Background="LightGreen" Margin="0,5,0,0" Padding="3"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
</ListBox>
- 范围分组
需要提供一个转换器,检查数据源中的一个字段或者多个字段,并返回组标题。只需要多个数据对象使用相同的组标题,就可以被放到相同的分组中。
- 分组和虚拟化
为了降低控件的内存开销,绑定较长的列表时能够提升速度,需要使用控件支持虚拟化。通过VirtualizingStackPanel.IsVirtualizingWhenGrouping=true来讲分组列表和未分组列表获取相同的虚拟化性能提升效果。
实时成型
如果改变正在使用的视图的过滤、排序、分组,就需要调用ICollectionViewSource.Refresh()方法来刷新视图,并确保正确的项出现在列表中。
实时成型的功能:监视特定属性中的变化,如果发生变化,就确定响应更改会影响当前视图并触发刷新动作。
使用实时成型需要满足的3个标准:
- 数据对象必须实现INotifyPropertyChanged,当属性变化时,使用该接口发出通知
- 集合必须实现ICollectionViewLiveShaping,标准的ListCollectionView和BindingListCollectionView都实现了这个接口
- 必须明确启用实时成型
实时成型会增加额外的开销,因此需要设置3个独立的属性:IsLiveFiltering、IsLiveSorting、IsLiveGrouping。通过这3个属性来设置哪些动作启用实时成型,除此之外,还需要设置哪些属性的变化会触发实时成型。
ListCollectionView lcview = CollectionViewSource.GetDefaultView(lstProducts.ItemsSource) as ListCollectionView;// Now if you edit and reduce the price (below the filter condition) the record will disappear automatically.lcview.IsLiveFiltering = true;lcview.LiveFilteringProperties.Add("UnitCost");
WPF进阶技巧和实战03-控件(5-列表、树、网格03)的更多相关文章
- WPF进阶技巧和实战03-控件(3-文本控件及列表控件)
系列文章链接 WPF进阶技巧和实战01-小技巧 WPF进阶技巧和实战02-布局 WPF进阶技巧和实战03-控件(1-控件及内容控件) WPF进阶技巧和实战03-控件(2-特殊容器) WPF进阶技巧和实 ...
- WPF进阶技巧和实战03-控件(4-基于范围的控件及日期控件)
系列文章链接 WPF进阶技巧和实战01-小技巧 WPF进阶技巧和实战02-布局 WPF进阶技巧和实战03-控件(1-控件及内容控件) WPF进阶技巧和实战03-控件(2-特殊容器) WPF进阶技巧和实 ...
- WPF进阶技巧和实战06-控件模板
逻辑树和可视化树 System.Windows.LogicalTreeHelper System.Windows.Media.VisualTreeHelper 逻辑树类(LogicalTreeHelp ...
- WPF进阶技巧和实战07--自定义元素02
在01节中,研究了如何开发自定义控件,下节开始考虑更特殊的选择:派生自定义面板以及构建自定义绘图 创建自定义面板 创建自定义面板是一种比较常见的自定义控件开发子集,面板可以驻留一个或多个子元素,并且实 ...
- WPF进阶技巧和实战09-事件(2-多点触控)
多点触控输入 多点触控输入和传统的基于比的输入的区别是多点触控识别手势,用户可以移动多根手指以执行常见的操作,放大,旋转,拖动等. 多点触控的输入层次 WPF允许使用键盘和鼠标的高层次输入(例如单击和 ...
- WPF进阶技巧和实战03-控件(1-控件及内容控件)
所有控件都继承自System.Windows.Controls.Control类,这个类添加一些基本结构: 设置控件内容对齐方式 (HorizontalContentAlignment,Vertica ...
- WPF进阶技巧和实战03-控件(5-列表、树、网格02)
数据模板 样式提供了基本的格式化能力,但是不管如何修改ListBoxItem,他都不能够展示功能更强大的元素组合,因为了每个ListBoxItem只支持单个绑定字段(通过DisplayMemberPa ...
- WPF进阶技巧和实战03-控件(5-列表、树、网格01)
列表控件 ItemsControl为列表项控件定义了基本功能,下图是ItemsControl的继承关系: 在继承自ItemsControl类的层次结构中,还显示了项封装器(MenuItem.TreeV ...
- WPF进阶技巧和实战08-依赖属性与绑定03
数据提供者 在大多数的代码中,都是通过设置元素的DataContext属性或者列表控件的ItemsSource属性,从而提供顶级的数据源.当数据对象是通过另一个类构造时,可以有其他选择. 一种是作为窗 ...
随机推荐
- 【mysql】explain性能分析
1. explain的概念 使用EXPLAIN 关键字可以模拟优化器执行SQL 查询语句,从而知道MySQL 是如何处理你的SQL 语句的.分析你的查询语句或是表结构的性能瓶颈. 用法: Explai ...
- Redis缓存雪崩、缓存穿透、热点key
转载自 https://blog.csdn.net/wang0112233/article/details/79558612 https://www.sohu.com/a/230787856_231 ...
- CentOS7中apache的部署与配置
一.apache的部署 输入命令 yum list | grep httpd 查看可安装的软件包,选择"httpd.x86_64"安装. 输入命令 yum install http ...
- 1TB是多大?
TB是计算机的存储单位,用来描述计算机的存储容量.另外还有GB.MB.KB.B.就像长度单位米.分米.厘米.毫米一样,它们之间有换算关系: 1KB = 1024B 1M = 1024KB 1GB = ...
- Go测试--main测试
目录 简介 示例 简介 子测试的一个方便之处在于可以让多个测试共享Setup和Tear-down.但这种程度的共享有时并不满足需求,有时希望在整个测试程序做一些全局的setup和Tear-down,这 ...
- vue开发:前端项目模板
简介 vue-cli创建vue项目,整合vuex.vue-router.axios.element-ui 项目模板下载地址 创建项目 使用vue-cli创建项目,功能选择:Babel.Router.v ...
- ES6扩展——箭头函数
1.箭头函数 在es6中,单一参数的单行箭头函数语法结构可以总结如下: const 函数名 = 传入的参数 => 函数返回的内容,因此针对于 const pop = arr => arr. ...
- HashSet的add()方法源码解析(jdk1.8)
HashSet 实现了Set接口 实际上是HashMap 可以存null,但只能有一个 不保证元素是有序的,取决于hash后,在确定索引结果 add源码 //核心操作putVal final V pu ...
- docker-harbor私有仓库使用笔记
1. 登录harbor管理页面,创建项目,比如yuqx_test 2. admin登录,此处免密登录,正常情况下会输入账号密码 [root@k8s-rancher2 ~]# docker login ...
- Onenote实现OCR识别图片
OCR识别推荐两个软件: 1. Tesseract:一个开源的,由谷歌维护的OCR软件. 2. Onenote:微软Office附带或者可以自己独立安装. 3. O ...