(一)、使用默认DataGridView
在上一篇中,小菜使用DataGridView控件来显示任务数据Tasks。用到的代码如下:
dgTasks.DataSource = _dataLayer.Tasks.DefaultView;
dgTasks为DataGridView控件。
效果如下图:
右边的dgTasks控件将强类型DataSet:DataSetTasks中的所有列都显示出来。因为这是默认情况。
(二)、使用默认DataGrid
vs2005的工具箱中只有DataGridView没有DataGrid,是不是就说DataGridView替代了DataGrid了。
那小菜在工具箱中找到DataGrid,那是不是说DataGrid替代DataGridView。
DataGridView可以替代DataGrid,一定是在哪些方面增强了。那是哪些地方呢?
如果你连DataGrid都没用过,也在相掺和说DataGridView替代DataGrid,那真该反思了。
上面的四句话,就是小菜从DataGrid说起的原因。
在vs2005中可以右击工具箱,选择项:
将这一项勾选,确定后在工具箱就会看到DataGrid控件了,和自定义控件的添加方式类似。
那我们就用DataGrid替换DataGridView来看看效果,如下图:
代码:
dgTasks.DataSource = _dataLayer.Tasks.DefaultView;
dgTasks为DataGrid控件。
主窗体中使用:
dgTasks.TableStyles.Add(MainFormDgStyle.GetStyle());
dgTasks.DataSource = _dataLayer.Tasks.DefaultView;
我们来分析下代码:
DataGrid->DataGridTableStyle->DataGridColumnStyle
DataGridTableStyle为DataGrid表格样式。
DataGridColumnStyle为DataGrid列样式,为抽象类。
DataGridTextBoxColumn(为DataGrid文本框列样式) 继承 DataGridColumnStyle
DataGridBoolColumn(为DataGrid单选框列样式) 继承 DataGridColumnStyle
所以下面的代码就很好理解了。
DataGridTextBoxColumn taskID =
new DataGridTextBoxColumn();
taskID.HeaderText =
"ID"; //列标头的文本
taskID.MappingName =
"TaskID"; //该列样式所映射到的数据成员名称
taskID.Width = 30; //列宽度
其它的都一样了。
dgTableStyle.GridColumnStyles.AddRange(
new DataGridColumnStyle[]{ taskID,priorityText,等等});
这是简单的把所定义的列样式添加到DataGrid表格样式中。
dgTableStyle.MappingName = TableName; //指定映射到数据源的名称
好了,继续我们的改进DataGrid控件。
我们希望默认情况下DataGrid中Date Created和Last Changed这两列不显示,不过经过定制可以显示出来。
这样我们可以修改代码将这两列的宽度暂时定为0,这样就可以暂时不显示出来,以后还有显示出来的机会。
DataGridTextBoxColumn dateCreated = new DataGridTextBoxColumn();
dateCreated.HeaderText = "Date Created";
dateCreated.MappingName = "DateCreated";
dateCreated.Width = 0;

DataGridTextBoxColumn dateModified = new DataGridTextBoxColumn();
dateModified.HeaderText = "Last Changed";
dateModified.MappingName = "DateModified";
dateModified.Width = 0;
(2)美化DataGrid
让DataGrid隔行显示背景色:
dgTableStyle.AlternatingBackColor = System.Drawing.Color.LemonChiffon;
运行效果如下图:
ID列左边的行标头,小菜并不想要,能去掉吗,当然。
dgTableStyle.RowHeadersVisible = false;
运行效果如下图:
去掉DataGrid的篮色鸡冠:
可以在dgTasks的属性窗口将CaptionVisible设为false
对应代码dgTasks.CaptionVisible = false;
运行效果如下:
从上图你可以看出,DataGrid默认使用DataGridTextBoxColumn做为列样式,所以默认是可编辑数据,最后一行白色可以允许你添加数据,
怎样才能禁止DataGrid添加删除修改呢?
在dgTasks的属性窗口将ReadOnly设为true
对应代码dgTasks.ReadOnly = true;
从图中你也可以看出,现在不能编辑,添加数据了,为灰色底框。
(3)自定义DataGrid列
新的需求出来了:Progress列是显示任务进度的,使用数字表示不够直观,让我们使用进度条来显示它。
如下图:
我们之前是使用:DataGridTextBoxColumn
DataGridTextBoxColumn progressText = new DataGridTextBoxColumn();
progressText.HeaderText = "Progress";
progressText.MappingName = "Progress";
progressText.Width = 55;
我们要自定义出进度条的效果,可以自定义类DataGridProgressBarColumn 继承 DataGridTextBoxColumn
为何不继承至DataGridColumnStyle呢?因为继承DataGridTextBoxColumn我们的工作将简化很多。这像写控件,你不会都想从Component继承吧,同理。
using System;
using System.Drawing;
using System.Windows.Forms;

namespace TaskVision


{
public class DataGridProgressBarColumn : System.Windows.Forms.DataGridTextBoxColumn

{
public DataGridProgressBarColumn(string headerText, string mappingName, int width)

{
base.HeaderText = headerText;
base.MappingName = mappingName;
base.Width = width;
}

protected override void Edit(CurrencyManager source, int rowNum, Rectangle bounds,
bool readOnly, string displayText, bool cellIsVisible)

{
//使单元格无法编辑
}

protected override void Paint(Graphics g, Rectangle bounds, CurrencyManager source,
int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)

{
int progressVal = (int)GetColumnValueAtRow(source, rowNum); //取得progress的值
float percentage = ((float)progressVal / 100.0f); //将progress除于100转为百份比
// if the current row is this row, draw the selection back color
if (this.DataGridTableStyle.DataGrid.CurrentRowIndex == rowNum)
g.FillRectangle(new SolidBrush(this.DataGridTableStyle.SelectionBackColor), bounds);
else
g.FillRectangle(backBrush, bounds);

if (percentage > 0.0)

{
// Draw the progress bar and the text
g.FillRectangle(new SolidBrush(Color.FromArgb(163, 189, 242)),bounds.X + 2,
bounds.Y + 2, Convert.ToInt32((percentage * bounds.Width - 4)),bounds.Height - 4);
g.DrawString(progressVal.ToString() + "%", this.DataGridTableStyle.DataGrid.Font,
foreBrush, bounds.X + 6, bounds.Y + 2);
}
else

{
// draw the text
if (this.DataGridTableStyle.DataGrid.CurrentRowIndex == rowNum)
g.DrawString(progressVal.ToString() + "%", this.DataGridTableStyle.DataGrid.Font,
new SolidBrush(this.DataGridTableStyle.SelectionForeColor),
bounds.X + 6, bounds.Y + 2);
else
g.DrawString(progressVal.ToString() + "%", this.DataGridTableStyle.DataGrid.Font,
foreBrush, bounds.X + 6, bounds.Y + 2);
}

}
}
}
修改为:
DataGridProgressBarColumn progressText = new DataGridProgressBarColumn("Progress", "Progress", 55);
代码并不复杂,我们可查询.net sdk2.0关于Paint的参数,注意是查询DataGridColumnStyle.Paint,为什么不是DataGridTextBoxColumn.Paint呢?因为我们想要得到更多的支持,像背景刷Brush backBrush, 前景刷Brush foreBrush。
还有就是Edit,也是使用DataGridColumnStyle.Edit,这样才能保证无法编辑。
DataGridColumnStyle.Paint参数如下:
g:要绘制到的 Graphics。
bounds:要在其中绘画的外围 Rectangle。
source:该列所属的
System.Windows.Forms.DataGrid 控件的
CurrencyManager。
rowNum:所引用的基础数据表中的行号。
backBrush:用于绘制背景色的 Brush。
foreBrush:用于绘制前景色的 Color。
alignToRight:一个值,它指示内容是否为右对齐。如果内容为右对齐,则为
true;否则为
false。
同样我们也不希望其它列可以编辑,因为灰色的底框太难看了,我们希望的效果如下图:
那我们就新建一个DataGridTextBoxColumn继承至DataGridTextBoxColumn
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

namespace TaskVision


{
public class DataGridTextBoxColumn : System.Windows.Forms.DataGridTextBoxColumn

{
public DataGridTextBoxColumn(string format, string headerText, string mappingName, int width)

{
base.Format = format;
base.HeaderText = headerText;
base.MappingName = mappingName;
base.Width = width;
}

protected override void Edit(System.Windows.Forms.CurrencyManager source, int rowNum,
System.Drawing.Rectangle bounds, bool isReadOnly, string instantText, bool cellIsVisible)

{
//使单元格无法编辑
}

protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle bounds,
System.Windows.Forms.CurrencyManager source, int rowNum, System.Drawing.Brush backBrush,
System.Drawing.Brush foreBrush, bool alignToRight)

{
object bVal = GetColumnValueAtRow(source, rowNum);

if (this.Format == "d") //日期格式

{
try

{
bVal = String.Format("{0:d}", Convert.ToDateTime(bVal));
}
catch

{
}
}

// if the current row is this row, draw the selection back color
if (this.DataGridTableStyle.DataGrid.CurrentRowIndex == rowNum)

{
g.FillRectangle(new SolidBrush(this.DataGridTableStyle.SelectionBackColor), bounds);
g.DrawString(Convert.ToString(bVal), this.DataGridTableStyle.DataGrid.Font,
new SolidBrush(this.DataGridTableStyle.SelectionForeColor), bounds.X + 2, bounds.Y + 2);
}
else

{
g.FillRectangle(backBrush, bounds);
g.DrawString(Convert.ToString(bVal), this.DataGridTableStyle.DataGrid.Font, foreBrush,
bounds.X + 2, bounds.Y + 2);
}
}
}
}

修改为
DataGridTextBoxColumn taskID = new DataGridTextBoxColumn(string.Empty, "ID", "TaskID", 30);
修改为
DataGridTextBoxColumn dateDue = new DataGridTextBoxColumn("d", "Due Date", "DateDue", 65);
DataDue为任务预计完成日期,如果超期,应该给于强调,比如让日期显示为红色。
我们可以修改DataGridTextBoxColumn来完成这个功能:
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

namespace TaskVision


{
public class DataGridTextBoxColumn : System.Windows.Forms.DataGridTextBoxColumn

{
private bool _isRedIfOverDue = false;

public DataGridTextBoxColumn(string format, string headerText, string mappingName, int width)

{
base.Format = format;
base.HeaderText = headerText;
base.MappingName = mappingName;
base.Width = width;
}

public DataGridTextBoxColumn(string format, string headerText, string mappingName,
int width, bool isRedIfOverDue)

{
base.Format = format;
base.HeaderText = headerText;
base.MappingName = mappingName;
base.Width = width;
this._isRedIfOverDue = isRedIfOverDue;
}

protected override void Edit(CurrencyManager source, int rowNum, Rectangle bounds,
bool readOnly, string displayText, bool cellIsVisible)

{
//使单元格无法编辑
}

protected override void Paint(Graphics g, Rectangle bounds, CurrencyManager source,
int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
