主题:  WINFORM的Datagrid探讨

蓝鲸

职务:版主
等级:5
金币:42.1
发贴:2614
#12004/9/19 12:03:20
想讨论的组件为.NET中System.Windows.Forms.DataGrid控件,不是ASP.NET的那个。System.Windows.Forms.DataGrid下面就简称DataGrid,是个令人困惑的控件。该控件功能非常强大,但却很难使用。
最近我在用DataGrid作为一个数据添加工具,比如销售,一次销售不可能是一件商品,所以要等商品全部列项后,成批更新。本想自己开发一个组件,类似于表格,但后来取消了这念头,原因是DataGrid很强大,并且于DataSet或DataView能联结在一起。但是DataGrid真的很难使用,很多问题真是令人摸不着头脑。比如明明是用关某一网格的值,但是结果得不到,但换种方法,用数据源(如DataTable),所对应的值,结果是正确的。有时不得不怀疑网格与数据源的同步性,或者一些微小细节,使数据源和网格数据存在差异。
另一个困惑的事,是DataGrid的鼠标键盘事件非常难控制,网上有关于双击事件的介绍等。你按普通方法去做,但确不会触发该事件,原因是你第一次单击时,焦点已落在网格内,而网格又属于一子组件(如DataGridTextBoxColumn类),所以第二次单击并不能触发。再如KeyDown、KeyPress等,如果没些耐心的话,我想等你听完音乐,放松后再来吧,否则你会吐血的。但这些恰恰是这个控能发挥威力的关键东西。比如,我在一网格内输入数量或单价,而旁边网格的小计值是要实时自动更新的。
为了这个功能,我差点一次又一次放弃,打完游戏再来干,然后以失望,再打游戏,再做。现在功能可以实现了。但还是没把问题的根结找出来,也不能保证程序的健壮,但总之能实现了。为什么要这样做,原因很简单,使用者不会管你怎样编程的,也不会考虑这编程的难度,在他们想来,这个功能是轻而易举的。
原本,自己做过一小组件,实现较容易。但考虑以后的升级问题,并且在升级中要发挥ADO+的强大威力,所以这小组件丢掉了。

各位不要吓怕了,如果你了解这个控件,真的有心理准备,或者等微软下个版本。

以下我暂时放弃这可怕的编程,来些轻松的。是个小软件件,单位要求大气日报能实现一些手动控制,比如能实现删除一些异常值。有时一些人为的因素,影响值能够删除。以SO2为例。该数据是自动仪中记录的,它每分种均记录一次。日报先要出来小时平均值,然后删除可疑值,再平均出来一日均值,数据库如下:


非常大鱼

蓝鲸

职务:版主
等级:5
金币:42.1
发贴:2614
#22004/9/19 12:07:52

图片如下:


以下是软件的界面。我吃饭去了,空了再写
图片如下:


非常大鱼

蓝鲸

职务:版主
等级:5
金币:42.1
发贴:2614
#32004/9/19 19:50:52
下面就来看看如何用这个DataGrid。以上这个实例用到的DataGrid一些简单功能,并没有高深的东西。只是这个“有效”字段是手动添加的。
原本我想用这样方法:
sql = " SELECT A, True as 有效 FROM Table";
OleDbConnection DBConn = new OleDbConnection(...);
OleDbDataAdapter DBAdapter = new OleDbDataAdapter(sql,DBConn);
DBAdapter.Fill(DataSet1, "SO2");
DataGrid1.DataSource = DataSet1.Tables["SO2"];
但结果没有出现想要的效果,在“有效”格里只是显示"True"。

以下是实现过程:
(1)实现SQL查询,计算每个小时的平均值。要查询的时间是从昨日的12:00到今天的11:59:59。

用时间控件,df为起始时间,dw为终止日间
dw = "#" + datSO2.Value.Date.ToString("yyyy-MM-dd") + " 11:59:59#";
df = "#" + datSO2.Value.Date.AddDays(-1).ToString("yyyy-MM-dd") + " 12:00:00#";


SQL查询语句
sql = "SELECT DatePart('h',DataTime) AS 时段 "
	+ ",AVG(DataValue) AS 小时平均值 "
	+ "FROM SO2MinData "
	+ "WHERE DataTime BETWEEN " + df + " AND " + dw + " "
	+ "GROUP BY DatePart('h',DataTime)";


最后填充DataSet
DBAdapter = new OleDbDataAdapter(sql,DBConn);
DBDataSet.Tables["SO2"].Clear();
DBAdapter.Fill(DBDataSet, "SO2");


接下来就是小小技巧,在Table中增加一列
DBDataSet.Tables["SO2"].Columns.Add("有效",System.Type.GetType("System.Boolean"));
grdSO2.DataSource = DBDataSet.Tables["SO2"];


最后不讨论一些计算等代码了,程序没有什么复杂,开个小头。

编辑历史:[此帖最近一次被 蓝鲸 编辑过(编辑时间:2004-09-19 20:03:18)]

非常大鱼

蓝鲸

职务:版主
等级:5
金币:42.1
发贴:2614
#42004/9/19 19:58:27
开始,想试着对DataGrid作些进一步了解了。初用DataGrid控件,觉得DataGrid列的大小都是一样大小,不容易定制。但DataGrid中的网格也正象网页上的一些Styles,可能自由控制。先看一下界面。

图片如下:


以上界面用到了表格的风格类DataGridTableStyle,及列的类GridColumnStylesCollection
下面进一步讨论。

编辑历史:[此帖最近一次被 蓝鲸 编辑过(编辑时间:2004-09-19 20:15:04)]

非常大鱼

蓝鲸

职务:版主
等级:5
金币:42.1
发贴:2614
#52004/9/19 20:21:00
以下是实现代码,可进一步在VS.NET帮助中了解这两个类的详细
	/// <summary>
	/// 建立grdRecord及grdDetai样式
	/// </summary>
	public void SetDataGrideStyle()
	{
		DataGridTableStyle grdRecordStyle = new DataGridTableStyle();
		if(!grdRecord.TableStyles.Contains("Record"))
		{
		//设置表格总体风格
		grdRecordStyle.MappingName = "Record";
		grdRecord.TableStyles.Add(grdRecordStyle);
		grdRecordStyle.RowHeadersVisible = true;
		grdRecordStyle.HeaderBackColor = Color.FromArgb(249, 249, 251);
		grdRecordStyle.AllowSorting = false;
		grdRecordStyle.RowHeadersVisible = true;
		grdRecordStyle.HeaderForeColor = SystemColors.WindowText;
		grdRecordStyle.HeaderFont = new System.Drawing.Font("宋体", 9F, 
			System.Drawing.FontStyle.Regular, 
			System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
		grdRecordStyle.GridLineColor = Color.FromArgb(222, 222, 224);
		grdRecordStyle.PreferredRowHeight = 22;
		grdRecordStyle.SelectionBackColor = Color.Lavender;
		grdRecordStyle.SelectionForeColor = SystemColors.WindowText;
		grdDetail.BackgroundColor = Color.White; 

		//设置列的宽度 
		GridColumnStylesCollection colRecordStyle = grdRecord.TableStyles[0].GridColumnStyles;
			colRecordStyle[0].HeaderText = "ID";
			colRecordStyle[0].Width = 0;
			colRecordStyle[1].HeaderText = "单号";
			colRecordStyle[1].Width = 75;
			colRecordStyle[2].HeaderText = "原始凭证号";
			colRecordStyle[2].Width = 75;
			colRecordStyle[3].HeaderText = "付款方式";
			colRecordStyle[3].Width = 55;
			colRecordStyle[3].Alignment = HorizontalAlignment.Center;
			colRecordStyle[4].HeaderText = "应付款";
			colRecordStyle[4].Width = 65;
			colRecordStyle[5].HeaderText = "已付款";
			colRecordStyle[5].Width = 65;
			colRecordStyle[6].HeaderText = "付款日期";
			colRecordStyle[6].Width = 65;
			colRecordStyle[7].HeaderText = "付讫";
			colRecordStyle[7].Width = 35;
			colRecordStyle[7].Alignment = HorizontalAlignment.Center;
			colRecordStyle[8].HeaderText = "备注";
			colRecordStyle[8].Width = 0;
			colRecordStyle[9].HeaderText = "操作员ID";
			colRecordStyle[9].Width = 0;
			colRecordStyle[10].HeaderText = "操作员";
			colRecordStyle[10].Width = 55;
			colRecordStyle[10].Alignment = HorizontalAlignment.Center;
			colRecordStyle[11].HeaderText = "供货日期";
			colRecordStyle[11].Width = 65;
			colRecordStyle[12].HeaderText = "供货单位ID";
			colRecordStyle[12].Width = 0;
			colRecordStyle[13].HeaderText = "供货单位名称";
			colRecordStyle[13].Width = 200;
			colRecordStyle[14].HeaderText = "联系人";
			colRecordStyle[14].Width = 0;
			colRecordStyle[15].HeaderText = "电话";
			colRecordStyle[15].Width = 0;
			colRecordStyle[16].HeaderText = "传真";
			colRecordStyle[16].Width = 0;
			colRecordStyle[17].HeaderText = "地址";
			colRecordStyle[17].Width = 0;
			colRecordStyle[18].HeaderText = "邮编";
			colRecordStyle[18].Width = 0;		
		}
	}

编辑历史:[此帖最近一次被 蓝鲸 编辑过(编辑时间:2004-09-19 20:29:17)]

非常大鱼

缺缺

职务:管理员
等级:8
金币:41.0
发贴:9620
#62004/9/20 16:50:21
呵呵这里毕竟还只是网页后台版块,这样的讨论难怪少人参与



我个人来说是宁愿用ListView也不用DataGrid的



蓝鲸

职务:版主
等级:5
金币:42.1
发贴:2614
#72004/9/20 20:02:49
allinhands在上个帖子中说
引用:
呵呵这里毕竟还只是网页后台版块,这样的讨论难怪少人参与



我个人来说是宁愿用ListView也不用DataGrid的


倒忘了这点。心理真打算用B/S结构,可真没指望不懂电脑的在XP上面装IIS,不得不用WINFORM。以后多讨论些网页方面的。


非常大鱼