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