Windows 和 Web 通用组件






4.08/5 (7投票s)
一种使用相同接口创建 Windows 和 Web 组件的方法。

引言
本文的目的是介绍一个框架,该框架可以创建具有几乎相同外观和感觉的 Windows 和 Web 应用程序,并实现最大的代码重用。
示例代码包含通用于各种用户界面的 UI 组件。这意味着:拥有通用的 UI 组件,这些组件可以通过通用接口进行访问。例如:一个通用的TextBox
,在 ITextBox
接口中具有通用的 Text
属性,该属性可用于 Web 和 Windows 应用程序。显然,这种方法存在一些限制,但根据业务需求,这些限制也可以得到缓解。所有通用组件都是可绑定的,例如实现 ITreeView
接口的 Windows 和 Web 组件可以绑定到具有递归关系的数据表。以下是提供的示例代码中使用的一些通用组件
- Framework.UI.baWebControls
- 类
AddEditDelete
:System.Web.UI.WebControls.WebControl
,IAddEditDelete
- 类
baButton
:System.Web.UI.WebControls.Button
,IButton
- 类
baComboBox
:System.Web.UI.WebControls.DropDownList
,IComboBox
- 类
baGrid
:System.Web.UI.WebControls.GridView
,IGrid
- 类
baTextBox
:System.Web.UI.WebControls.TextBox
,ITextBox
- 类
baTreeView
:System.Web.UI.WebControls.TreeView
,ITreeView
- 类
baBindingManager
:ObjectDataSource
,IBindingManager
- 类
- Framework.UI.baWinControls
- 类
AddEditDelete
:System.Windows.Forms.UserControl
,IAddEditDelete
- 类
baButton
:System.Windows.Forms.Button
,IButton
- 类
baComboBox
:System.Windows.Forms.ComboBox
,IComboBox
- 类
baGrid
:System.Windows.Forms.DataGridView
,IGrid
,IState
- 类
baTextBox
:System.Windows.Forms.TextBox
,ITextBox
,IState
- 类
baTreeView
:Framework.UI.baWinControls.TreeViewStrategy
,ITreeView
- 类
baBindingManager
:System.Windows.Forms.BindingSource
,IBindingManager
- 类
Using the Code
应用程序的开发分为以下两个解决方案
- App.Development.sln: 根据业务需求开发接口。在下图中标为黄色。
- Framework.Development.sln: 为两种 UI 类型开发组件。在下图中标为白色。
Windows 窗体 UI (App.WinForm) |
Web 窗体 UI (App.WebForm) |
单元测试 (App.Test) |
数据传输对象 (App.DataSets) |
框架通用 (Framework.Lib) (Framework. (Framework.UI. (Framework.UI. |
(Framework.UI. |
(Framework.UI. |
(Framework.UI. |
||
UI 控制器 (App.Controller) |
||||
商用版 (App.BusinessController) |
||||
数据访问层 (DAL) (Framework.DAL) |
参考示例代码:我们有一个窗体(GeoForm
实现 IGeoForm
接口),其中包含许多组件(GeoTblGrid
实现 IGrid
,GeoTblTreeView
实现 ITreeView
,EntityCombo
实现 IComboBox
,所有这些都包含在 IGeoForm
中)。每个窗体都有一个 Controller
对象,该对象实现一个接口(IGeoForm
),用于保存和使用在 Windows 和 Web 中都使用的通用组件。在 Controller 中;开发人员可以实现 UI 行为,并使用业务逻辑层和其他框架服务,这些服务是所有用户界面通用的。分层架构如下:
- 表示层:实现
IForm
接口的窗体/页面,持有对Controller
对象的引用,该对象被传递给窗体。 - 控制器层:每个窗体/页面都有一个
Controller
对象,该对象与从窗体接口提供的通用组件一起工作。
注意:GeoCtrl Controller
对象持有对实现 IGeoForm
接口的窗体的引用,以便与其通用组件一起工作。
在 Windows 和 Web 解决方案中;我们创建一个用户界面文件夹(UI Folder),例如 BaseFrm 文件夹中的 GeoFrm Form
,并在两者中通过一个名为 IGeoForm
的接口来识别我们想要包含在这些页面中的通用组件。
public interface IGeoForm
{
string Caption{ get; set; }
ITextBox GeoTblName{ get; }
IGrid GeoTblGrid{ get; }
IGrid EntityTableGrid{ get; }
IComboBox GeoTblKind{ get; }
IAddEditDelete AddEditDel{ get; }
IBindingManager BindingManager{ get; }
IBindingManager DetailBindingManager{ get; }
IBindingRelation BindingRelation{ get; }
ITreeView GeoTblTreeView{ get; }
IComboBox EntityCombo{ get; }
ITextBox EntityTextBox{ get; }
IAddEditDelete addEditDelDetail{ get; }
}
对于 Windows 窗体
public partial class LookupForm : Form, IGeoForm
{
public LookupForm()
{
GeoCtrl ctrl = new GeoCtrl(this, RelationKind.Lookup);
}
}
对于 Web 窗体
public partial class LookupForm : WebPageBase, IGeoForm
{
protected void Page_Load(object sender, System.EventArgs e)
{
GeoCtrl ctrl = new GeoCtrl(this, RelationKind.Lookup);
}
}
对于两者,我们创建一个实现 IGeoForm
的 Controller 实例,如上面的代码所示(new GeoCtrl(this, RelationKind.Lookup)
)。Controller 负责使用通用组件提供的接口。
/// GeoCtrl is the Controller class for IGeoForm
public class GeoCtrl
{
public IGeoForm theForm;
public GeoCtrl(IGeoForm theForm, RelationKind kind)
{
/// Set the form that uses this controller to a
/// variable being used internally
/// by the controller
this.theForm = theForm;
}
}
为了将通用的 TreeView
组件(ITreeView
)绑定到数据源(IBindingManager
)
- 将
baBindingManager
拖放到窗体上 - 设置上述
BindingManager
的Datasource
和DataMember
属性 - 将
baTreeView
拖放到同一个窗体上 - 设置
TreeView
的以下属性
-
TreeViewComponent.BindingManager = theForm.BindingManager; // The Binding Manager
-
TreeViewComponent.TextField = "Name"; // Display name that is // defined in the DataSource
-
TreeViewComponent.ValueField = "ID"; // Unique Id field defined in the DataSource
-
TreeViewComponent.ValueParentField = "ParentID"; // Recursive relation // foreign key in the DataSource
关注点
- 表示层(包括组件和托管窗体)与底层之间的几乎所有交互都是通过预定义的接口进行的。要使用此解决方案创建应用程序,应为每个用户交互组件(如 Web/Win 组件(
IGrid
、ITextBox
、ITextBox
…)和窗体/页面(IGeoForm
))提供接口。用户界面组件可以包含其他通用组件(IGeoForm
包含IGrid
、ITextBox
、ITextBox
…)。Controller 对象可以使用提供的接口来实现业务功能。 - 使用通用组件本身存在一些限制,这些限制可以根据业务需求得到缓解。
- 可以使用适当的代码生成器应用程序来为每个窗体创建接口,并定义其通用组件和事件。

历史
- 2008 年 7 月 24 日:初始发布