public partial class HeaderUnitView : DataGridView
{
private TreeView[] _columnTreeView;
private ArrayList _columnList = new ArrayList();
private int _cellHeight = 17;
public int CellHeight
{
get { return _cellHeight; }
set { _cellHeight = value; }
}
private int _columnDeep = 1;
private bool HscrollRefresh = false;
/// <summary>
/// 水平滚动时是否刷新表头,数据较多时可能会闪烁,不刷新时可能显示错误
/// </summary>
[Description("水平滚动时是否刷新表头,数据较多时可能会闪烁,不刷新时可能显示错误")]
public bool RefreshAtHscroll
{
get { return HscrollRefresh; }
set { HscrollRefresh = value; }
}
/// <summary>
/// 构造函数
/// </summary>
public HeaderUnitView()
{
InitializeComponent();
this.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
//设置列高度显示模式
}
[Description("设置或获得合并表头树的深度")]
public int ColumnDeep
{
get
{
if (this.Columns.Count == 0)
_columnDeep = 1;
this.ColumnHeadersHeight = _cellHeight * _columnDeep;
return _columnDeep;
}
set
{
if (value < 1)
_columnDeep = 1;
else
_columnDeep = value;
this.ColumnHeadersHeight = _cellHeight * _columnDeep;
}
}
[Description("添加合并式单元格绘制的所需要的节点对象")]
public TreeView[] ColumnTreeView
{
get { return _columnTreeView; }
set
{
if (_columnTreeView != null)
{
for (int i = 0; i <= _columnTreeView.Length - 1; i++)
_columnTreeView[i].Dispose();
}
_columnTreeView = value;
}
}
[Description("设置添加的字段树的相关属性")]
public TreeView ColumnTreeViewNode
{
get { return _columnTreeView[0]; }
}
public ArrayList NadirColumnList
{
get
{
if (_columnTreeView == null)
return null;
if (_columnTreeView[0] == null)
return null;
if (_columnTreeView[0].Nodes == null)
return null;
if (_columnTreeView[0].Nodes.Count == 0)
return null;
_columnList.Clear();
GetNadirColumnNodes(_columnList, _columnTreeView[0].Nodes[0], false);
return _columnList;
}
}
///<summary>
///绘制合并表头
///</summary>
///<param name="node">合并表头节点</param>
///<param name="e">绘图参数集</param>
///<param name="level">结点深度</param>
///<remarks></remarks>
public void PaintUnitHeader(
TreeNode node,
System.Windows.Forms.DataGridViewCellPaintingEventArgs e,
int level)
{
//根节点时退出递归调用
if (level == 0)
return;
RectangleF uhRectangle;
int uhWidth;
SolidBrush gridBrush = new SolidBrush(this.GridColor);
SolidBrush backColorBrush = new SolidBrush(e.CellStyle.BackColor);
Pen gridLinePen = new Pen(gridBrush);
StringFormat textFormat = new StringFormat();
textFormat.Alignment = StringAlignment.Center;
uhWidth = GetUnitHeaderWidth(node);
if( node.Nodes.Count == 0)
{
uhRectangle = new Rectangle(e.CellBounds.Left,
e.CellBounds.Top + node.Level * _cellHeight,
uhWidth - 1,
_cellHeight * (_columnDeep - node.Level) - 1);
}
else
{
uhRectangle = new Rectangle(
e.CellBounds.Left,
e.CellBounds.Top + node.Level * _cellHeight,
uhWidth - 1,
_cellHeight - 1);
}
//画矩形
e.Graphics.FillRectangle(backColorBrush, uhRectangle);
//划底线
e.Graphics.DrawLine(gridLinePen
, uhRectangle.Left
, uhRectangle.Bottom
, uhRectangle.Right
, uhRectangle.Bottom);
//划右端线
e.Graphics.DrawLine(gridLinePen
, uhRectangle.Right
, uhRectangle.Top
, uhRectangle.Right
, uhRectangle.Bottom);
////写字段文本
e.Graphics.DrawString(node.Text, this.Font
, new SolidBrush(e.CellStyle.ForeColor)
, uhRectangle.Left + uhRectangle.Width / 2 -
e.Graphics.MeasureString(node.Text, this.Font).Width / 2 - 1
, uhRectangle.Top +
uhRectangle.Height / 2 - e.Graphics.MeasureString(node.Text, this.Font).Height / 2);
//Image img = new Bitmap((int)uhRectangle.Width, (int)uhRectangle.Height);
//Graphics g = Graphics.FromImage(img);
//g.FillRectangle(backColorBrush, uhRectangle);
//g.DrawLine(gridLinePen
// , uhRectangle.Left
// , uhRectangle.Bottom
// , uhRectangle.Right
// , uhRectangle.Bottom);
//g.DrawLine(gridLinePen
// , uhRectangle.Right
// , uhRectangle.Top
// , uhRectangle.Right
// , uhRectangle.Bottom);
//g.DrawString(node.Text, e.CellStyle.Font, new SolidBrush(e.CellStyle.ForeColor), uhRectangle.Left + uhRectangle.Width / 2 - g.MeasureString(node.Text, this.Font).Width / 2 - 1, uhRectangle.Top +
// uhRectangle.Height / 2 - g.MeasureString(node.Text, this.Font).Height / 2, textFormat);
//this.Rows[e.RowIndex].Cells[e.ColumnIndex].ValueType = typeof(Image);
//this.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = img;
////递归调用()
if (node.PrevNode == null)
if (node.Parent != null)
PaintUnitHeader(node.Parent, e, level - 1);
}
/// <summary>
/// 获得合并标题字段的宽度
/// </summary>
/// <param name="node">字段节点</param>
/// <returns>字段宽度</returns>
/// <remarks></remarks>
private int GetUnitHeaderWidth(TreeNode node)
{
//获得非最底层字段的宽度
int uhWidth = 0;
//获得最底层字段的宽度
if (node.Nodes == null)
return this.Columns[GetColumnListNodeIndex(node)].Width;
if (node.Nodes.Count == 0)
return this.Columns[GetColumnListNodeIndex(node)].Width;
for (int i = 0; i <= node.Nodes.Count - 1; i++)
{
uhWidth = uhWidth + GetUnitHeaderWidth(node.Nodes[i]);
}
return uhWidth;
}
/// <summary>
/// 获得底层字段索引
/// </summary>
///' <param name="node">底层字段节点</param>
/// <returns>索引</returns>
/// <remarks></remarks>
private int GetColumnListNodeIndex(TreeNode node)
{
for (int i = 0; i <= _columnList.Count - 1; i++)
{
if (((TreeNode)_columnList[i]).Equals(node))
return i;
}
return -1;
}
/// <summary>
/// 获得底层字段集合
/// </summary>
/// <param name="alList">底层字段集合</param>
/// <param name="node">字段节点</param>
/// <param name="checked">向上搜索与否</param>
/// <remarks></remarks>
private void GetNadirColumnNodes(
ArrayList alList,
TreeNode node,
Boolean isChecked)
{
if (isChecked == false)
{
if (node.FirstNode == null)
{
alList.Add(node);
if (node.NextNode != null)
{
GetNadirColumnNodes(alList, node.NextNode, false);
return;
}
if (node.Parent != null)
{
GetNadirColumnNodes(alList, node.Parent, true);
return;
}
}
else
{
if (node.FirstNode != null)
{
GetNadirColumnNodes(alList, node.FirstNode, false);
return;
}
}
}
else
{
if (node.FirstNode == null)
{
return;
}
else
{
if (node.NextNode != null)
{
GetNadirColumnNodes(alList, node.NextNode, false);
return;
}
if (node.Parent != null)
{
GetNadirColumnNodes(alList, node.Parent, true);
return;
}
}
}
}
/// <summary>
/// 滚动
/// </summary>
/// <param name="e"></param>
protected override void OnScroll(ScrollEventArgs e)
{
bool scrollDirection = (e.ScrollOrientation == ScrollOrientation.HorizontalScroll);
base.OnScroll(e);
if (RefreshAtHscroll && scrollDirection)
this.Refresh();
}
/// <summary>
/// 列宽度改变的重写
/// </summary>
/// <param name="e"></param>
protected override void OnColumnWidthChanged(DataGridViewColumnEventArgs e)
{
Graphics g=Graphics.FromHwnd(this.Handle);
float uwh=g.MeasureString(e.Column.HeaderText, this.Font).Width;
if (uwh >= e.Column.Width) { e.Column.Width = Convert.ToInt16(uwh);}
base.OnColumnWidthChanged(e);
}
/// <summary>
/// 单元格绘制(重写)
/// </summary>
/// <param name="e"></param>
/// <remarks></remarks>
protected override void OnCellPainting(System.Windows.Forms.DataGridViewCellPaintingEventArgs e)
{
try
{
//行标题不重写
if (e.ColumnIndex < 0)
{
base.OnCellPainting(e);
return;
}
if (_columnDeep == 1)
{
base.OnCellPainting(e);
return;
}
//绘制表头
if (e.RowIndex == -1)
{
if (e.ColumnIndex >= NadirColumnList.Count) { e.Handled = true; return; }
PaintUnitHeader((TreeNode)NadirColumnList[e.ColumnIndex]
, e
, _columnDeep);
e.Handled = true;
}
}
catch
{ }
}
}
网格:
public partial class RowUnitView : DataGridView
{
public RowUnitView()
{
InitializeComponent();
this.MultiSelect = true;
this.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
this.AllowUserToAddRows = false;
this.RowHeadersVisible = false;
this.ReadOnly = true;
}
private int i = 1;
private int count2 = 1;
private int flag;
string selectedValue;
protected override void OnPaint(PaintEventArgs pe)
{
// TODO: 在此处添加自定义绘制代码
// 调用基类 OnPaint
base.OnPaint(pe);
}
protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
{
try
{
DrawCell(e);
base.OnCellPainting(e);
}
catch
{ }
}
/// <summary>
/// 画单元格
/// </summary>
/// <param name="e"></param>
private void DrawCell(DataGridViewCellPaintingEventArgs e)
{
Brush gridBrush = new SolidBrush(this.GridColor);
SolidBrush backBrush = new SolidBrush(e.CellStyle.BackColor);
SolidBrush fontBrush = new SolidBrush(e.CellStyle.ForeColor);
int cellheight;
int fontheight;
int cellwidth;
int fontwidth;
int countU = 0;
int countD = 0;
int count = 0;
int totalheight = 0;
int heightU = 0;
int heightD = 0;
// 对第1,2列相同单元格进行合并
if ((e.ColumnIndex == 0 || e.ColumnIndex == 1) && e.RowIndex != -1)
{
// cellheight = e.CellBounds.Height;
// fontheight = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Height;
// cellwidth = e.CellBounds.Width;
// fontwidth = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Width;
// Pen gridLinePen = new Pen(gridBrush);
// string curValue = e.Value == null ? "" : e.Value.ToString().Trim();
// string curSelected = this.CurrentRow.Cells[0].Value == null ? "" : this.CurrentRow.Cells[0].Value.ToString().Trim();
// if (!string.IsNullOrEmpty(curValue))
// {
// for (int i = e.RowIndex; i < this.Rows.Count; i++)
// {
// if (this.Rows[i].Cells[0].Value.ToString().Equals(curValue))
// {
// this.Rows[i].Cells[0].Selected = this.Rows[e.RowIndex].Selected;
// this.Rows[i].Selected = this.Rows[e.RowIndex].Selected;
// countD++;
// heightD += this.Rows[i].Height;
// }
// else
// {
// break;
// }
// }
// for (int i = e.RowIndex; i >= 0; i--)
// {
// if (this.Rows[i].Cells[0].Value.ToString().Equals(curValue))
// {
// this.Rows[i].Cells[0].Selected = this.Rows[e.RowIndex].Selected;
// this.Rows[i].Selected = this.Rows[e.RowIndex].Selected;
// heightU += this.Rows[i].Height;
// countU++;
// }
// else
// {
// break;
// }
// }
// heightU = heightU - e.CellBounds.Height;
// totalheight = heightU + heightD;
// count = countD + countU -1;
// if (count < 2) { return; }
// }
// if (this.Rows[e.RowIndex].Selected)
// {
// backBrush.Color = e.CellStyle.SelectionBackColor;
// fontBrush.Color = e.CellStyle.SelectionForeColor;
// }
// e.Graphics.FillRectangle(backBrush, e.CellBounds); //new Rectangle(e.CellBounds.X,e.CellBounds.Y-(countU-1) * cellheight,cellwidth,cellheight*countU));
// //e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (countU - 1) + (cellheight * count - fontheight) / 2);
// e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - heightU + (totalheight - fontheight) / 2);
// if (countD == 1)
// {
// e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);
// //count = 0;
// }
// // 画右边线
// e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right-1 , e.CellBounds.Top, e.CellBounds.Right-1 , e.CellBounds.Bottom);
// e.Handled = true;
//}
//else if (e.ColumnIndex == 1 && e.RowIndex != -1)
//{
cellheight = e.CellBounds.Height;
fontheight = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Height;
cellwidth = e.CellBounds.Width;
fontwidth = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Width;
Pen gridLinePen = new Pen(gridBrush);
string curValue = this.Rows[e.RowIndex].Cells[0].Value == null ? "" : this.Rows[e.RowIndex].Cells[0].Value.ToString().Trim();
string curSelected = this.CurrentRow.Cells[0].Value == null ? "" : this.CurrentRow.Cells[0].Value.ToString().Trim();
if (!string.IsNullOrEmpty(curValue))
{
for (int i = e.RowIndex; i < this.Rows.Count; i++)
{
if (this.Rows[i].Cells[0].Value.ToString().Equals(curValue))
{
this.Rows[i].Cells[0].Selected = this.Rows[e.RowIndex].Selected;
this.Rows[i].Selected = this.Rows[e.RowIndex].Selected;
countD++;
heightD += this.Rows[i].Height;
}
else
{
break;
}
}
for (int i = e.RowIndex; i >= 0; i--)
{
if (this.Rows[i].Cells[0].Value.ToString().Equals(curValue))
{
this.Rows[i].Cells[0].Selected = this.Rows[e.RowIndex].Selected;
this.Rows[i].Selected = this.Rows[e.RowIndex].Selected;
heightU += this.Rows[i].Height;
countU++;
}
else
{
break;
}
}
heightU = heightU - e.CellBounds.Height;
totalheight = heightU + heightD;
count = countD + countU - 1;
if (count < 2) { return; }
}
if (this.Rows[e.RowIndex].Selected)
{
backBrush.Color = e.CellStyle.SelectionBackColor;
fontBrush.Color = e.CellStyle.SelectionForeColor;
}
e.Graphics.FillRectangle(backBrush, e.CellBounds); //new Rectangle(e.CellBounds.X,e.CellBounds.Y-(countU-1) * cellheight,cellwidth,cellheight*countU));
//e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (countU - 1) + (cellheight * count - fontheight) / 2);
string cellvalue = e.Value.ToString();
if (fontwidth > cellwidth)
{
for (int i = cellvalue.Length-1; i > 0; i--)
{
cellvalue = cellvalue.Substring(0, i);
fontwidth = (int)e.Graphics.MeasureString(cellvalue,e.CellStyle.Font).Width;
if (fontwidth <= cellwidth) break;
}
}
e.Graphics.DrawString(cellvalue, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - heightU + (totalheight - fontheight) / 2);
if (countD == 1)
{
e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);
//count = 0;
}
// 画右边线
e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right-1, e.CellBounds.Top, e.CellBounds.Right-1, e.CellBounds.Bottom);
if(e.ColumnIndex==0)e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left , e.CellBounds.Top, e.CellBounds.Left , e.CellBounds.Bottom);
//GraphicsPath mypath = new GraphicsPath();
//StringFormat sf = new StringFormat();
//sf.Alignment = StringAlignment.Center;
//mypath.AddString((string)e.Value, e.CellStyle.Font.FontFamily, (int)FontStyle.Regular, e.CellStyle.Font.Size * count, new PointF(e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - heightU + (totalheight - fontheight) / 2), sf);
//PointF[] pathpoints = mypath.PathPoints;
//byte[] pathbyte = mypath.PathTypes;
//e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
//e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
//e.Graphics.FillPath(fontBrush, mypath);
e.Handled = true;
}
//else
//{
// // 对第2列相同单元格进行合并
// if (e.ColumnIndex == 1 && e.RowIndex != -1)
// {
// h = e.CellBounds.Height;
// wh = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Height;
// using (Pen gridLinePen = new Pen(gridBrush))
// {
// // 清除单元格
// e.Graphics.FillRectangle(backBrush, e.CellBounds);
// // 画 Grid 边线(仅画单元格的底边线和右边线)
// //如果本行的港口画了一条底边线,则在当前的单元格画一条底边线,并填充数据
// if (flag == 1)
// {
// e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);
// e.Graphics.DrawString(e.Value == null ? "" : e.Value.ToString(), e.CellStyle.Font, Brushes.Black, e.CellBounds.X + 2, e.CellBounds.Y + h - (h * count2 - wh) / 2 - wh);
// count2 = 1;
// flag = 0;
// }
// else
// {
// count2 = count2 + 1;
// }
// // 画右边线
// e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom);
// }
// e.Handled = true;
// }
//}
}
protected override void OnSelectionChanged(EventArgs e)
{
try
{
base.OnSelectionChanged(e);
if (this.SelectedRows.Count < 1) return;
string curvalue = this.CurrentRow.Cells[0].Value.ToString();
foreach(DataGridViewRow dgvr in this.SelectedRows)
{
if (!dgvr.Cells[0].Value.ToString().Equals( curvalue))
{
dgvr.Selected = false;
}
}
}
catch { }
}
protected override void OnCellClick(DataGridViewCellEventArgs e)
{
base.OnCellClick(e);
if(e.RowIndex>-1)
this.Rows[e.RowIndex].Cells[0].Selected = true;
}
protected override void OnRowHeightChanged(DataGridViewRowEventArgs e)
{
Graphics g=Graphics.FromHwnd(this.Handle);
float fornheight = g.MeasureString(e.Row.Cells[0].Value.ToString(), e.Row.InheritedStyle.Font).Height;
if (e.Row.Height <= fornheight) e.Row.Height = (int)fornheight;
base.OnRowHeightChanged(e);
this.Refresh();
}
}