在实际的项目中,存在这么一个问题:所有页面都从自定义的页面基类(MyPageBase)中继承过来。一些公共的方法可以在基类中实现。其中有一个是防止并发问题的,任何页面在绑定数据之前,都去检查是否有其它用户以可写的方式打开了此文档(写独占),如果被他人独占,则以只读方式打开。同时在页面中显示如“只读”标识,这样既很好地避免了并发的问题,同时又很清楚的告诉当前用户“你现在只能浏览本文档,因为他人正在修改此文档……”(如图1)。现在问题来了:我不可能要求其它程序员都在自己做的页面的某个位置手工放置“只读”标识吧?!这样做重复劳动不说,风格也很难统一。怎么办呢?
如果在WinForm中,基类Form可以拖个Label控件,label1.Text = “只读”(或者是一副图片),则其所有派生类都会有这个Label控件。但WebForm中就不行,因为在Web中页面(指WebForm1.aspx)之间不能像WinForm一样实现继承,但页面的代码类(指WebForm1.aspx.cs)可以继承。分析Web程序的原理:服务器接受客户端的请求后,经过处理生成一个Html的文本发送给客户端,如果我们可以在服务器发送Html的文本到客户端之前对Html的文本进行修改,然后再发送给客户端,那问题就能得到解决。幸运的是:页面类Page中有一个Render(HtmlTextWriter writer)方法可以承载。
做法:我在页面基类(MyPageBase)承载Render(HtmlTextWriter writer)方法,然后在得到的Html的文本中的<body>标识与<form>之间插入一段标识文本,用来标识文档是否“只读”。这样,所有从此页面基类中派生过来的页面,都在最顶端标出文档是否“只读”。当然是否显示“只读”标识必须看是否只读打开此文档的,如果不是只读打开(没有他人独占文档),则没必要显示“只读”标识,如图2。
图2
代码如下:
1
/// <summary>
2
/// 本项目中所有页面的基类
3
/// </summary>
4
public class MyPageBase : System.Web.UI.Page
5
{
6
7
private bool _isReadOnly = true;
8
9
protected override void Page_Load(object sender, EventArgs e)
10
{
11
base.Page_Load(sender, e);
12
13
14
if (!IsPostBack)
15
{
16
try
17
{
18
this.MainDataSet = this.ManagerProvider.Open(DocID, false); //DocID为文档的ID
19
this.ViewState.Add("IsReadOnly",false);
20
}
21
catch(LockException lockEx) //LockException为自定义的锁定异常类
22
{
23
this.MainDataSet = this.ManagerProvider.Open(DocID, true);
24
this.ViewState.Add("IsReadOnly",true);
25
26
SetPageReadOnly(); //设置页面为只读的
27
}
28
30
31
}
32
33
}
34
35
36
/// <summary>
37
/// 根据本页面/文档是是否是“只读”,选择是否加载“只读”图片
38
/// </summary>
39
protected override void Render(HtmlTextWriter writer)
40
{
41
bool isReadOnly = (bool)this.ViewState["IsReadOnly"];
42
if(isReadOnly )
43
{
44
StringWriter wt = new StringWriter();
45
HtmlTextWriter buffer = new HtmlTextWriter(wt);
46
base.Render(buffer);
47
48
string pMarkup = wt.ToString();
49
int indexEndBody = 0;
50
string readonlyFlag = @"<table width=100% border=0 cellspacing=0 cellpadding=0>
51
<tr>
52
<td><img src=../../include/images/ReadOnly.JPG width=404 height=58 align=left></td>
53
</tr>
54
</table>";
55
56
indexEndBody = pMarkup.IndexOf(">",pMarkup.IndexOf("<body"));
57
pMarkup = pMarkup.Insert(indexEndBody + 1, readonlyFlag);
58
59
writer.Write(pMarkup);
60
}
61
else
62
base.Render(writer);
63
}
64
65
66
/// <summary>
67
/// 设置页面为只读的,派生类可以重载此方法,加入对页面中各控件的Enable属性的设置。
68
/// </summary>
69
protected virtual void SetPageReadOnly()
70
{
71
}
72
/// <summary>2
/// 本项目中所有页面的基类3
/// </summary>4
public class MyPageBase : System.Web.UI.Page5
{6
7
private bool _isReadOnly = true;8

9
protected override void Page_Load(object sender, EventArgs e)10
{11
base.Page_Load(sender, e);12

13

14
if (!IsPostBack)15
{16
try17
{18
this.MainDataSet = this.ManagerProvider.Open(DocID, false); //DocID为文档的ID19
this.ViewState.Add("IsReadOnly",false);20
}21
catch(LockException lockEx) //LockException为自定义的锁定异常类22
{23
this.MainDataSet = this.ManagerProvider.Open(DocID, true);24
this.ViewState.Add("IsReadOnly",true);25

26
SetPageReadOnly(); //设置页面为只读的27
}28

30
31
}32

33
}34

35

36
/// <summary>37
/// 根据本页面/文档是是否是“只读”,选择是否加载“只读”图片38
/// </summary>39
protected override void Render(HtmlTextWriter writer)40
{41
bool isReadOnly = (bool)this.ViewState["IsReadOnly"];42
if(isReadOnly )43
{44
StringWriter wt = new StringWriter();45
HtmlTextWriter buffer = new HtmlTextWriter(wt);46
base.Render(buffer);47

48
string pMarkup = wt.ToString();49
int indexEndBody = 0;50
string readonlyFlag = @"<table width=100% border=0 cellspacing=0 cellpadding=0>51
<tr>52
<td><img src=../../include/images/ReadOnly.JPG width=404 height=58 align=left></td>53
</tr>54
</table>";55

56
indexEndBody = pMarkup.IndexOf(">",pMarkup.IndexOf("<body"));57
pMarkup = pMarkup.Insert(indexEndBody + 1, readonlyFlag);58

59
writer.Write(pMarkup);60
}61
else62
base.Render(writer);63
}64
65
66
/// <summary>67
/// 设置页面为只读的,派生类可以重载此方法,加入对页面中各控件的Enable属性的设置。68
/// </summary>69
protected virtual void SetPageReadOnly()70
{71
}72

Arbean Wu 于广州
2005-6-7


浙公网安备 33010602011771号