时隔上篇文章又是很长时间了,其实自己总是想着多纪录点东西,但是总是懒得去写。今天抽个空,分享一下我刚刚做的一个东东,欢迎波友们批评指正。。。
And Now , Let 's Start! Go Go Go !!!
Before,我们还是先预览一下效果图吧:
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
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
///
/// 对于按钮等事件
///
public
event
EventHandler
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(
|