2012-05-01 23:59:39|?次阅读|上传:wustguangh【已有?条评论】发表评论
这是OutlookGrid类的核心方法,实现了数据行的填充,与设置数据列一样,首先调用数据行Rows属性的Clear方法将数据行数据清空,然后根据groupingStyle是否为null判断是否启用数据分组功能。如果不使用数据分组功能,则根据数据模型中的数据行元素逐行创建DataGridViewCell对象的实例,并调用Rows属性的Add方法,增加到数据行即可。如果groupingStyle不等于null,则对数据模型中的数据行进行分组,遇到新的分组数据就增加一行分组概述行。
此外,OutlookGrid类还覆盖了响应鼠标单击、双击以及编辑事件的函数和排序函数,以便响应排序、分组的激励事件,这些都比较简单,不在此赘述。
OutlookGridRow类继承自DataGridViewRow,实现了数据行显示的相关功能,包括对分组行的特殊渲染方式,下面对其重要的成员方法进行介绍。
a. 判断鼠标事件是否在"+"、"-"图标区域
internal bool IsIconHit(DataGridViewCellMouseEventArgs e)
{
if (e.ColumnIndex < 0) return false;
OutlookGrid grid = (OutlookGrid)this.DataGridView;
Rectangle rowBounds = grid.GetRowDisplayRectangle(this.Index, false);
int x = e.X;
DataGridViewColumn c = grid.Columns[e.ColumnIndex];
if (this.isGroupRow &&
(c.DisplayIndex == 0) &&
(x > rowBounds.Left + 4) &&
(x < rowBounds.Left + 16) &&
(e.Y > rowBounds.Height - 18) &&
(e.Y < rowBounds.Height - 7))
return true;
return false;
//System.Diagnostics.Debug.WriteLine(e.ColumnIndex);
}
这个方法很简单,根据鼠标事件的DataGridViewCellMouseEventArgs类型参数判断鼠标事件对应的坐标是否在"+"、"-"图标的区域内部,并且返回对应的bool值。
b. 数据行的绘制函数
protected override void Paint(Graphics graphics,Rectangle clipBounds,
Rectangle rowBounds, int rowIndex, DataGridViewElementStates rowState,
bool isFirstDisplayedRow, bool isLastVisibleRow)
{
if (this.isGroupRow)
{
OutlookGrid grid = (OutlookGrid)this.DataGridView;
int rowHeadersWidth = grid.RowHeadersVisible ? grid.RowHeadersWidth : 0;
// this can be optimized
Brush brush = new SolidBrush(grid.DefaultCellStyle.BackColor);
Brush brush2 = new SolidBrush(Color.FromKnownColor(KnownColor.GradientActiveCaption));
int gridwidth = grid.Columns.GetColumnsWidth(DataGridViewElementStates.Displayed);
Rectangle rowBounds2 = grid.GetRowDisplayRectangle(this.Index, true);
// draw the background
graphics.FillRectangle(brush,
rowBounds.Left + rowHeadersWidth - grid.HorizontalScrollingOffset,
rowBounds.Top, gridwidth, rowBounds.Height - 1);
// draw text, using the current grid font
graphics.DrawString(group.Text, grid.Font, Brushes.Black,
rowHeadersWidth - grid.HorizontalScrollingOffset + 23, rowBounds.Bottom - 18);
//draw bottom line
graphics.FillRectangle(brush2,
rowBounds.Left + rowHeadersWidth - grid.HorizontalScrollingOffset,
rowBounds.Bottom - 2, gridwidth - 1, 2);
// draw right vertical bar
if (grid.CellBorderStyle == DataGridViewCellBorderStyle.SingleVertical
|| grid.CellBorderStyle == DataGridViewCellBorderStyle.Single)
graphics.FillRectangle(brush2,
rowBounds.Left + rowHeadersWidth - grid.HorizontalScrollingOffset + gridwidth - 1,
rowBounds.Top, 1, rowBounds.Height);
if (group.Collapsed)
{
if (grid.ExpandIcon != null)
graphics.DrawImage(grid.ExpandIcon,
rowBounds.Left + rowHeadersWidth - grid.HorizontalScrollingOffset + 4,
rowBounds.Bottom - 18, 11, 11);
}
else
{
if (grid.CollapseIcon != null)
graphics.DrawImage(grid.CollapseIcon,
rowBounds.Left + rowHeadersWidth - grid.HorizontalScrollingOffset + 4,
rowBounds.Bottom - 18, 11, 11);
}
brush.Dispose();
brush2.Dispose();
}
base.Paint(graphics, clipBounds, rowBounds, rowIndex, rowState, isFirstDisplayedRow, isLastVisibleRow);
}
对OutlookGridRow类的行绘制函数进行重写,如果是分组行,则调用自定义的绘制逻辑,包括对"+"、"-"图标的绘制,否则直接调用父类的绘制函数即可。
c. 单元格的绘制
protected override void PaintCells(Graphics graphics, Rectangle clipBounds,
Rectangle rowBounds, int rowIndex, DataGridViewElementStates rowState,
bool isFirstDisplayedRow, bool isLastVisibleRow, DataGridViewPaintParts paintParts)
{
if (!this.isGroupRow)
base.PaintCells(graphics, clipBounds, rowBounds, rowIndex, rowState,
isFirstDisplayedRow, isLastVisibleRow, paintParts);
}
如果不是分组行,则调用父类的PaintCells对单元格进行绘制,否则不需要绘制单元格。
3.3 DataSourceManager类的设计
DataSourceManager类主要用来对网格控件的数据模型进行管理,该类的一个核心方法是InitManager,该方法的完整定义如下:
private void InitManager()
{
if (dataSource is IListSource)
InitDataSet();
if (dataSource is IList)
InitList();
if (dataSource is OutlookGrid)
InitGrid();
}
该方法根据传入的dataSource类型调用不同的数据初始化方法初始化数据,下面分别对各方法进行介绍。
a. InitDataSet