【转】   [WPF]ListView点击列头排序功能实现

这是一个非常常见的功能,要求也很简单,在Column Header上显示一个小三角表示表示现在是在哪个Header上的正序还是倒序就可以了。微软的MSDN也已经提供了实现方式。微软的方法中,是通过ColumnHeader Template实现的,一共要维护至少两个Header Template,一个显示正三角,一个显示倒三角。在用户点击Header的时候同时切换使用的Template。如果你的ListView只提供Sort功能,这个方法就可以了。但是如果你的ListView还在在Header中提供Filter功能呢?如果还需要用户可以配置是否开启Sort和Filter功能呢?那么你就需要6个Template来处理Sort和Filter的组合。如果在Header本来就有好几种(文字Header、画片Header等)或是要放入更多的功能呢?显然微软的这个方式只能用于技术演示(当然MSDN本来就是这个目的),面对实际项目时就会力不从心。Google搜索WPF ListView Sort,可以找到很多不同的实现方式。

1.       SwitchOnTheCode:使用Adorner Layer,重写Adorner的OnRender方法,画出一个三角形。画个三角可以,要画个有发光、渐变、动画效果的三角,代码会变得很难维护。而且不能用Blend去编辑这个样式。不过思路是很好的,因为它不会占用控件的现有的任何属性,就不会有微软的方式中功能组合的问题。

2.       Jeol Rumerman’s Blog:继承GridViewColumn,扩展出Sort功能。还是用Header Template,更糟糕的是,为加一个功能而使用继承本身就不是一个很好的设计。同理要加个Filter功能,是不是还要继承出一个FilteredGridViewColumn和FilteredAndSortedGridViewColumn呢?不仅要处理Template的组合,还会产生类膨胀,实在是不可取。

3.       CodeProject WPFListViewSorter:与微软的方式一样,只是通过自定义Sorter函数解决了微软的方式中,把Column Header上的名字,当作Sort Property的问题。

4.       Thejoyofcode:通过Attached Property解决了同样的问题,而且没有界面显示的实现。而且还继承出了一个SortableListView。缺点就不再解释了。

5.       Marlongrech:提供了Disable/Enable Sort功能。不过也是用HeaderTemplate做界面实现。(突然发现Wordpress可以访问了)

没有找到一个满足我要求的实现方式,每个解决方案都只是关注于自己要解决的问题的那一个点上。当然在Blog里让示例简单一些也没有错。那就让我把他们所解决的问题集成到一个示例中。要求也不多。

1.       不影响现有功能。

2.       不独占现有属性。

3.       使用组合,而不是继承。

第一个方案,使用Adorner Layer是个很好的思路,Adorner Layer相当于一个画板,我画在这里,别的功能画在那里就是了,所以不会影响现有功能也不算独占现有属性。它的示例中占用了Tag来描述使用哪个属性排序。我们用Attached Property替换掉就可以了。然后就剩下一个问题了——不要画三角。我们想用Template。这样不同的地方的样子可以有不一样的界面效果而又不用修改代码。但是问题是Adorner是没有Template的。

参考了两篇关于Adorner Layer的文章。

1.       Adorners in WPF

2.       Visual Level Programming vs Logical Level Programming

写了一个晚上的代码,终于搞出一个自我感觉良好的实现出来。在ListView上添加Sort功能,只需要添加一个Attached Property就可以。代码如下。

<ListView ext:ListViewBehavior.HeaderSort="True"
ItemsSource="{Binding}">
<ListView.View>
<GridView>
<GridViewColumn Header="Name"
DisplayMemberBinding="{Binding ItemName}"
ext:ListViewBehavior.SortField="ItemName"/>
<GridViewColumn Header="Value"
DisplayMemberBinding="{Binding ItemValue}"
ext:ListViewBehavior.SortField="ItemValue"/>
</GridView>
</ListView.View>
</ListView>

在GridViewColumn中也使用Attached Property指定按哪一列排序。如果不指定,就默认使用Header的名称做为排序属性。

使用了Sheva的示例中的UIElementAdorner(略有改动)把一个自定义控件ListSortDecorator放在当前排序列上。代码如下。

using System.Collections;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media; namespace SortListView.Extention
{
public class UIElementAdorner : Adorner
{
private UIElement child; /// <summary>
///
/// </summary>
/// <param name="element"></param>
/// <param name="direction"></param>
public UIElementAdorner(UIElement element, UIElement child)
: base(element)
{
this.child = child;
AddLogicalChild(child);
AddVisualChild(child);
} protected override Size ArrangeOverride(Size finalSize)
{
child.Arrange(new Rect(finalSize)); return finalSize;
} protected override Size MeasureOverride(Size constraint)
{
child.Measure(constraint); return AdornedElement.RenderSize;
} protected override int VisualChildrenCount
{
get { return ; }
} protected override Visual GetVisualChild(int index)
{
return child;
} protected override IEnumerator LogicalChildren
{
get
{
ArrayList list = new ArrayList();
list.Add(child);
return (IEnumerator)list.GetEnumerator();
}
} /// <summary>
///
/// </summary>
public UIElement Child
{
get { return child; }
}
}
}

三角形的样子就可以由ListSortDecorator来定义了。默认的样子如下。

<ControlTemplate TargetType="{x:Type ext:ListSortDecorator}">
<Path x:Name="path" Data="M0,0L2,0 1,1z"
Fill="{TemplateBinding Foreground}"
Stroke="{TemplateBinding Foreground}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Width="" Height="" Stretch="Fill"/>
<ControlTemplate.Triggers>
<Trigger Property="SortDirection" Value="Descending">
<Setter TargetName="path" Property="Data" Value="M0,1L2,1L1,0Z"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

这样就可以方便地在Blend中绘制三角形的样子并制作动画了。显示效果如图所示。

图1. 界面效果

整个的示例代码可以从这里下载。错误之处,欢迎大家指正。

转载地址:http://www.cnblogs.com/nankezhishi/archive/2009/12/04/SortListView.html

[WPF]ListView点击列头排序功能实现的更多相关文章

  1. MFC listcontrol 分列 添加行数据 点击列头排序

    适用于 对话框程序 1.在工具箱中拖出 ListControl,然后右键-属性,view-Report 让你的ListControl变成这幅模样! 2.添加ListControl控件的control类 ...

  2. C++ 简单实现MFC ListControl 点击列头排序

    说明: SetItemData可以为每一行绑定一个DWORD类型的变量.用GetItemData可以获得这个变量.举个例子,假设CListCtrl中你需要显示某个数据表中的记录,该表有个流水号主键ID ...

  3. C# ListView点击列头进行排序

    /// <summary> /// This class is an implementation of the 'IComparer' interface. /// </summa ...

  4. MFC CListControl 点击列头排序的实现

    SetItemData可以为每一行绑定一个DWORD类型的变量.用GetItemData可以获得这个变量.举个例子,假设CListCtrl中你需要显示某个数据表中的记录,该表有个流水号主键ID,一般这 ...

  5. WPF DataGrid点击列头选择全列并具有背景色

    完成这个操作,主要是XAML的代码. 主要思路是通过绑定多路数据,在多路转换器中返回布尔值,在通过数据触发器来设置被选择的全列的背景色. XAML页面主要代码 首先定义DataGridCell < ...

  6. DataWindow.NET 控件 实现点击列头排序

    1.定义字段                         Boolean ib_SetSort = true;                string is_SortType = " ...

  7. easyui datagrid 点击列表头排序出现错乱的原因

    之前我的导师,也就是带我的同事,使用datagrid,发现点击列表头排序出现乱序,按理说只有顺序和逆序两种排序结果.因为他比较忙,当时没解决,把排序禁掉了,后来又要求一定要排序,所以他交给我. 一开始 ...

  8. datagridview 点击列标题排序

    开发winform中,平时经常用到数据列表,我们大多选用datagridview,但是此控件本身没有排序的功能.参阅网上资料.留下标记,以后备用. datagridview的数据显示一般是通过数据绑定 ...

  9. jqgrid 点击列头的超链接或按钮时,不触发列排序事件

    接上篇文章:jqgrid 将列头设置为超链接或按钮 如果在列头设置了超链接或按钮,在点击超链接或按钮时会触发列的排序事件. 原由:点击超链接/按钮会触发排序的冒泡事件 解决方法:点击超链接/按钮时,阻 ...

随机推荐

  1. MyEclipse8.5自动生成注册码

    package com; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamRe ...

  2. SVN取消记住密码

    百度上面找的,SVN取消记录密码的方法: 找到这个文件夹首先需要在文件夹选项里面,显示所有的文件和文件夹,不能隐藏. SVN取消记住用户名的方法 打开C:\Documents and Settings ...

  3. Qt修改文件内容

    在用Qt进行嵌入式开发的时候,有时需要通过界面永久的改变ip地址等网卡信息.此时只能修改系统中包含网卡信息的文件,下图红框中所示就是文件中的网卡信息. 那么如何修改这四行呢,我的做法是先打开该文本文件 ...

  4. jquery使用总结

    jquery使用总结-常用DOM操作 (1)查询或设置元素属性操作 html()   //获取匹配元素集合中的第1个元素 html(htmlString)  //为匹配集合中的所有元素设置内容 tex ...

  5. B/S 网站技术选型

    Windows平台: http://www.asp.net, http://www.asp.net/mvc Web技术 http://msdn.microsoft.com/ef 数据访问中间件 htt ...

  6. js网页返回页面顶部的小方法

    咳咳,在网页出现滚动条的时候,许多网站会在右下角出现一个图标,点击可以回到页面顶部 本文就记录下js实现代码: 1.在html页面body添加dom元素 <img src="toTop ...

  7. JUnit三分钟教程 ---- 实际应用

    JUnit三分钟教程 ---- 实际应用 摘自http://lavasoft.blog.51cto.com/62575/65775   接上文"JUnit三分钟教程 ---- 快速起步&qu ...

  8. 2016"百度之星" - 资格赛(Astar Round1) 1001

    思路:第一个做法就是:每读入起始位置i和结束位置j,就从这位置i到位置j计算,可是TLE了,后面我想想要是我输入一个最长的字符串,且以最大次数计算开始位置1到结束位置100000,那么这计算量是很大的 ...

  9. 数据库中的索引Index

    索引就像一本书的目录,而书中的索引是对一个词语的列表,其中注明了包含各个词的页码.数据库中的索引 是某一个表中一列或者若干列值的集合和相应的只想表中物理标识这些值的数据页的逻辑指针清单. 索引的作用: ...

  10. Live555 分析(二):服务端

    live555支持单播和组播,我们先分析单播的流媒体服务端,后面分析组播的流媒体服务端. 一.单播的流媒体服务端: // Create the RTSP server: RTSPServer* rts ...