上文中我们提到,希望动态窗体的格式等全部可以由用户进行设定,这样,用户可以有最大的灵活性,于是,最终,我们的Form文件看起来可能是这样的:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<style type="text/css">
<!--
.STYLE3 {
font-family: "宋体";
font-size: 12px;
}
.STYLE4 {
font-family: "宋体";
font-size: 24px;
font-weight: bold;
}
.STYLE6 {
font-family: "幼圆";
font-size: 36px;
}
-->
</style>
</head>
<body>
<font size="+3"><asp:PlaceHolder runat="server" ID="__RowName"></asp:PlaceHolder> <!--标题--></font>
<hr />
<table width="730" border="0" cellpadding="0" cellspacing="0" class="STYLE3">
<tr>
<td align="center">(发布:<asp:PlaceHolder runat="server" ID="__Text1"></asp:PlaceHolder> <!--发布人--> 时间:<asp:PlaceHolder runat="server" ID="__Text2"></asp:PlaceHolder> <!--发布时间-->)</td>
</tr>
<tr>
<td>
<asp:PlaceHolder runat="server" ID="__Content"></asp:PlaceHolder>
<!--新闻内容--> </td>
</tr>
</table>
<!--新闻内容-->
</body>
</html>
这是一个用DreamWeaver制作的网页文件,美工完全可以完成;在完成之后,在特定的地方,插入我们的标识符,也就是PlaceHolder控件,那么,当服务器加载完这个用户控件之后,对其子控件进行遍历,并且为我们的PlaceHolder控件增加适当的子控件就可以了,这是实现User Defined Form的总体思路。我们的目的就是,希望通过这样的方式,可以让用户自己就可以定义界面;而不是通常情况下DotNetNuke的UDT模块所产生的很死板的录入界面。
当然,这里马上就会有一个问题:如果是我们在开发的时候定义好的界面,比如一个添加了Text1文本控件的ascx文件,我们在页面保存的时候,当然可以采用Text1.Text等方式来读取文本框的内容;但是,如果是动态页面的话,我们的控件是在运行的时候产生的,而不是设计时。所以,我们在产生控件的时候,就必须要将之放到一个控件数组或者其他的方式存储,这样,我们在进行Save等动作的时候,就可以从控件数组(或者其他的存储形式)中获取到该控件以及内容,并且保存到数据库中。
在这里,我认为UserDefinedTable的方式非常好,定义了一个对象集合,具体的代码,大家可以下载UDT3.3.7以上的版本,找到EditControls.vb文件自行研究一下,下面是部分代码:
Public Class EditControls
Inherits System.Collections.CollectionBase
Private parentModule As Entities.Modules.PortalModuleBase
Public Sub New(ByVal ParentModule As Entities.Modules.PortalModuleBase)
Me.parentModule = ParentModule
End Sub
Public Function Add(ByVal FieldTitle As String, ByVal FieldType As String, ByVal FieldID As Integer, _
ByVal Value As String, ByVal Required As Boolean, ByVal ExtendedSettings As String) As EditControl
Dim Editor As EditControl
Select Case FieldType
Case "CreatedBy"
Editor = New EditCreatedBy(FieldTitle, FieldType, FieldID, Value, Required, ExtendedSettings)
End Select
MyBase.List.Add(Editor)
Return CType(Editor, EditControl)
End Function
Default Public ReadOnly Property Item(ByVal Fieldtitle As String) As EditControl
Get
Dim i As Integer = 0
Dim ec As EditControl
Do
ec = CType(MyBase.List.Item(i), EditControl)
i += 1
Loop Until ec.FieldTitle = Fieldtitle Or i > MyBase.List.Count
If i > MyBase.List.Count Then Throw New ApplicationException("No EditControl found for " & Fieldtitle)
Return ec
End Get
End Property
End Class
好了,整体的思路就是:
我们让用户使用网页编辑工具定义窗体,并且约定窗体中包含有我们预定义的控件;【尽量灵活】
在页面加载的时候,动态加载页面并且动态创建控件;【尽量让定义简单】
所创建的控件,保存在我们约定的集合中,这样,在页面进行Post的时候,我们就可以读取到动态创建的控件,以便将控件的内容保存到数据库中。【保留我们创建的内容】
以上,就是我们做自定义窗体的总体思路。
下面的章节,我们看一下如何创建控件,以及如何扩展控件;以及控件如何自己进行行为约束等