⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 listviewex.cs

📁 图书馆信息管理系统 Library Information Management System
💻 CS
字号:
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;
using System.Resources;
using System.Reflection;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
using System.Data ;
 
namespace Library.Class.GUI.ListViewEx
{
	#region Enumerations
	public enum SortedFormatType
	{
		String,
		Numeric,
		Date,
		Custom
	}
	public enum SortedDirection
	{
		Ascending,
		Descending
	}
	#endregion
	#region 事件处理定义...
	public delegate void ListViewExEventHandler(object sender, ListViewExEventArgs e);
	/// <summary>
	///在生成Listview 事件 需要的自定义参数。
	/// </summary>
	public class ListViewExEventArgs : EventArgs
	{
		private string mFiledName;
		private string mSubItemText;
  
		public ListViewExEventArgs(string pFieldName,string pSubItemText)
		{
			mFiledName = pFieldName;
			mSubItemText = pSubItemText;
		}
		#region Public 属性 ...
		public string SubItemText
		{
			get
			{
				return mSubItemText;
			}
			set
			{
				mSubItemText=value;
			}
		}
		#endregion Public 属性 ...
	}
	#endregion 事件处理定义...
	/// <summary>
	/// 继承ListView 并增加数据绑定和排序的功能
	/// </summary>
	[ToolboxItemFilter("System.Windows.Forms")]
	[ToolboxBitmap(typeof(ListViewEx),"ListViewEx.bmp")]
	public class ListViewEx : ListView
	{
		private DataSet mDataSouce;
		private int mKeyIndex = -1 ;
		private string mKeyName = "ID";
		private SortColumnType[] mColType;
		private ListViewSortManager mSortManager;
		private int mMaxRowCount = 1000;
		#region 事件处理相关...
		private ListViewExEventHandler mBeforAddCell;
		public event ListViewExEventHandler BeforAddCell 
		{
			add 
			{ 
				mBeforAddCell += value; 
			} 
			remove 
			{ 
				mBeforAddCell -= value; 
			}
		}
		private void FireBeforAddCell(ListViewExEventArgs e)
		{
			if (mBeforAddCell!= null) 
			{
				// 调用相应的委托代理
				mBeforAddCell(this, e);
			}
		}
		#endregion 事件处理相关...
		public ListViewEx()
		{      
			FullRowSelect = true;
			View = View.Details;
			this.CheckBoxes = true; 
		}
		//绑定DataSet 
		public DataSet DataSouce
		{
			set
			{
				mDataSouce = value;
				refresh();
			}
		}
		#region 创建 ListView 的表头和子项...
		private void refresh()
		{
			Debug.Assert(mDataSouce!=null,"显示ListView","显示ListView的时候不能设置一个空的DataSet!");
			createColumns() ;
			createListItem();
			//增加排序的处理
			mSortManager = new ListViewSortManager(this,mColType);
		}
		//创建 List Item 
		private void createListItem()
		{
			DataTable dt =  mDataSouce.Tables[0];
			if(this.Items.Count>0)
				this.Items.Clear();
			int colCount = dt.Columns.Count; 
			int curRowIndex = 0;
			foreach(DataRow dr in dt.Rows)
			{
				//目前设置最大值是1000,翻页处理以后再添加
				if(curRowIndex > MaxRowCount)
					break;
				//先增加Key 值列
				int itemIndex = 0;
				if( mKeyIndex ==0)
				{
					itemIndex =1;
				}
				string cellText = dr[itemIndex].ToString();
				ListViewExEventArgs arg = new ListViewExEventArgs( dt.Columns[itemIndex].ColumnName,cellText);
				FireBeforAddCell(arg);
				ListViewItem item = new ListViewItem(arg.SubItemText,0);
				//把Table 的行存在Item 的tag 属性中
				item.Tag = dr;
				for(int i=itemIndex ; i< mKeyIndex;i++)
				{
					cellText = dr[i].ToString();
					arg = new ListViewExEventArgs( dt.Columns[i].ColumnName,cellText);
					FireBeforAddCell(arg);
					item.SubItems.Add(arg.SubItemText);
				}
				for(int i=mKeyIndex +1;i<colCount ;i++)
				{
					cellText = dr[i].ToString();
					arg = new ListViewExEventArgs( dt.Columns[i].ColumnName,cellText);
					FireBeforAddCell(arg);
					item.SubItems.Add(arg.SubItemText);
				}
				curRowIndex ++;
				this.Items.Add(item) ; 
			}
		}
		//创建ListView的表头
		private void createColumns()
		{
			DataTable dt =  mDataSouce.Tables[0];
			if(Columns.Count > 0)
				Columns.Clear();
			int i = 0;
			mColType = new SortColumnType[dt.Columns.Count];
			foreach(DataColumn dc in dt.Columns)
			{
				//HorizontalAlignment.Left
				//得到该Table 中是否有内置的Key Index 并得到它
				if(i!=mKeyIndex)
				{
					if(dc.ColumnName.ToUpper()  == mKeyName)
					{
						//this.Columns.Add(dc.Caption, 0,getAlignment(dc,i));
						mKeyIndex = i;
					}
					else
					{
						this.Columns.Add(dc.Caption,100,getAlignment(dc,i));
					}
				}
				i++;
			}
		}
		//得到列的文本的对齐方式
		private HorizontalAlignment getAlignment(DataColumn pDc,int pColIndex)
		{
			switch(pDc.GetType().Name)
			{
				case "String":
					mColType[pColIndex] = SortColumnType.Text ;
					return HorizontalAlignment.Left;
				case "Int16" :
				case "Int32" :
				case "Decimal":
					mColType[pColIndex] = SortColumnType.Number;
					return HorizontalAlignment.Right;
				case "DateTime" :
					mColType[pColIndex] = SortColumnType.DateTime;
					return HorizontalAlignment.Left;
				default:
					mColType[pColIndex] = SortColumnType.Text ;
					return HorizontalAlignment.Left;
			}
		}
		#endregion 创建 ListView 的表头和子项...
		#region Public 属性 ...
		public int KeyIndex
		{
			get
			{
				return mKeyIndex;
			}
			set
			{
				mKeyIndex = value;
			}
		}
		public string KeyName
		{
			get
			{
				return mKeyName;
			}
			set
			{
				mKeyName = value;
			}
		}
		public int MaxRowCount
		{
			get
			{
				return mMaxRowCount;
			}
			set
			{
				mMaxRowCount = value;
			}
		}
		#endregion Public 属性 ...
	}

	#region  ListViewSortManager ...
	enum SortColumnType
	{
		Text,
		Number,
		DateTime
	}
	/// <summary>
	/// 继承IComparer接口,提供两个文本之间的比较方法
	/// </summary>
	class ListViewTextSort: IComparer
	{
		private SortColumnType mType;
		private Int32 mColumn;
		private Boolean mAscending;
		public  SortColumnType CompareType
		{
			set
			{
				mType = value;
			}
		}
		public ListViewTextSort(Int32 sortColumn, Boolean ascending)
		{
			mColumn = sortColumn;
			mAscending = ascending;
		}
		/// <summary>
		/// 实现IComparer.Compare
		/// </summary>
		/// <param name="lhs">比较的第一个对象</param>
		/// <param name="rhs">比较的第二个对象</param>
		/// <returns>  如果lhs 小于 rhs那么小于零,否则大于零,或者等于零</returns>
		public Int32 Compare(Object lhs, Object rhs)
		{
			ListViewItem lhsLvi = lhs as ListViewItem;
			ListViewItem rhsLvi = rhs as ListViewItem;
			if(lhsLvi == null || rhsLvi == null)   
				return 0;
			ListViewItem.ListViewSubItemCollection lhsItems = lhsLvi.SubItems;
			ListViewItem.ListViewSubItemCollection rhsItems = rhsLvi.SubItems;
			String lhsText = (lhsItems.Count > mColumn) ? lhsItems[mColumn].Text : String.Empty;
			String rhsText = (rhsItems.Count > mColumn) ? rhsItems[mColumn].Text : String.Empty;
			Int32 result = 0;
			if(lhsText.Length == 0 || rhsText.Length == 0)
				result = lhsText.CompareTo(rhsText);
			else
				result = OnCompare(lhsText, rhsText);
			if(!mAscending)
				result = -result;
			return result;
		}
		/// <summary>
		/// 覆盖进行特别类型的比较
		/// </summary>
		/// <param name="lhs">比较的第一个对象</param>
		/// <param name="rhs">比较的第二个对象</param>
		/// <returns>  如果lhs 小于 rhs那么小于零,否则大于零,或者等于零</returns>
		protected virtual Int32 OnCompare(String lhs, String rhs)
		{
			switch(mType)
			{
				case SortColumnType.Text :
					return String.Compare(lhs, rhs, false);
				case SortColumnType.Number :
					Double result = Double.Parse(lhs) - Double.Parse(rhs);
					if(result > 0)
						return 1;
					else if(result < 0)
						return -1;
					else
						return 0;
				case SortColumnType.DateTime :
					return DateTime.Parse(lhs).CompareTo(DateTime.Parse(rhs));
				default :
					return String.Compare(lhs, rhs, false);
			}
		}
	}
	/// <summary>
	/// 和ListViewEx分离,实现列排序的管理
	/// </summary>
	class ListViewSortManager
	{
		private Int32 mColumn;
		private SortOrder mSortOrder;
		private ListViewEx mList;
		private SortColumnType[] mComparers;
		private ImageList mImgList;
		/// <param name="list">管理列排序的ListViewEx对象</param>
		/// <param name="comparers">对应每一列排序的类型</param>
		public ListViewSortManager(ListViewEx list, SortColumnType[] comparers)
		{
			mColumn = -1;
			mSortOrder = SortOrder.None;
			mList = list;
			mComparers = comparers;
			mImgList = new ImageList();
			mImgList.ImageSize = new Size(8, 8);
			mImgList.TransparentColor = System.Drawing.Color.Magenta;
			mImgList.Images.Add(GetArrowBitmap(ListSortDirection.Ascending));   
			mImgList.Images.Add(GetArrowBitmap(ListSortDirection.Descending));   
			SetHeaderImageList(mList, mImgList);
			list.ColumnClick += new ColumnClickEventHandler(ColumnClick);
		}
		/// <summary>
		/// 当前排序的列的Index
		/// </summary>
		public Int32 Column
		{
			get { return mColumn; }
		}
		/// <summary>
		/// 当前排序的方式
		/// </summary>
		public SortOrder SortOrder
		{
			get { return mSortOrder; }
		}
		/// <summary>
		/// 排序行
		/// </summary>
		public void Sort(Int32 column)
		{
			SortOrder order = SortOrder.Ascending;
   
			if(column == mColumn)
				order = (mSortOrder == SortOrder.Ascending) ? SortOrder.Descending : SortOrder.Ascending;
			Sort(column, order);
		}
		public void Sort(Int32 column, SortOrder order)
		{
			if(column < 0 || column >= mComparers.Length)
				throw new IndexOutOfRangeException();
			if(column != mColumn)
			{
				ShowHeaderIcon(mList, mColumn, SortOrder.None);
				mColumn = column;
			}
			ShowHeaderIcon(mList, mColumn, order);
			mSortOrder = order;
			if(order != SortOrder.None)
			{
				ListViewTextSort comp = new ListViewTextSort(mColumn, order == SortOrder.Ascending);//(ListViewTextSort) Activator.CreateInstance(mComparers[mColumn], new Object[] { mColumn, order == SortOrder.Ascending } );
				comp.CompareType = mComparers[mColumn]; 
				mList.ListViewItemSorter = comp;
			}
		}
		//当Click ListViewEx列标题时,得到它的事件,并进行排序的处理
		private void ColumnClick(object sender, ColumnClickEventArgs e)
		{
			this.Sort(e.Column);        
		}

		#region Graphics
		//画向下或者向上的方向箭头
		Bitmap GetArrowBitmap(ListSortDirection  type)
		{
			Bitmap bmp = new Bitmap(8, 8);
			Graphics gfx = Graphics.FromImage(bmp);
			Pen lightPen = SystemPens.ControlLightLight;
			Pen shadowPen = SystemPens.ControlDark;
			gfx.FillRectangle(System.Drawing.Brushes.Magenta, 0, 0, 8, 8);
			if(type == ListSortDirection.Ascending)  
			{
				gfx.DrawLine(lightPen, 0, 7, 7, 7);
				gfx.DrawLine(lightPen, 7, 7, 4, 0);
				gfx.DrawLine(shadowPen, 3, 0, 0, 7);
			}
			else if(type == ListSortDirection.Descending)
			{
				gfx.DrawLine(lightPen, 4, 7, 7, 0);
				gfx.DrawLine(shadowPen, 3, 7, 0, 0);
				gfx.DrawLine(shadowPen, 0, 0, 7, 0);
			}
   
			gfx.Dispose();
			return bmp;
		}
		#region WIndows32 API...
		[StructLayout(LayoutKind.Sequential)]
			private struct HDITEM 
		{
			public Int32     mask; 
			public Int32     cxy;  
			[MarshalAs(UnmanagedType.LPTStr)] 
			public String    pszText; 
			public IntPtr  hbm; 
			public Int32     cchTextMax; 
			public Int32     fmt; 
			public Int32     lParam; 
			public Int32     iImage;
			public Int32     iOrder;
		};
		[DllImport("user32")]
		static extern IntPtr SendMessage(IntPtr Handle, Int32 msg, IntPtr wParam, IntPtr lParam);
		[DllImport("user32", EntryPoint="SendMessage")]
		static extern IntPtr SendMessage2(IntPtr Handle, Int32 msg, IntPtr wParam, ref HDITEM lParam);
		const Int32 HDI_WIDTH   = 0x0001;
		const Int32 HDI_HEIGHT   = HDI_WIDTH;
		const Int32 HDI_TEXT   = 0x0002;
		const Int32 HDI_FORMAT   = 0x0004;
		const Int32 HDI_LPARAM   = 0x0008;
		const Int32 HDI_BITMAP   = 0x0010;
		const Int32 HDI_IMAGE   = 0x0020;
		const Int32 HDI_DI_SETITEM  = 0x0040;
		const Int32 HDI_ORDER   = 0x0080;
		const Int32 HDI_FILTER   = 0x0100;  // 0x0500
		const Int32 HDF_LEFT   = 0x0000;
		const Int32 HDF_RIGHT   = 0x0001;
		const Int32 HDF_CENTER   = 0x0002;
		const Int32 HDF_JUSTIFYMASK  = 0x0003;
		const Int32 HDF_RTLREADING  = 0x0004;
		const Int32 HDF_OWNERDRAW  = 0x8000;
		const Int32 HDF_STRING   = 0x4000;
		const Int32 HDF_BITMAP   = 0x2000;
		const Int32 HDF_BITMAP_ON_RIGHT = 0x1000;
		const Int32 HDF_IMAGE   = 0x0800;
		const Int32 HDF_SORTUP   = 0x0400;  // 0x0501
		const Int32 HDF_SORTDOWN  = 0x0200;  // 0x0501
		const Int32 LVM_FIRST           = 0x1000;  // List 消息
		const Int32 LVM_GETHEADER  = LVM_FIRST + 31;
		const Int32 HDM_FIRST           = 0x1200;  // Header 消息
		const Int32 HDM_SETIMAGELIST = HDM_FIRST + 8;
		const Int32 HDM_GETIMAGELIST    = HDM_FIRST + 9;
		const Int32 HDM_GETITEM   = HDM_FIRST + 11;
		const Int32 HDM_SETITEM   = HDM_FIRST + 12;
		#endregion WIndows32 API...
		//显示Header的图标
		private void ShowHeaderIcon(ListView list, int columnIndex, SortOrder sortOrder)
		{
			if(columnIndex < 0 || columnIndex >= list.Columns.Count)
				return;
			IntPtr hHeader = SendMessage(list.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
			ColumnHeader colHdr = list.Columns[columnIndex];
			HDITEM hd = new HDITEM();
			hd.mask = HDI_IMAGE | HDI_FORMAT;
			HorizontalAlignment align = colHdr.TextAlign;
			if(align == HorizontalAlignment.Left)
				hd.fmt = HDF_LEFT | HDF_STRING | HDF_BITMAP_ON_RIGHT;
			else if(align == HorizontalAlignment.Center)
				hd.fmt = HDF_CENTER | HDF_STRING | HDF_BITMAP_ON_RIGHT;
			else // HorizontalAlignment.Right
				hd.fmt = HDF_RIGHT | HDF_STRING;
			if(sortOrder != SortOrder.None)
				hd.fmt |= HDF_IMAGE;
			hd.iImage = (int) sortOrder - 1;
			SendMessage2(hHeader, HDM_SETITEM, new IntPtr(columnIndex), ref hd);
		}
		private void SetHeaderImageList(ListView list, ImageList imgList)
		{
			IntPtr hHeader = SendMessage(list.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);
			SendMessage(hHeader, HDM_SETIMAGELIST, IntPtr.Zero, imgList.Handle);
		}
		#endregion Graphics
	}
	#endregion  ListViewSortManager ...
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -