浅谈WinForm下ListView的扩展(一):单击列头实现排序
来源:互联网 发布:高通9008端口驱动下载 编辑:程序博客网 时间:2024/05/18 18:02
[C#][Windows Form]
我们在开发Windows Form 应用程序时,往往需要使用ListView控件——通过设置其View属性为Details——来显示列表形式的详细数据。遗憾的是,.NET自带的这个ListView控件并没有提供一些我们常用的功能,例如:单击列头实现文本升降序排序、滚动条滚动事件等等。 得益于.NET强大的面向对象的支持,我们可以继承ListView并加入我们想要实现的功能,从而实现ListView的扩展。 今天讨论一下在C#中如何实现“单击列头实现排序”的功能。部分参考http://msdn.microsoft.com/zh-cn/library/system.windows.forms.listview.listviewitemsorter.aspx 一、 知识准备 要实现排序功能,首先我们得了解ListView以及.NET本身自带的一些关于排序、比较方面的接口和对象的属性、方法或事件。 ListView.ListViewItemSorter 属性: 获取或设置用于控件的排序比较器。 该属性类型为System.Collections.IComparer,顾名思义,这是一个实现对象比较的接口,其中只定义了一个方法:int Compare(object x, object y);通过实现该方法来比较两个对象并返回比较结果。 二、 实现思路 我们知道,为ListViewItemSorter属性赋值后,则ListView自动调用Sort方法实现排序。 既然ListViewItemSorter的类型为System.Collections.IComparer,那么我们自定义一个类并实现IComparer接口,然后在列单击事件里面将该类的实例赋给ListViewItemSorter属性即可。需要说明的是,传入方法:int Compare(object x, object y)的参数x和y均是ListViewItem类型的对象。 三、 具体实现 1. 定义一个类ListViewEx继承于ListView。 public class ListViewEx : ListView 2. 在该类中定义一个私有类ListViewItemComparer,并且该类实现System.Collections.IComparer接口。 private class ListViewItemComparer : System.Collections.IComparer 3. 因为方法:int Compare(object x, object y)的参数x和y均是ListViewItem类型的对象,所以要实现某列的排序,就必须有该列的index值。我们通过构造函数传参的方式将列的index传入。 private int _column; public ListViewItemComparer(int column) { _column = column; } 4. 关键步骤1:实现int Compare(object x, object y)方法。 public int Compare(object x, object y) { return (string.Compare(((ListViewItem)x).SubItems[_column].Text, ((ListViewItem)y).SubItems[_column].Text)); } 5. 关键步骤2:重写(override)ListView的OnColumnClick方法。 protected override void OnColumnClick(ColumnClickEventArgs e) { base.OnColumnClick(e); this.ListViewItemSorter = new ListViewItemComparer(e.Column); } 6. 全部代码,这里省去VS自动生成的部分——InitializeComponent()。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text; using System.Windows.Forms; namespace ListViewExtand { public partial class ListViewEx : ListView { public ListViewEx() { InitializeComponent(); } public ListViewEx(IContainer container) { container.Add(this); InitializeComponent(); } protected override void OnColumnClick(ColumnClickEventArgs e) { base.OnColumnClick(e); this.ListViewItemSorter = new ListViewItemComparer(e.Column); } private class ListViewItemComparer : System.Collections.IComparer { private int _column; public ListViewItemComparer(int column) { this. _column = column; } #region IComparer Members public int Compare(object x, object y) { return (-string.Compare(((ListViewItem)x).SubItems[_column].Text, ((ListViewItem)y).SubItems[_column].Text)); } #endregion } } } 四、 缺陷及改进 可以发现,这样做出来的ListView扩展控件,在单击列头时始终是按照文本升序进行排序。我们需要是这样的实用功能:某列头单击一次按文本升序排序,再次单击则按降序排序。 那么现在就拿上面的半成品继续改进。相信有了以上的基础,这次改进会比较容易,只需要理清实现思路即可:某列头单击一次按文本升序排序后,应该能够存储当前该列排序的状态(即列索引index值、排序方向),以便在再次单击时,能够改变该列的排序状态从而实现重新排序。 1. 在私有类中增加2个属性int SortColumn和SortOrder Order,同时自定义构造函数public ListViewItemComparer(int column)和public ListViewItemComparer(int column, SortOrder sortOrder)。 public ListViewItemComparer() { this.SortColumn = 0; this.Order = SortOrder.None; } public ListViewItemComparer(int column) : this() { this.SortColumn = column; } public ListViewItemComparer(int column, SortOrder sortOrder) : this(column) { this.Order = sortOrder; } public int SortColumn { get; set; } public SortOrder Order { get; set; } 2. 重新实现int Compare(object x, object y)方法:当获知当前按升序排序时(根据属性Order),返回对象x和y的比较结果;否则若是按降序排序,则返回对象x和y的比较结果的相反数;再则返回0,表示不排序。 public int Compare(object x, object y) { int result = string.Compare(((ListViewItem)x).SubItems[this.SortColumn].Text, ((ListViewItem)y).SubItems[this.SortColumn].Text); if (this.Order == SortOrder.Ascending) { return result; } else if (this.Order == SortOrder.Descending) { return (-result); } else { return 0; } } 3. 在类ListViewEx中重新实现重写(override)ListView的OnColumnClick方法。 protected override void OnColumnClick(ColumnClickEventArgs e) { base.OnColumnClick(e); if (this.ListViewItemSorter == null) { this.ListViewItemSorter = new ListViewItemComparer(e.Column, SortOrder.Ascending); } else { ListViewItemComparer comparer = this.ListViewItemSorter as ListViewItemComparer; if (comparer.SortColumn == e.Column) { if (comparer.Order == SortOrder.Ascending) { comparer.Order = SortOrder.Descending; } else { comparer.Order = SortOrder.Ascending; } } else { comparer.SortColumn = e.Column; comparer.Order = SortOrder.Ascending; } //仅仅改变了ListViewItemSorter属性值,这里不会自动调用Sort()方法,需要显式指定执行Sort()方法实现排序。 this.Sort(); } } 4. 全部代码,这里省去VS自动生成的部分——InitializeComponent()。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text; using System.Windows.Forms; namespace ListViewExtand { public partial class ListViewEx : ListView { public ListViewEx() { InitializeComponent(); } public ListViewEx(IContainer container) { container.Add(this); InitializeComponent(); } protected override void OnColumnClick(ColumnClickEventArgs e) { base.OnColumnClick(e); if (this.ListViewItemSorter == null) { this.ListViewItemSorter = new ListViewItemComparer(e.Column, SortOrder.Ascending); } else { ListViewItemComparer comparer = this.ListViewItemSorter as ListViewItemComparer; if (comparer.SortColumn == e.Column) { if (comparer.Order == SortOrder.Ascending) { comparer.Order = SortOrder.Descending; } else { comparer.Order = SortOrder.Ascending; } } else { comparer.SortColumn = e.Column; comparer.Order = SortOrder.Ascending; } //仅仅改变了ListViewItemSorter属性值,这里不会自动调用Sort()方法,需要显式指定执行Sort()方法实现排序。 this.Sort(); } } private class ListViewItemComparer : System.Collections.IComparer { public ListViewItemComparer() { this.SortColumn = 0; this.Order = SortOrder.None; } public ListViewItemComparer(int column) : this() { this.SortColumn = column; } public ListViewItemComparer(int column, SortOrder sortOrder) : this(column) { this.Order = sortOrder; } public int SortColumn { get; set; } public SortOrder Order { get; set; } #region IComparer Members public int Compare(object x, object y) { int result = string.Compare(((ListViewItem)x).SubItems[this.SortColumn].Text, ((ListViewItem)y).SubItems[this.SortColumn].Text); if (this.Order == SortOrder.Ascending) { return result; } else if (this.Order == SortOrder.Descending) { return (-result); } else { return 0; } } #endregion } } } 五、 小结 只需按照以上方法,自定义一个类实现IComparer接口,并将其实例赋给ListView的属性即可完美实现“点击列头排序”。 终于写完了,不知读者看过后有何感想,是否还有需要该进的地方?比如说类ListViewItemComparer作为内部私有类这种处理方式的优缺点,等等欢迎讨论。
- 浅谈WinForm下ListView的扩展(一):单击列头实现排序
- 单击ListView 列表头实现排序
- 重写ListView控件,实现点击列头排序的功能
- ListView点击列头排序功能实现
- C# WinForm的ListView的列排序
- 单击ListView列标题实现项排序功能
- ListView点击列头排序
- ListView点击列头排序
- [WPF]ListView点击列头排序功能实现
- 实现listview控件report视图下任何列头的双向排序
- 实现listview控件report视图下任何列头的双向排序
- PB中单击列表框的列标题实现排序
- ListView点击列排序的实现
- C# ListView点击列头进行排序
- C# listview 点击列头排序
- Delphi listview 点击列头排序
- C# WinForm的ListView的排序,列标题包括排序三角形
- 单击数据窗口的列进行排序
- 网络犯罪开始针对小型企业
- 升级YUM导致YUM无法正常运行原来是由于tmprepo 插件
- excel導入sql server
- 今天注册了
- 在水晶报表中动态显示任意格式的图片
- 浅谈WinForm下ListView的扩展(一):单击列头实现排序
- EVERWOOD - brabra
- 东软 实习
- VS2005的word2003 VBA编程
- 结果集已耗尽
- Polish 之接收Fire按键
- WinCE控制面板添加应用程序
- DECIMAL 和CString 转换
- 关于构造函数构造默认对象加括号的疑惑