<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

所谓的单数据窗体是指那种在窗体只显示一张单表的数据的窗体,主要就是用于显示基本表,因为这个系统要显示的差不多就是基本表为主,这一篇主要讲这个数据显示窗体的基类。

既然是基类嘛,当然要提供一些虚方法给子类来改写,要有一些变量必须由子量来初始化。首先必须由子量来提供实例的变量主要是跟子类关联的数据表有关,因为窗体的始化及UI的呈现都是与数据有关的,所以上述变量的初始化必须是在构造函数的最开始的地方进行。

public
       {
           InitVariable();
if
return;

 
           InitializeComponent();
new
       }

 
/// <summary>
/// 初始化一些由子类提供的变量
/// </summary>
protected virtual void
        {

 
       }

 
/// <summary>
/// 加载数据
/// </summary>
/// <returns></returns>
protected virtual bool
       {
try
           {
if (stMgr != null && stMgr.LastState == StateEnum.Insert) //新增一笔记录后要清除以前查询条件,否则会看不到新增的那一笔记录
                  condition.ClearCondition();
              DBCommandWrapper command = condition.BuildCondidtionCommand();
              dataTable = recordAction.GetAll(command);
if
"没有可显示的记录");
return true;
           }
catch(Exception)
           {
return true;
           }
       }

 

在子窗体的InitVariable方法里,根据当前窗体关联的数据表初始化对应的变量,这里其实主要就是初始化数据对象及跟它有关的一些东西(比如表示查询条件的类等等),比如“会议基本表”这个窗体

protected override void
       {
new
new
           condition = recordAction.GetQueryCondition();
       }

上面的record、recordAction是数据对象的基类,为什么要提供呢?因为考虑到数据显示与数据操作的问题。虽说是基本表,但有些还是有外键关联的,数据显示的时候我们并不是直接从表本身上取数据,一般会从这个表衍生的视图上取数据(可以提供外键的友好显示)。而新增、修改的时候,操作的还是那个基本表,所以分了二个数据对象(这里的会议表没什么外键,所以二者是一致的)。

缺省情况下,数据窗体是从数据表里取出所有的数据,当然在子窗体里可以根据不同情况来取,也可以根据条件排序。


 

数据窗体最为繁琐的地方就是工具栏,数据窗体的工具栏一般就是一些导航及数据操作按钮,但.Net Framework带的这个ToolBar实在做得是不算好。虽然上几篇化了点功夫改造了一下,但这里的工具栏是要在设计期用的,要在ToolBar的设计器中加入自定义类型的ToolBarButton要费点力气,想想就算了,反正用原始的工具栏也能解决问题,虽然看起来比较难看点。

先来看一下ToolBar的ButtonClick事件:

protected virtual void toolBar1_ButtonClick(object
       {
           currPos = curM.Position;
switch(e.Button.ToolTipText)
           {
case "First":
                  grid.UnSelect(curM.Position);
                  curM.Position = 0;
                  grid.Select(curM.Position);
break;
case "Previous":
                  grid.UnSelect(curM.Position);
                  curM.Position = (curM.Position == 0) ? 0 : curM.Position - 1;
                  grid.Select(curM.Position);
break;
              。。。。。。
              。。。。。。
case "Add":
                  stMgr.SetInsert();
false;
                  BeforeInsert();
break;
              。。。。。。
              。。。。。。
case "OK":
if (!BeforePost()) return;

 
if
                     stMgr.btnOKClick();
else 
                     CombineCondition();

 
switch
                  {
case
                         AfterInsert();
break;
case
                         AfterEdit();
break;
case
                         AfterQuery();
break;
                  }

 
                  LoadData();
true;

 
                  ReBind();
                  stMgr.SetBrowse();

 
                  grid.Refresh();
                  grid.Focus();
if
                  {
switch
                     {
case
break;
case
break;
                     }

 
                     currPos = (currPos >= curM.Count) ? curM.Count - 1 : currPos;

 
                     grid.UnSelect(curM.Position);
                     grid.Select(currPos);
                     curM.Position = currPos;
                  }
break;
              。。。。。。
              。。。。。。
           }
       }


 

上面这个方法为什么要声明成virtual呢?这是为了让子窗体可以有机会改写而做一些自己的事情,其实最后在子窗体中也没做什么大的事情,只是重新初始化了一下record这个变量,这个步骤比较好的方法本应该是在方法的入口处放一个Place Holder来让子窗体写,不过因为最开始时这么写,后来就没改了。

第二个要说的地方就是那个switch后面跟的条件了,找来找去实在找不出什么属性可以用来分清工具栏的各个按钮,用index之类的属性显然是不合适的,而Tag我已经有新的用途了,最后选了个ToolTipText属性,好歹也是个字符串的属性,看代码也还算看得明白。

上面当然是省略了很多的分支,不过处理都是大同小异的,所以就不一一列出来了。主要的技巧是放了大量的Place Holder,主要是那些After***、Before***方法,其实那些方法在基类里基本是空的虚方法,即使有点代码也就二三行,这些方法主要用途就是开放接口让子窗体能够做一些特殊处理。

那工具栏状态是如何控制的,及数据操作(新增、修改、删除、查询)是如何进行的呢,从上面看不出来,其实所有的奥秘都在stMgr状态管理器里,不过这个篇幅比较长,要放在下篇讲了。


 

最后记一个不太扣这一篇主旨的东西――点击grid选择整行,这是从网上查来的。其实其他的东西当然也有很多是从网上来的,但那些东西都比较大,要经过消化,这个小东西没什么可消化的,直接在这里记一笔了。

在grid的MouseUp事件里写:

private void grid_MouseUp(object
       {
new
           DataGrid.HitTestInfo hti = grid.HitTest(pt); 
if(hti.Type == DataGrid.HitTestType.Cell) 
           { 
new
              grid.Select(hti.Row); 
           }
       }