[按]
你可能会误解本文标题:让WEB FORM 更像WINDOWS FORM。 你也许会把本文当作是讨论应用程序界面. 其实本文讨论的是ASP.NET表现层设计。  也许会给你一点启示:如何设计逻辑隔离良好的、更容易设计和管理的应用程序。作者是一个偏向于应用的开发人员,因此可能在某些方面涉论不深,希望可以与有更多想法的朋友交流。作者的电子邮件xujian(a)nwpu.edu.cn

[引言]
在项目设计和实施的过程中,我经常再想,既然我们必须给用户以样式美观并且易用的用户界面,就应该好好设计表现层的UI逻辑。或者想办法把业务逻辑、系统逻辑、和UI逻辑隔离得更好。使界面相关元素得到最大程度的重用和最大的灵活性。

本文的核心论述对象是ASCX(ASP.NET User Controls)。这里我们把ASCX比作WIN32应用程序的”窗体(FORM)“。我们知道,设计WINDOWS应用程序的时候,不管使用什么开发工具,用户界面的主要构成元素是“窗体”,我们预先设计好承担不同任务的窗体,然后在适当的时候把他们弹出来,任务完成后把他们关掉。这样就基本完成了用户界面的流程控制。

而ASCX是类似可嵌入到网页中的UI单元。我们可以通过编写HTML来开发一个ASCX。这只是ASP.NET框架所提供的一种机制。我们可以把ASCX做为FORM,像操作WINDOWS FORMS一样操作网页中的ASCX,来完成我们的UI逻辑。

由于ASCX可以嵌入页面中,这就使得最大程度重用页面构图提供了可能性。我们可以把ASPX页面当作ASCX的容器。ASPX仅包含UI逻辑。更复杂的业务上的逻辑由ASCX承担。甚至ASCX仅承载数据。(在我的实际经验中,我总是设计两类ASCX。一类是数据类,仅以一定格式显示数据,不承担业务逻辑;另外一种是事务型,用来完成某种操作。)ASPX控制其中的各个ASCX交互显示隐藏,由此完成流程控制。

实现的障碍在哪里?提供ASCX的主要目的是隐藏其中的逻辑,并且提供一定程度上的重用性。但是ASCX内部的逻辑并不能和其容器直接交流。也就是说ASCX对外界是一无所知的。承载ASCX的容器(可能是一个ASPX页面或者另一个ASCX)可以很方便的控制他的显示,隐藏,但是容器却不知道什么时候关闭他。在流程完成后,ASCX无法直接调用容器的方法是自己关掉。

关键性的技巧就是让ASCX可以向外引发事件。只要ASCX需要变动自己的UI状态,就以一定的事件通知容器。而不用管容器如何处理。而容器可以很容易捕获控件的事件而最初相应处理。这样就给我们提供了一种指导性的模式。

作者的设计。一般而言, 我给表现层的ASPX和ASCX都至少抽象一个基类。基类里包含所有ASCX都需要的内容。有安全方面的,有系统配置方面的。对于本文所论述的内容,我使所有ASCX都可以引发三种事件,分别代表ASCX生命周期的各个阶段,他们是:

MissionStart:事务开始,代表控件最初状态。
MissionAbort:事务中止,用户的操作取消。需要返回原界面。
MissionEnd:事务结束, 用户的操作完成,需要进一步处理。

这三个事件都没有任何参数,他们仅仅包含了界面逻辑,和业务逻辑没有关系。 这样我们可以在用户没有进行有结果的操作,并且需要返回原界面时引发MissionAbort事件,在用户操作完成,需要进一步处理时引发MissionEnd事件。(MissionStart我还从来没有应用到, 但我想预留这么一个事件是必要的。)

[有关源代码]
以下源代码摘自UserControlBase.cs 该类继承自System.System.Web.UI.UserControl
  /// <summary>
  /// 关键系统事件: 事务开始. ASCX生命周期开始.
  /// </summary>
  public event System.EventHandler MissionStart;

/// <summary>
  /// 关键系统事件: 事务中止. 未进行到事件最终状态. ASCX关闭但操作未完成.
  /// </summary>
  public event System.EventHandler MissionAbort;

/// <summary>
  /// 关键系统事件: 事务完成. 既定操作完成. ASCX被关闭, 通知容器向下进行.
  /// </summary>
  public event System.EventHandler MissionEnd;

/// <summary>
  /// 引发MissionStart事件
  /// </summary>
  protected void RaiseMissionStart()
  {
   if(this.MissionStart != null)
   {
    this.MissionStart(this, new System.EventArgs());
   }
  }

/// <summary>
  /// 引发MissionAbort事件
  /// </summary>
  protected void RaiseMissionAbort()
  {
   if(this.MissionAbort != null)
   {
    this.MissionAbort(this, new System.EventArgs());
   }
  }

/// <summary>
  /// 引发MissionEnd事件
  /// </summary>
  protected void RaiseMissionEnd()
  {
   if(this.MissionEnd != null)
   {
    this.MissionEnd(this, new System.EventArgs());
   }
  }
ASCX需要从此基类派生. 例如:
public class ComplexSearch : XxxXxx.YyyYyy.UserControlBase
{
...
}

上述ASCX是一个做组合查询的UI. 有一个“取消“命令按钮. 我们在取消按钮的Click事件上做如下命令
This.RaiseMissionAbort();

之后容器捕获该事件, 在private void InitializeComponent()方法中加上:
this.XxxXxxxx.MissionAbort += new EventHandler(AttributeInsert_MissionAbort);

(注意:以上代码是+=以后的部分IDE可以自动为你完成. 并且自动生成复合编码约定的方法名):

private void XxxXxxxx_MissionAbort(object sender, EventArgs e)
  {
   ///...(处理过程)
  }

以上仅仅是基类相关事件的定义以及应用范例. 实际情况也复杂不到哪里去. 不过除了这些之外, 作者所开发的项目中, 几乎每个ASCX都有着异常丰富的特性. 有着较高的可重用性/灵活性和独立性.

[几点与主题无关的原则]
1. 尽量抽象一些公共特性到基类
2. 尽量分离逻辑. 公开足够的特性(Properties), 方法, 事件.
3. 设计上多用一天, 可以减少几天的编码及维护工作量. 并且可为后继的工作带来便利.

[结束]
本着抛砖引玉的想法,本文仅仅讨论了给ASCX加上三个事件。想法简单明晰,但在一定程度上反映了”架构“上的一些思想。

转载于:https://www.cnblogs.com/xchunyu/archive/2004/04/05/5252.html

让WEB FORM更像WINDOWS FORM: 控制窗体事件相关推荐

  1. Windows Form中的Grid Control

    MDI的一些界面设计方案: DotNetMagic Tim Dawson Syncfusion Xtreme Docking Pane Infragistics WinTabbedMDI Window ...

  2. windows form (窗体) 之间传值

    在windows form之间传值,我总结了有四个方法:全局变量.属性.窗体构造函数和delegate. 第一个全局变量: 这个最简单,只要把变量描述成static就可以了,在form2中直接引用fo ...

  3. windows form参数传递过程

    1 三.windows form参数传递过程 2 在Windows 程序设计中参数的传递,同样也是非常的重要的. 3 这里主要是通过带有参数的构造函数来实现的, 4 5 说明:Form1为主窗体,包含 ...

  4. 微软一站式示例代码库(中文版)2012-2-10版本, 新添加ASP.NET, Windows Form, VSX, Windows Shell, WPF等16个Sample

    让大家久等了,2月份我们准备了16个中文版Microsoft OneCode Sample,其中包括2个Windows Form Sample,2个VSX Sample,1个Windows Shell ...

  5. C# Windows Form编程

    目录 1. Windows 编程概述 1.1 概述 1.2 Windows应用程序的消息来源有以下四种 2. 窗体与事件处理 3. 控件属性和布局 4. 常用控件 4.1 listBox控件 4.2 ...

  6. spring boot构建基础版web项目(一)springboot、thymeleaf控制层基础构

    原文作者:弥诺R 原文地址:http://www.minuor.com/147852147/article 转载声明:转载请注明原文地址,注意版权维护,谢谢! 写前说明 根据个人在各篇博文中看到的信息 ...

  7. 怎样让你的Linux使用起来更像Windows

    许多Linux初学者刚从Windows"移民"过来,对Linux环境和操作即新奇又陌生,怎样才能让初学者迅速找到感觉,尽快进入Linux殿堂呢?当然是先从操作环境和使用习惯入手了, ...

  8. C#窗口的Form.AcceptButton 属性和Form.CancelButton 属性

    C#窗口的Form.AcceptButton 属性和Form.CancelButton 属性 初入门时,看到这两个属性一般不太关注它,因为这两个属性在窗口设计上也不需要设置就可以工作,因为默认了按下回 ...

  9. form action=./ 或者为form action=/ 的提交路径

    <form action="./" >或者为<form action="/" >的提交路径: 这里表示提交到项目的根路径: 比如:htt ...

最新文章

  1. Android性能优化系列 + Android官方培训课程中文版
  2. 微信公众号的分享功能
  3. 筛选汇总 power_批量汇总多Excel表格 | 标题都从第n行起怎么办?
  4. django请求与响应(HttpRequest对象和HttpResponse对象)
  5. fms3 NetConnection.Connect.Rejected 问题
  6. linux c 系统调用
  7. 安卓手机系统可删除的自带软件大集合
  8. 用画小狗的方法来解释Java中的值传递
  9. CSS3 实用技巧:制作三角形
  10. mysql判断存在返回布尔_MySqlClient访问tinyint字段返回布尔值篇
  11. Java课程设计-旅游管理系统
  12. 【万字讲解C语言入门小游戏】——三子棋
  13. <EDEM 基础案例02>Rock Box
  14. 数据治理---Apache Atlas元数据管理
  15. TensorFlow2 学习——RNN生成古诗词
  16. 电脑时间不准怎么办?电脑时间不准怎么修复?
  17. sccm数据库远程服务器,SCCM 2007 R2部署之连接远程SQL Server模式
  18. c语言编译器怎么防止优化变量,volatile关键字的作用:防止变量被编译器优化
  19. iOS开发 dispatch_semaphor的简单使用
  20. remote access between two linuxs

热门文章

  1. 网络协议文档阅读笔记-Introduction to DTLS(Datagram Transport Layer Security)
  2. C++设计模式-使用Qt框架模拟策略模式(Strategy)商场促销
  3. RESTful API实现APP订餐实例
  4. Java基础入门笔记-链表与容器
  5. 24口光纤配线架 cad块_光纤配线架cad画法
  6. 船舶和计算机结合论文格式,近海船舶监控系统中航迹关联算法的计算机研究与实现...
  7. oracle十进制函数语法,Oracle 十进制、二进制互相转换自定义函数
  8. ai可以滚轮缩放吗_AI侵入艺术天堂!艺术也可以“量产”了吗?
  9. linux系统查看进程并杀掉,Linux如何查找8080进程并杀掉该进程
  10. 计算机管理员四级,计算机四级基本知识点