(⊙WinForm⊙) 开发自定义的表格控件

时隔上篇文章又是很长时间了,其实自己总是想着多纪录点东西,但是总是懒得去写。今天抽个空,分享一下我刚刚做的一个东东,欢迎波友们批评指正。。。

  And Now , Let 's Start! Go Go Go !!!

  Before,我们还是先预览一下效果图吧:

     (⊙WinForm⊙) 开发自定义的表格控件_第1张图片

  First,如果你是一个winform开发人员,而且你们的产品明确要求不能使用三方控件,那么首先你需要蛋定~,至于怎麽蛋定,自己敲去。

  我们都晓得,在winform开发中,如果应用.net自带的那些控件的话有时候是很难满足我们的需求的。例如我们想做一个表格,那么我们会去用DataGridView,这个东东是个好东西,功能也特别的强大,其实我们完全可以去定制扩展它(前提是如果你非常熟悉他的话),但是往往有些效果就是那么的不自然,比如如果我想要像网页的表格一样,最后一列的操作项,根据不同的值放不同的按钮,又或者我一个单元格又要文字又要图片,怎么放? 我们需要定制扩展,但是DataGridView很复杂,扩展定制起来还是挺麻烦的,这里我就自定义了一个winform的表格iTable.

    Second,设计想法:

  1.使用TableLayoutPanel作为扩展对象,因为他提供了很好的表格形式。(其实也可以用ListView来扩展)

  2.表格需要表头,表头需要能有排序的功能,而且点击后应该有排序的小箭头。因此定制一种表头单元格控件。

  3.对于单元格我们的需要定制,一个单元格内有可能存放很多种内容,比如:纯文本、链接文本、图片、按钮等,这里分为三种:纯文本、链接文本和容器类(只要有容器,不管你放按钮       还是图片都可以)。

  4.对于一个表格,如何去设计,可以选择使用一行一行的设计,但这里使用列的形式。一个列中包含表头单元格样式和单元格样式。

  5.表格的列需要几种模式:Absolute、Percent、AutoSize。这里就是运用TableLayoutPanel的好处。  

  6.表格中的按钮,链接文本等能在点击时响应事件,并且能让我们知道触发者和响应的行信息。

  7.其他

    Third,代码:

@iCellStyle



using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Drawing;
using  System.Windows.Forms;
using  System.ComponentModel;
 
namespace  UserTableControlSurvey.UserComponent
{
     ///
     /// 单元格
     ///
     public  class  iCellStyle
     {
         #region "属性变量"
 
         //
         // 单元格内容类型
         //
         private  iCellContentType _contentType = iCellContentType.CONTAINER;
         //
         // 单元格内容对齐方式
         //
         private  ContentAlignment _textAlign = ContentAlignment.MiddleCenter;
         //
         // 单元格字体样式
         //
         private  Font _textFont = SystemFonts.DefaultFont;
         //
         // 高度
         //
         private  int  height = 20;
 
         #endregion
 
         #region "getter/setter"
 
         ///
         /// 高度
         ///
         public  int  Height
         {
             get
             {
                 return  this .height;
             }
             set
             {
                 this .height = value;
             }
         }
 
         ///
         /// 内容类型
         ///
         public  iCellContentType ContentType
         {
             get  { return  this ._contentType; }
             set  { this ._contentType = value; }
         }
 
         ///
         /// 文本对齐方式
         ///
         public  ContentAlignment TextAlign
         {
             get  { return  this ._textAlign; }
             set  { this ._textAlign = value; }
         }
 
         ///
         /// 文本字体
         ///
         public  Font TextFont
         {
             get  { return  this ._textFont; }
             set  { this ._textFont = value; }
         }
 
         #endregion
 
         public  iCellStyle()
         {
         }
 
         public  iCellStyle(iCellContentType contentType, ContentAlignment textAlign, Font txtFont)
             : this ()
         {
             this ._contentType = contentType;
             this ._textAlign = textAlign;
             this ._textFont = txtFont;
         }
 
     }
}

@iGridStyle

using  System;
using  System.Collections.Generic;
using  System.Text;
 
namespace  UserTableControlSurvey.UserComponent
{
     public  class  iGridStyle
     {
     }
 
     ///
     /// 单元格内容类型
     ///
     public  enum  iCellContentType
     {
         //
         // 纯文本
         //
         PLAIN_TEXT,
         //
         // 连接文本
         //
         LINK_TEXT,
         //
         // 容器,可以添加控件
         //
         CONTAINER
     }
 
     ///
     /// 排序方式
     ///
     public  enum  iCellSortArrow
     {
         //
         // 不排序
         //
         NONE,
         //
         // 按升序排序
         //
         ASC,
         //
         // 按降序排序
         //
         DESC
     }
}

@iHeaderCell

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Windows.Forms;
using  System.Drawing;
using  System.Drawing.Drawing2D;
 
namespace  UserTableControlSurvey.UserComponent
{
     ///
     /// 表头单元格
     ///
     public  class  iHeaderCell : UserControl
     {
         //
         // 默认排序方式为不排序
         //
         public  iCellSortArrow SortArrow = iCellSortArrow.NONE;
         //
         // 文本
         //
         private  string  text = string .Empty;
         //
         // 是否获取焦点
         //
         private  bool  IsFocusOn = false ;
         //
         // 鼠标经过颜色
         //
         protected  Color MouseOverColor = Color.SkyBlue;
         //
         // 是否允许排序
         //
         public  bool  IsAllowSort = true ;
 
         ///
         /// 文本
         ///
         public  override  string  Text
         {
             set  { this .text = value; }
             get  { return  this .text; }
         }
 
         ///
         /// 排序事件响应
         ///
         public  event  EventHandler Sorted;
 
         public  iHeaderCell()
         {
             this .Dock = DockStyle.Fill;
             this .AutoSize = true ;
             this .SetStyle(ControlStyles.UserPaint, true );
             this .SetStyle(ControlStyles.AllPaintingInWmPaint, true );
             this .SetStyle(ControlStyles.OptimizedDoubleBuffer, true );
             this .SetStyle(ControlStyles.ResizeRedraw, true );
 
             this .MouseHover += new  EventHandler(iHeaderCell_MouseHover);
             this .MouseLeave += new  EventHandler(iHeaderCell_MouseLeave);
             this .MouseClick += new  MouseEventHandler(iHeaderCell_MouseClick);
         }
 
 
         public  iHeaderCell( string  text, Font font, Color backColor, Color foreColor)
             : this ()
         {
             this .Init(text, font, backColor, foreColor);
         }
 
         public  iHeaderCell( string  text, string  name, Font font, Color backColor, Color foreColor)
             : this ()
         {
             this .Text = text;
             this .Name = name;
             this .Font = font;
             this .BackColor = backColor;
             this .ForeColor = foreColor;
         }
 
         public  void  Init( string  text, Font font, Color backColor, Color foreColor)
         {
             this .Text = text;
             this .Font = font;
             this .BackColor = backColor;
             this .ForeColor = foreColor;
         }
 
         #region "Events"
 
         private  void  iHeaderCell_MouseClick( object  sender, MouseEventArgs e)
         {
             if  ( this .IsAllowSort)
             {
                 if  ( this .SortArrow == iCellSortArrow.ASC)
                     this .SortArrow = iCellSortArrow.DESC;
                 else  this .SortArrow = iCellSortArrow.ASC;
                 this .Refresh();
                 this .OnSort();
             }
         }
 
         private  void  iHeaderCell_MouseLeave( object  sender, EventArgs e)
         {
             this .IsFocusOn = false ;
             this .Refresh();
         }
 
         private  void  iHeaderCell_MouseHover( object  sender, EventArgs e)
         {
             this .IsFocusOn = true ;
             this .Refresh();
         }
 
         protected  void  OnSort()
         {
             if  (Sorted != null )
                 Sorted( this , new  iHeaderSortEventArgs( this .Name, this .SortArrow));
         }
 
         #endregion
 
         #region "repaint"
 
         protected  override  void  OnPaintBackground(PaintEventArgs e)
         {
             base .OnPaintBackground(e);
 
             Graphics g = e.Graphics;
             Rectangle rect = e.ClipRectangle;
             Brush brush = new  SolidBrush( this .BackColor);
             if  (IsFocusOn)
                 brush = new  LinearGradientBrush(rect, Color.White, this .MouseOverColor, 90, true );
             g.FillRectangle(brush, rect);
         }
 
         protected  override  void  OnPaint(PaintEventArgs e)
         {
             base .OnPaint(e);
             
             Rectangle rect1 = e.ClipRectangle;
             Rectangle rect = new  Rectangle(rect1.Location.X +(rect1.Width- this .Width), rect1.Location.Y + (rect1.Height- this .Height), rect1.Width, rect1.Height);
             Graphics g = e.Graphics;
             SizeF size = g.MeasureString( this .text, this .Font);
             PointF point = this .GetPreferredSize(size, rect);
             g.DrawString( this .text, this .Font, new  SolidBrush(ForeColor), point);
             DrawSortArrow(g, size, rect, point);
         }
 
         protected  void  DrawSortArrow(Graphics g, SizeF size, Rectangle rect, PointF point)
         {
             float  triangleWidth = 10;
             float  triangleHeight = 6;
             float  offset = 5;
             float  x = point.X + size.Width + 5;
             float  y = point.Y;
             PointF[] points = new  PointF[3];
             switch  ( this .SortArrow)
             {
                 case  iCellSortArrow.ASC:
                     points[0] = new  PointF((rect.Location.X + rect.Width - offset - triangleWidth / 2), (rect.Height - triangleHeight) / 2);
                     points[1] = new  PointF((rect.Location.X + rect.Width - offset - triangleWidth), (rect.Height + triangleHeight) / 2);
                     points[2] = new  PointF((rect.Location.X + rect.Width - offset), (rect.Height + triangleHeight) / 2);
                     break ;
                 case  iCellSortArrow.DESC:
                     points[0] = new  PointF((rect.Location.X + rect.Width - offset - triangleWidth / 2), (rect.Height + triangleHeight) / 2);
                     points[1] = new  PointF((rect.Location.X + rect.Width - offset - triangleWidth), (rect.Height - triangleHeight) / 2);
                     points[2] = new  PointF((rect.Location.X + rect.Width - offset), (rect.Height - triangleHeight) / 2);
                     break ;
                 default : break ;
             }
             if  (points.Length > 0)
             {
                 g.FillPolygon(Brushes.SlateGray, points);
                 //g.DrawPolygon(Pens.SlateGray, points);
             }
         }
 
         //
         // Attention:在计算中间位置的时候使用this.Width 和this.Height,滚动的时候不会出错
         //
         protected  PointF GetPreferredSize(SizeF size, Rectangle rect)
         {
             PointF point = new  PointF();
             point.X = rect.Location.X + ( this .Width - size.Width) / 2;
             point.Y = rect.Location.Y + ( this .Height - size.Height) / 2;
             return  point;
         }
 
         #endregion
     }
}

.............................................. 有点多,还是把主要上码。

#关键部分,iTable源码

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Windows.Forms;
using  System.ComponentModel;
using  System.Data;
using  System.Drawing;
 
namespace  UserTableControlSurvey.UserComponent
{
 
     ///
     /// @author      : gxjiang
     /// @date        : 2011/4/21
     /// @description : 自定义表格控件
     ///
     public  class  iTable : TableLayoutPanel
     {
         //
         // 外部添加控件的委托
         //
         public  FunctionsAddHandler OuterFunctionsAdd;
         //
         // 表头的索引
         //
         private  const  int  INDEX_HEADER = 0;
         //
         // 保存表格的数据
         //
         private  DataTable _data;
         //
         // 列类型
         //
         private  iColumn[] _iColumns;
 
         ///
         /// 绑定的数据
         ///
         public  DataTable Data
         {
             get
             {
                 return  this ._data;
             }
             set
             {
                 this ._data = value;
                 this .ClearRows();
                 this .PrepareRows();
             }
         }
 
         ///
         /// 列样式定义集合
         ///
         [Browsable( true )]
         public  iColumn[] iColumns
         {
             get
             {
                 return  this ._iColumns;
             }
             set
             {
                 this ._iColumns = value;
                 this .InitializeColumnStyle();
                 this .SortedEventBinder();
             }
         }
 
         ///
         /// 排序事件响应
         ///
         public  event  EventHandler Sorted;
 
         ///
         /// 对于按钮等事件
         ///
         public  event  EventHandler Actioned;
 
         public  iTable()
         {
             //
             // 预处理一下
             //
             this .ColumnCount = 1;
             this .RowCount = 1;
             //
             // 设置一些方式
             //
             this .SetStyle(ControlStyles.UserPaint, true );
             this .SetStyle(ControlStyles.AllPaintingInWmPaint, true );
             this .SetStyle(ControlStyles.OptimizedDoubleBuffer, true );
             this .SetStyle(ControlStyles.ResizeRedraw, true );
             //
             // 默认给委托指向一个默认处理的方法
             //
             this .OuterFunctionsAdd = new  FunctionsAddHandler(DefaultOperationAddHandler);
             //this.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
 
         }
 
         private  void  iColumns_Sorted( object  sender, iHeaderSortEventArgs e)
         {
             //
             // 清除各个表头的排序箭头
             //
             foreach  (iColumn icon in  this ._iColumns)
             {
                 if  (e.Name != icon.Name)
                     icon.HeaderCell.SortArrow = iCellSortArrow.NONE;
             }
             //
             // 刷新,使得其他的表头的箭头去掉
             //
             this .Refresh();
             //
             // 对datatable进行排序
             //
             this ._data.DefaultView.Sort = e.Name + " "  + e.SortArrow;
             this ._data = this ._data.DefaultView.ToTable();
             //
             // 重新将数据刷新到界面
             //
             this .DataRebinding();
             //
             // 向外部抛出排序事件
             //
             //this.OnSort(e.Name, e.SortArrow);
         }
 
         //
         // 初始化表格的列
         //
         protected  void  InitializeColumnStyle()
         {
             this .ColumnCount = this .iColumns.Length;
             iColumn iCol;
             for  ( int  i = 0, len = this .iColumns.Length; i < len; i++)
             {
                 iCol = this .iColumns[i];
                 ColumnStyles.Add(

你可能感兴趣的:((⊙WinForm⊙) 开发自定义的表格控件)