重写ListView控件,实现点击列头排序的功能

.net中的ListView列表控件默认只能实现按第一列排序的功能,而且只能按字符串排序。由于项目需要重写了一个控件。继承自ListVIew,实现了能按每个列排序的功能,而且可以为每一列指定排序方式(数字,字符串,时间)。

完整代码如下:

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace UserControl
{
 /// <summary>
 /// UserControl1 的摘要说明。
 /// </summary>
 public class myListView : System.Windows.Forms.ListView
 {
  /// <summary>
  /// 必需的设计器变量。
  /// 控件说明:
  /// 此控件使用一个数组来保存每一列的排序方式。
  /// 使用时:当创建了控件的列后,要使用InitTypeList()函数来根据列数生成数组数据。默认值为0,按字符串排序
  /// 当有特殊要求时,可以指定相应列所对应的排序值。如typeList[3] = 2;
  /// </summary>
  private System.ComponentModel.Container components = null;
  
  [DllImport("User32")]
  private static extern bool LockWindowUpdate(IntPtr hWndLock);

  public ArrayList typeList; //存放每一列的排序方式 :0:字符串 1:数字 2:日期

  public myListView()
  {
   // 该调用是 Windows.Forms 窗体设计器所必需的。
   InitializeComponent();

   // TODO: 在 InitComponent 调用后添加任何初始化
   this.typeList = new ArrayList();

  }

  /// <summary>
  /// 清理所有正在使用的资源。
  /// </summary>
  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if( components != null )
     components.Dispose();
   }
   base.Dispose( disposing );
  }
  
  new public   void Clear()
  {
   base.Clear();
   this.typeList.Clear();
  }

  public void InitTypeList()
  {
   this.typeList.Clear();
   for(int i=0; i<this.Columns.Count; i++)
   {
    this.typeList.Add(0); //初始化数组
   }
  }

  #region 组件设计器生成的代码
  /// <summary>
  /// 设计器支持所需的方法 - 不要使用代码编辑器
  /// 修改此方法的内容。
  /// </summary>
  private void InitializeComponent()
  {
   components = new System.ComponentModel.Container();
  }
  #endregion


  protected override void OnColumnClick(ColumnClickEventArgs e)
  {
   base.OnColumnClick (e);
   
   LockWindowUpdate(this.Handle);
   
   this.BeginUpdate();
   ColumnSort columnsort = new ColumnSort(e.Column);

   
   columnsort.iSortTye = (int)this.typeList[e.Column];

   columnsort.bAscending = (this.Sorting == SortOrder.Ascending);
   if (columnsort.bAscending)
   {
    this.Sorting = SortOrder.Descending;
   }
   else
   {
    this.Sorting = SortOrder.Ascending;
   }
   
   this.ListViewItemSorter = columnsort;
   this.Sort();
   this.EndUpdate();

   LockWindowUpdate(IntPtr.Zero);

  }

  protected override void OnLeave(EventArgs e)
  {
   base.OnLeave (e);
  }

  new public void Dispose()
  {
   base.Dispose();
   this.typeList.Clear();
   this.typeList = null;
  }


  public class ColumnSort:IComparer
  {
   private int columnNum = 0;
   public bool bAscending  = true;
   public int iSortTye = 0; //排序方式:0:按字符串排序 1:按数字 2:按日期
   double iRes = 0.0;
   DateTime dTime1;
   DateTime dTime2;
   public ColumnSort(int column_to_sort)
   {
    columnNum = column_to_sort;
   }

   public int Compare(object a, object b)
   {
    System.Windows.Forms.ListViewItem listItemA = (System.Windows.Forms.ListViewItem)a;
    System.Windows.Forms.ListViewItem listItemB = (System.Windows.Forms.ListViewItem)b;
    
    if (bAscending)
    {
     
      if( (listItemA.SubItems[columnNum].Text == null || listItemA.SubItems[columnNum].Text.Trim() == String.Empty) && (listItemB.SubItems[columnNum].Text ==null || listItemB.SubItems[columnNum].Text.Trim() ==String.Empty) )
       return 0;
      if( (listItemA.SubItems[columnNum].Text == null || listItemA.SubItems[columnNum].Text.Trim() == String.Empty) && listItemB.SubItems[columnNum].Text != null)
       return -1;
      if(listItemA.SubItems[columnNum].Text != null && (listItemB.SubItems[columnNum].Text ==null || listItemB.SubItems[columnNum].Text.Trim() ==String.Empty) )
       return 1;
     if(this.iSortTye == 1)
     { //按数字
      iRes = double.Parse(listItemA.SubItems[columnNum].Text) - double.Parse( listItemB.SubItems[columnNum].Text);
      if(iRes < 0.0)
       return -1;
      else if(iRes > 0.0)
       return 1;
      else return 0;

     }
     else
      if(this.iSortTye == 2)
      { //按日期
      try
      {
       dTime1 = System.DateTime.Parse(listItemA.SubItems[columnNum].Text);
      }
      catch
      {
       dTime1 = new DateTime(1800,1,1,1,0,0,0);
      }
      
      try
      {
       dTime2 = System.DateTime.Parse(listItemB.SubItems[columnNum].Text);
      }
      catch
      {
       dTime2 = new DateTime(1800,1,1,1,0,0,0);
      }
      return System.DateTime.Compare(dTime1,dTime2);
      //return System.DateTime.Compare(System.DateTime.Parse(listItemA.SubItems[columnNum].Text), System.DateTime.Parse(listItemB.SubItems[columnNum].Text));
      }
      else
      {
       return String.Compare(listItemA.SubItems[columnNum].Text,listItemB.SubItems[columnNum].Text);
      }
    }
    else
    {
     if(listItemA.SubItems[columnNum].Text == null && listItemB.SubItems[columnNum].Text == null)
      return 0;
     if(listItemA.SubItems[columnNum].Text == null && listItemB.SubItems[columnNum].Text != null)
      return 1;
     if(listItemA.SubItems[columnNum].Text != null && listItemB.SubItems[columnNum].Text == null)
      return -1;

//
     if(this.iSortTye == 1)
     {
      iRes = double.Parse(listItemA.SubItems[columnNum].Text) - double.Parse( listItemB.SubItems[columnNum].Text);
      if(iRes < 0.0)
       return 1;
      else if(iRes > 0.0)
       return -1;
      else return 0;

     }
     else if(this.iSortTye == 2)
     {
      try
      {
       dTime1 = System.DateTime.Parse(listItemA.SubItems[columnNum].Text);
      }
      catch
      {
       dTime1 = new DateTime(1800,1,1,1,0,0,0);
      }
      
      try
      {
       dTime2 = System.DateTime.Parse(listItemB.SubItems[columnNum].Text);
      }
      catch
      {
       dTime2 = new DateTime(1800,1,1,1,0,0,0);
      }
      return -1 * System.DateTime.Compare(dTime1,dTime2);
//      return -1 * System.DateTime.Compare(System.DateTime.Parse(listItemA.SubItems[columnNum].Text), System.DateTime.Parse(listItemB.SubItems[columnNum].Text));
     }
     else
     {
      return -1 * String.Compare(listItemA.SubItems[columnNum].Text,listItemB.SubItems[columnNum].Text);
     }    
    }
   }
  }
 }
}

使用示例:

第一次使用时都不要忘记初始化

this.listView_clerk.InitTypeList();
   this.listView_clerk.typeList[9] = 2;//为第10列指定排序方式为日期
   this.listView_clerk.typeList[10] = 1;//排序方式为数字,其它列默认为按字符串排序
原文地址:https://www.cnblogs.com/zsyzsj/p/2002274.html