Net有道

紫冠道人的求道历程

导航

RFID会议签到系统总结(十九)――单数据窗体

 

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

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

       public frmData()

       {

           InitVariable();

           if (!LoadData())

              return;

 

           InitializeComponent();

           toolBar1.ButtonClick += new ToolBarButtonClickEventHandler(toolBar1_ButtonClick);

       }

 

       /// <summary>

       /// 初始化一些由子类提供的变量

       /// </summary>

       protected virtual void InitVariable()

        {

 

       }

 

       /// <summary>

       /// 加载数据

       /// </summary>

       /// <returns></returns>

       protected virtual bool LoadData()

       {

           try

           {

              if (stMgr != null && stMgr.LastState == StateEnum.Insert) //新增一笔记录后要清除以前查询条件,否则会看不到新增的那一笔记录

                  condition.ClearCondition();

              DBCommandWrapper command = condition.BuildCondidtionCommand();

              dataTable = recordAction.GetAll(command);

              if (dataTable.Rows.Count == 0)

                  Msg.ShowInformation("没有可显示的记录");

              return true;

           }

           catch(Exception)

           {

              return true;

           }

       }

 

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

       protected override void InitVariable()

       {

           record = new MeetInfoBO();

           recordAction = new MeetInfoBO();

           condition = recordAction.GetQueryCondition();

       }

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

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

 

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

先来看一下ToolBarButtonClick事件:

       protected virtual void toolBar1_ButtonClick(object sender, ToolBarButtonClickEventArgs e)

       {

           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();

                  grid.Enabled = false;

                  BeforeInsert();

                  break;

              。。。。。。

              。。。。。。

              case "OK":

                  if (!BeforePost()) return;

 

                  if (stMgr.CurrentState != StateEnum.Query)

                     stMgr.btnOKClick();

                  else

                     CombineCondition();

 

                  switch (stMgr.CurrentState)

                  {

                     case StateEnum.Insert:

                         AfterInsert();

                         break;

                     case StateEnum.Edit:

                         AfterEdit();

                         break;

                     case StateEnum.Query:

                         AfterQuery();

                         break;

                  }

 

                  LoadData();

                  grid.Enabled = true;

 

                  ReBind();

                  stMgr.SetBrowse();

 

                  grid.Refresh();

                  grid.Focus();

                  if (curM.Count > 0)

                  {

                     switch (stMgr.LastState)

                     {

                         case StateEnum.Insert:

                            currPos = curM.Count - 1;

                            break;

                         case StateEnum.Query:

                            currPos = 0;

                            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选择整行,这是从网上查来的。其实其他的东西当然也有很多是从网上来的,但那些东西都比较大,要经过消化,这个小东西没什么可消化的,直接在这里记一笔了。

gridMouseUp事件里写:

       private void grid_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)

       {

           System.Drawing.Point pt = new Point(e.X, e.Y);

           DataGrid.HitTestInfo hti = grid.HitTest(pt);

           if(hti.Type == DataGrid.HitTestType.Cell)

           {

              grid.CurrentCell = new DataGridCell(hti.Row, hti.Column);

              grid.Select(hti.Row);

           }

       }

posted on 2007-07-25 14:05  lichdr  阅读(797)  评论(1编辑  收藏  举报