Web系统中经常会遇到这样的情况:页面提交很慢,用户耐心受到挑战就开始摧残页面上的按钮,反复点击反而搞得更慢。前两天就遇到这样一个问题,用户要进行大数据量的导出操作,这个服务器端需要比较长的时间处理,于是很容易出现用户等得不耐烦就反复点击导出按钮的情况。
比较简单的解决方法就是在用户进行了点击操作将按钮之类的东西隐藏掉,国外的一位同行写了一个对button的扩展:pleasewaitButton 源文档 <http://www.codeproject.com/KB/webforms/PleaseWaitButton.aspx> 就是实现了这个效果。但是这个控件是有局限的,有时候要隐藏的不只是按钮。我觉得可以学习UpdatePanel的“包起来”一个区域的方式以获得更大的灵活性。
下面是页面代码的一个示例:
1 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
2
3 <%@ Register Assembly="KingWebControlToolkit" Namespace="KingWebControlToolkit" TagPrefix="King" %>
4 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5 <html xmlns="http://www.w3.org/1999/xhtml">
6 <head runat="server">
7 <title>Untitled Page</title>
8 </head>
9 <body>
10 <form id="form1" runat="server">
11 <div>
12 <King:LoadingControl runat="server">
13 <ContentTemplate>
14 <asp:Button ID="Button1" runat="server" Text="Button" />
15 </ContentTemplate>
16 <ProgressTemplate>
17 <img src="loader.gif" />Loading
18 </ProgressTemplate>
19 </King:LoadingControl>
20 </div>
21 </form>
22 </body>
23 </html>
24
2
3 <%@ Register Assembly="KingWebControlToolkit" Namespace="KingWebControlToolkit" TagPrefix="King" %>
4 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5 <html xmlns="http://www.w3.org/1999/xhtml">
6 <head runat="server">
7 <title>Untitled Page</title>
8 </head>
9 <body>
10 <form id="form1" runat="server">
11 <div>
12 <King:LoadingControl runat="server">
13 <ContentTemplate>
14 <asp:Button ID="Button1" runat="server" Text="Button" />
15 </ContentTemplate>
16 <ProgressTemplate>
17 <img src="loader.gif" />Loading

18 </ProgressTemplate>
19 </King:LoadingControl>
20 </div>
21 </form>
22 </body>
23 </html>
24
为了能看到Loading的效果我们在Page_Load中使用System.Threading.Thread.Sleep(3000);做延迟。
页面render出来的代码如下:



























控件实现
其实就两个要点:
- 控件要支持两个模板一个是ContentTemplate这个是要隐藏部分的模板,一个是Progress模板用来放Loading的提示信息
- 添加javascript脚本来实现隐藏,这个利用事件传递的原理可以方便的实现
这个控件超简单直接贴代码了,控件源代码如下:
1
using System;
2
using System.ComponentModel;
3
using System.Drawing;
4
using System.Security.Permissions;
5
using System.Web;
6
using System.Web.UI;
7
using System.Web.UI.WebControls;
8
9
namespace KingWebControlToolkit
10
{
11
[
12
AspNetHostingPermission(SecurityAction.InheritanceDemand,
13
Level = AspNetHostingPermissionLevel.Minimal),
14
AspNetHostingPermission(SecurityAction.Demand,
15
Level = AspNetHostingPermissionLevel.Minimal),
16
ToolboxData(
17
"<{0}:LoadingControl runat=\"server\"> </{0}:LoadingControl>"),
18
]
19
public class LoadingControl : CompositeControl
20
{
21
private ITemplate contentTempalte;
22
private ITemplate progressTemplate;
23
24
private TemplateContainer contentContainer;
25
private TemplateContainer progressContainer;
26
[
27
Browsable(false),
28
DesignerSerializationVisibility(
29
DesignerSerializationVisibility.Hidden)
30
]
31
public TemplateContainer Owner
32
{
33
get
34
{
35
return contentContainer;
36
}
37
}
38
39
[
40
Browsable(false),
41
PersistenceMode(PersistenceMode.InnerProperty),
42
DefaultValue(typeof(ITemplate), ""),
43
Description("Control template"),
44
TemplateContainer(typeof(LoadingControl ))
45
]
46
public virtual ITemplate ContentTemplate
47
{
48
get
49
{
50
return contentTempalte;
51
}
52
set
53
{
54
contentTempalte = value;
55
}
56
}
57
58
[
59
Browsable(false),
60
PersistenceMode(PersistenceMode.InnerProperty),
61
DefaultValue(typeof(ITemplate), ""),
62
Description("Control template"),
63
TemplateContainer(typeof(LoadingControl))
64
]
65
public virtual ITemplate ProgressTemplate
66
{
67
get
68
{
69
return progressTemplate;
70
}
71
set
72
{
73
progressTemplate = value;
74
}
75
}
76
77
protected override void CreateChildControls()
78
{
79
Controls.Clear();
80
contentContainer = new TemplateContainer();
81
progressContainer = new TemplateContainer();
82
contentContainer.Attributes["onclick"] = "javascript:this.style.display='none';document.getElementById('progress').style.display='';";
83
contentContainer.Attributes["id"] = "content";
84
progressContainer.Attributes["id"] = "progress";
85
progressContainer.Attributes["style"] = "display:none";
86
ITemplate temp = contentTempalte;
87
if (temp == null)
88
{
89
temp = new DefaultTemplate();
90
}
91
temp.InstantiateIn(contentContainer);
92
93
temp = progressTemplate;
94
temp.InstantiateIn(progressContainer);
95
this.Controls.Add(contentContainer);
96
this.Controls.Add(progressContainer);
97
}
98
}
99
100
[
101
ToolboxItem(false)
102
]
103
public class TemplateContainer : WebControl
104
{
105
}
106
107
DefaultTemplate
117
}
118
Demo下载:https://files.cnblogs.com/me-sa/loadingdemo.rar

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

117

118

Demo下载:https://files.cnblogs.com/me-sa/loadingdemo.rar
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义