如何实现在Asp.net下XP风格的下拉菜单
结合Jst和Css实现了在Asp.net下XP风格的下拉菜单,效果图如下:
实现的步骤及源码如下:
Default.aspx代码:
1
<%@ Page language="c#" Codebehind="default.aspx.cs" AutoEventWireup="false" Inherits="PopupMenuControlSample._default" %>
2
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
3
<HTML>
4
<HEAD>
5
<title>PopupMenu control sample</title>
6
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
7
<meta content="C#" name="CODE_LANGUAGE">
8
<meta content="JavaScript" name="vs_defaultClientScript">
9
<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
10
<LINK href="PopupMenuSample.css" type="text/css" rel="Stylesheet">
11
</HEAD>
12
<body bgColor="#ffffcc" MS_POSITIONING="GridLayout">
13
<form id="MainForm" method="post" runat="server">
14
<asp:label id="PopupMenuOwner" Runat="server" CssClass="MainText">Click on me to show the popup menu</asp:label>
15
</form>
16
</body>
17
</HTML>
18

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

Default.aspx.cs代码:
1
using System;
2
using System.Collections;
3
using System.ComponentModel;
4
using System.Data;
5
using System.Drawing;
6
using System.Web;
7
using System.Web.SessionState;
8
using System.Web.UI;
9
using System.Web.UI.WebControls;
10
using System.Web.UI.HtmlControls;
11
using UIControl;
12
13
namespace PopupMenuControlSample
14
{
15
/// <summary>
16
/// Summary description for _default.
17
/// </summary>
18
public class _default : System.Web.UI.Page
19
{
20
const string ControlContainer = "MainForm";
21
const string ClickedMessage = "<BR/><BR/>The menu item '{0}' has been selected by the user.";
22
const string NoMenuItemClicked = "<BR/><BR/>No menu item has been clicked yet.";
23
const string MessageStyle = "Message";
24
const string MenuControlID = "PopupMenu";
25
const MenuItemDirection MenuDirection = MenuItemDirection.Vertical;
26
const string PopupMenuParentID = "PopupMenuOwner";
27
const string Services = "Services";
28
const string ServicesAltText = "available services";
29
const string ServicesName = "Services";
30
const string ServicesJavaScript = null;
31
const string ServicesImageUrl = null;
32
const MenuItemDirection ServicesDirection = MenuItemDirection.Vertical;
33
const string ServicesTableID = "Services";
34
const string AboutMe = "About me";
35
const string AboutMeAltText = "about me";
36
const string AboutMeName = "AboutMe";
37
const string AboutMeJavaScript = null;
38
const string AboutMeImageUrl = null;
39
const MenuItemDirection AboutMeDirection = MenuItemDirection.Vertical;
40
const string AboutMeTableID = "AboutMe";
41
const string UsefulLinks = "Useful links";
42
const string UsefulLinksAltText = "useful links";
43
const string UsefulLinksName = "UsefulLinks";
44
const string UsefulLinksJavaScript = null;
45
const string UsefulLinksImageUrl = null;
46
const MenuItemDirection UsefulLinksDirection = MenuItemDirection.Vertical;
47
const string UsefulLinksTableID = "UsefulLinks";
48
const string Presenter = ".NET Presenter";
49
const string PresenterAltText = "presenter for your .NET usergroup or show";
50
const string PresenterName = "Presenter";
51
const string PresenterJavaScript = null;
52
const string PresenterImageUrl = "images/presenter.gif";
53
const string PresenterTableID = "Presenter";
54
const string Author = ".NET author";
55
const string AuthorAltText = "author for your .NET magazine";
56
const string AuthorName = "Author";
57
const string AuthorJavaScript = "window.alert('Klaus Salchner, Chief Enterprise Architect');";
58
const string AuthorImageUrl = null;
59
const string AuthorTableID = "Author";
60
const string Architect = ".NET architecture review";
61
const string ArchitectAltText = "architecture review for your .NET project";
62
const string ArchitectName = "Architect";
63
const string ArchitectJavaScript = null;
64
const string ArchitectImageUrl = "images/review.gif";
65
const string ArchitectTableID = "Architect";
66
const string Resume = "Resume";
67
const string ResumeAltText = "my resume";
68
const string ResumeName = "Resume";
69
const string ResumeJavaScript = null;
70
const string ResumeImageUrl = null;
71
const string ResumeTableID = "Resume";
72
const string ContactMe = "Contact me";
73
const string ContactMeAltText = "contact me";
74
const string ContactMeName = "ContactMe";
75
const string ContactMeJavaScript = null;
76
const string ContactMeImageUrl = "images/contactme.gif";
77
const string ContactMeTableID = "ContactMe";
78
const string CodeGuru = "CodeGuru";
79
const string CodeGuruAltText = "CodeGuru";
80
const string CodeGuruName = "CodeGuru";
81
const string CodeGuruJavaScript = null;
82
const string CodeGuruImageUrl = "images/codeguru.gif";
83
const string CodeGuruTableID = "CodeGuru";
84
const string DeveloperLand = "DeveloperLand";
85
const string DeveloperLandAltText = "DeveloperLand";
86
const string DeveloperLandName = "DeveloperLand";
87
const string DeveloperLandJavaScript = null;
88
const string DeveloperLandImageUrl = "images/developerland.gif";
89
const string DeveloperLandTableID = "DeveloperLand";
90
const string Msdn = "MSDN";
91
const string MsdnAltText = "MSDN";
92
const string MsdnName = "Msdn";
93
const string MsdnJavaScript = null;
94
const string MsdnImageUrl = "images/msdn.gif";
95
const string MsdnTableID = "Msdn";
96
const string GotDotNet = "Got-Dot-Net";
97
const string GotDotNetAltText = "Got-Dot-Net";
98
const string GotDotNetName = "GotDotNet";
99
const string GotDotNetJavaScript = null;
100
const string GotDotNetImageUrl = null;
101
const string GotDotNetTableID = "GotDotNet";
102
private Label Message;
103
protected System.Web.UI.WebControls.Label PopupMenuOwner;
104
105
Web Form Designer generated code
125
126
/// <summary>
127
/// initialize the form; allows us to add new controls to it
128
/// </summary>
129
/// <param name="sender">event sender</param>
130
/// <param name="e">event argument</param>
131
private void Page_Init(object sender, System.EventArgs e)
132
{
133
// create a new popup menu control to display
134
PopupMenuControl MyPopupMenu = new PopupMenuControl();
135
MyPopupMenu.MenuDirection = MenuDirection;
136
MyPopupMenu.MenuShowSubMenuIndicator = true;
137
MyPopupMenu.PopupMenuParentID = PopupMenuParentID;
138
MyPopupMenu.ShowVerticalMenuImageBar = true;
139
MyPopupMenu.ID = MenuControlID;
140
141
// create the popup-menu items
142
MyPopupMenu.PopupMenu.Add(new PopupMenuItemDetails(Services, ServicesAltText, ServicesName, ServicesJavaScript, ServicesImageUrl, null, ServicesDirection, ServicesTableID, true));
143
MyPopupMenu.PopupMenu.Add(new PopupMenuItemDetails(AboutMe, AboutMeAltText, AboutMeName, AboutMeJavaScript, AboutMeImageUrl, null, AboutMeDirection, AboutMeTableID, true));
144
MyPopupMenu.PopupMenu.Add(new PopupMenuItemDetails(UsefulLinks, UsefulLinksAltText, UsefulLinksName, UsefulLinksJavaScript, UsefulLinksImageUrl, null, UsefulLinksDirection, UsefulLinksTableID, true));
145
146
// create the services sub-menu
147
MyPopupMenu.PopupMenu[0].PopupSubMenus = new PopupMenuItemDetailsCollection();
148
MyPopupMenu.PopupMenu[0].PopupSubMenus.Add(new PopupMenuItemDetails(Presenter, PresenterAltText, PresenterName, PresenterJavaScript, PresenterImageUrl, null, MenuItemDirection.Vertical, PresenterTableID, false));
149
MyPopupMenu.PopupMenu[0].PopupSubMenus.Add(new PopupMenuItemDetails(Author, AuthorAltText, AuthorName, AuthorJavaScript, AuthorImageUrl, null, MenuItemDirection.Vertical, AuthorTableID, false));
150
MyPopupMenu.PopupMenu[0].PopupSubMenus.Add(new PopupMenuItemDetails(Architect, ArchitectAltText, ArchitectName, ArchitectJavaScript, ArchitectImageUrl, null, MenuItemDirection.Vertical, ArchitectTableID, false));
151
152
// create the about-me sub-menu
153
MyPopupMenu.PopupMenu[1].PopupSubMenus = new PopupMenuItemDetailsCollection();
154
MyPopupMenu.PopupMenu[1].PopupSubMenus.Add(new PopupMenuItemDetails(Resume, ResumeAltText, ResumeName, ResumeJavaScript, ResumeImageUrl, null, MenuItemDirection.Vertical, ResumeTableID, false));
155
MyPopupMenu.PopupMenu[1].PopupSubMenus.Add(new PopupMenuItemDetails(ContactMe, ContactMeAltText, ContactMeName, ContactMeJavaScript, ContactMeImageUrl, null, MenuItemDirection.Vertical, ContactMeTableID, false));
156
157
// create the useful links sub-menu
158
MyPopupMenu.PopupMenu[2].PopupSubMenus = new PopupMenuItemDetailsCollection();
159
MyPopupMenu.PopupMenu[2].PopupSubMenus.Add(new PopupMenuItemDetails(DeveloperLand, DeveloperLandAltText, DeveloperLandName, DeveloperLandJavaScript, DeveloperLandImageUrl, null, MenuItemDirection.Vertical, DeveloperLandTableID, false));
160
MyPopupMenu.PopupMenu[2].PopupSubMenus.Add(new PopupMenuItemDetails(CodeGuru, CodeGuruAltText, CodeGuruName, CodeGuruJavaScript, CodeGuruImageUrl, null, MenuItemDirection.Vertical, CodeGuruTableID, false));
161
MyPopupMenu.PopupMenu[2].PopupSubMenus.Add(new PopupMenuItemDetails(GotDotNet, GotDotNetAltText, GotDotNetName, GotDotNetJavaScript, GotDotNetImageUrl, null, MenuItemDirection.Vertical, GotDotNetTableID, false));
162
MyPopupMenu.PopupMenu[2].PopupSubMenus.Add(PopupMenuItemDetails.PopupMenuItemSeparator());
163
MyPopupMenu.PopupMenu[2].PopupSubMenus.Add(new PopupMenuItemDetails(Msdn, MsdnAltText, MsdnName, MsdnJavaScript, MsdnImageUrl, null, MenuItemDirection.Vertical, MsdnTableID, false));
164
165
// find the cell we use to add our content
166
Control ContentCell = BaseControl.FindControl(Controls, ControlContainer);
167
168
// event handler called when a menu item has been clicked
169
MyPopupMenu.MenuClicked += new MenuClicked(MyPopupMenu_MenuClicked);
170
171
// if we found the content cell then let's add the popup menu control to it
172
if (ContentCell != null)
173
ContentCell.Controls.Add(MyPopupMenu);
174
175
// the label which shows which menu item has been clicked
176
Message = BaseControl.CreateLabel(Controls, NoMenuItemClicked);
177
Message.CssClass = MessageStyle;
178
}
179
180
/// <summary>
181
/// event handler called when a menu item has been clicked
182
/// </summary>
183
/// <param name="Controls">the menu controls collection</param>
184
/// <param name="ClickedMenuItem">the selected menu item</param>
185
void MyPopupMenu_MenuClicked(ControlCollection Controls, MenuItemDetails ClickedMenuItem)
186
{
187
Message.Text = String.Format(ClickedMessage, ClickedMenuItem.DisplayText);
188
}
189
}
190
}
191

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

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

PopupMenuControl.js代码:
1
2
var VisibleSubMenus = '';
3
var MenuTimer = 0;
4
var CloseTimer = 0;
5
6
7
function EnterMenuCell(MenuCell,SubMenuTable)
8
{
9
// if the sub-menu-table is not displayed at the moment
10
if (SubMenuTable.style.display == 'none')
11
{
12
// then display it now
13
SubMenuTable.style.display = '';
14
15
// add this to the list of visible sub-menus; this is important if the user browses
16
// multiple cascaded sub-menus
17
if (VisibleSubMenus.length == 0)
18
VisibleSubMenus += SubMenuTable.id;
19
else
20
VisibleSubMenus += ',' + SubMenuTable.id;
21
}
22
}
23
24
//
25
// the user moves the mouse outside the menu cell
26
//
27
function LeaveMenuCell(MenuCell,SubMenuTable)
28
{
29
30
if (MenuTimer == 0)
31
MenuTimer = window.setInterval("CheckIfSubMenuToClose(" + SubMenuTable.id + ")", 20);
32
}
33
34
35
function LeaveSubMenuTable(SubMenuTable)
36
{
37
// get the list of visible sub-menus
38
var VisibleSubMenusArray = VisibleSubMenus.split(",");
39
40
// get the last visible sub-menu
41
var LastVisibleSubMenu = VisibleSubMenusArray[VisibleSubMenusArray.length - 1];
42
43
44
if ((SubMenuTable.style.display != 'none') & (LastVisibleSubMenu == SubMenuTable.id))
45
{
46
// closes the sub-menu table
47
CloseSubMenu(SubMenuTable);
48
49
50
if (MenuTimer == 0)
51
MenuTimer = window.setInterval("CloseAllSubMenus()", 20);
52
}
53
}
54
55
56
function CloseAllSubMenus()
57
{
58
// first clear the timer
59
if (MenuTimer != 0)
60
{
61
window.clearInterval(MenuTimer);
62
MenuTimer = 0;
63
}
64
65
// check if we have any sub-menus open
66
if (VisibleSubMenus.length > 0)
67
{
68
// get the list of visible sub-menus
69
var VisibleSubMenusArray = VisibleSubMenus.split(",");
70
71
// now loop through all visible sub-menus and close them too
72
for (Count=0; Count < VisibleSubMenusArray.length; Count++)
73
{
74
// get a reference to the visible sub-menu
75
var SubMenu = document.getElementById(VisibleSubMenusArray[Count]);
76
77
// and now hide it
78
SubMenu.style.display = 'none';
79
}
80
81
// reset the list of visible sub-menus
82
VisibleSubMenus = '';
83
}
84
}
85
86
//
87
// the user moves the mosue cursor over the sub-menu table
88
//
89
function EnterSubMenuTable(SubMenuTable)
90
{
91
92
if (MenuTimer != 0)
93
{
94
window.clearInterval(MenuTimer);
95
MenuTimer = 0;
96
}
97
}
98
99
100
function CheckIfSubMenuToClose(SubMenuTable)
101
{
102
// first clear the timer itself
103
if (MenuTimer != 0)
104
{
105
window.clearInterval(MenuTimer);
106
MenuTimer = 0;
107
}
108
109
// now close the sub-menu table
110
CloseSubMenu(SubMenuTable);
111
}
112
113
//
114
// closes the sub-menu table and removes it from the list of visible sub-menus
115
//
116
function CloseSubMenu(SubMenuTable)
117
{
118
// now close the sub-menu
119
SubMenuTable.style.display = 'none';
120
121
// get the list of visible sub-menus
122
var VisibleSubMenusArray = VisibleSubMenus.split(",");
123
124
// now we rebuild the list of visible sub-menus by excluding the sub-menu we
125
// just closed
126
VisibleSubMenus = '';
127
128
// loop through all existing sub-menus
129
for (Count=0; Count < VisibleSubMenusArray.length; Count++)
130
131
// if the sub-menu is the same as the one we just closed then ignore it;
132
// otherwise add it again
133
if (VisibleSubMenusArray[Count] != SubMenuTable.id)
134
if (VisibleSubMenus.length > 0)
135
VisibleSubMenus += "," + VisibleSubMenusArray[Count];
136
else
137
VisibleSubMenus = VisibleSubMenusArray[Count];
138
}
139
140
141
function SetControlPosition(SubMenuTable,ParentTable,ParentCell,ParentMenuDirection,OffsetX,OffsetY)
142
{
143
// we position the control absolute
144
SubMenuTable.style.position = 'absolute';
145
146
// parent menu is horizontal, so we position the sub-menu at left/bottom
147
if (ParentMenuDirection == 'Horizontal')
148
{
149
SubMenuTable.style.left = ParentTable.offsetLeft + ParentCell.offsetLeft - 1;
150
SubMenuTable.style.top = ParentTable.offsetTop + ParentTable.offsetHeight - 1;
151
}
152
else
153
154
// parent menu is vertical, so we position the sub-menu at right/top
155
if (ParentMenuDirection == 'Vertical')
156
{
157
SubMenuTable.style.left = ParentTable.offsetLeft + ParentTable.offsetWidth - 1;
158
SubMenuTable.style.top = ParentTable.offsetTop + ParentCell.offsetTop - 1;
159
}
160
161
// there is no parent-menu; this is a popup menu which will be positioned in the
162
// middle of the owning control
163
else
164
{
165
SubMenuTable.style.left = ParentTable.offsetLeft + (ParentTable.offsetWidth / 2) + 1 + Number(OffsetX);
166
SubMenuTable.style.top = ParentTable.offsetTop + (ParentTable.offsetHeight / 2) + 1 + Number(OffsetY);
167
168
// add any body margin we have
169
SubMenuTable.style.left = Number(SubMenuTable.style.left.replace('px','')) + Number(document.body.leftMargin);
170
SubMenuTable.style.top = Number(SubMenuTable.style.top.replace('px','')) + Number(document.body.topMargin);
171
}
172
}
173
174
175
function ShowPopupMenu(PopupOwnerControl,PopupTableControl,OffsetX,OffsetY)
176
{
177
// position the popup menu in the middle of the owner control
178
SetControlPosition(PopupTableControl, PopupOwnerControl, null, 'popup', OffsetX, OffsetY);
179
180
// show the popup-menu
181
PopupTableControl.style.display = '';
182
183
// give the popup menu table the focus so we know when the user clicks anywhere
184
// else (the control looses then the focus
185
PopupTableControl.focus();
186
}
187
188
189
function ClosePopupMenu(PopupOwnerControl,PopupTableControl)
190
{
191
if (CloseTimer == 0)
192
CloseTimer = window.setInterval("ClosePopupMenuDelayed(" + PopupOwnerControl.id + "," + PopupTableControl.id + ")", 190);
193
}
194
195
196
function ClosePopupMenuDelayed(PopupOwnerControl,PopupTableControl)
197
{
198
// clears first the timer
199
if (CloseTimer != 0)
200
{
201
window.clearInterval(CloseTimer);
202
CloseTimer = 0;
203
}
204
205
// we hide the popup menu
206
PopupTableControl.style.display = 'none';
207
208
// close any open sub-menu
209
CloseAllSubMenus();
210
}
211

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

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

PopupMenuControl.css代码:
1
.PopupMenuTableStyle
2
{
3
border: groove 2px white;
4
background-color: black;
5
position: relative;
6
left: 0px;
7
top: 0px;
8
}
9
.PopupMenuRowStyle
10
{
11
vertical-align: middle;
12
}
13
.PopupMenuCellStyle
14
{
15
background-color: #ececec;
16
text-align: left;
17
width: 180px;
18
height: 20px;
19
}
20
.PopupMenuCellHighlightedStyle
21
{
22
background-color: #ccccff;
23
text-align: left;
24
width: 180px;
25
height: 20px;
26
}
27
.PopupMenuLinkStyle
28
{
29
font: normal normal bold small/normal Arial;
30
text-decoration: none;
31
white-space: nowrap;
32
color: blue;
33
cursor: hand;
34
line-height: 18px;
35
}
36
.PopupMenuLinkHighlightedStyle
37
{
38
font: normal normal bolder small/normal Arial;
39
text-decoration: none;
40
white-space: nowrap;
41
color: #ffffcc;
42
color: blue;
43
cursor: hand;
44
line-height: 18px;
45
}
46
.MenuSeparatorCellStyle
47
{
48
background-color: #ececec;
49
height: 1px;
50
padding: 0px 0px 0px 0px;
51
margin: 0px 0px 0px 0px;
52
}
53
.MenuSeparatorStyle
54
{
55
border-top: ridge 1px;
56
width: 100%;
57
color: white;
58
height: 1px;
59
}
60
.PopupMenuImageBarStyle
61
{
62
background-color: #cccccc;
63
width: 24px;
64
}
65

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

源码下载地址:
https://files.cnblogs.com/Terrylee/PopupMenuControlSample.rar
支持TerryLee的创业产品Worktile
Worktile,新一代简单好用、体验极致的团队协同、项目管理工具,让你和你的团队随时随地一起工作。完全免费,现在就去了解一下吧。
https://worktile.com
Worktile,新一代简单好用、体验极致的团队协同、项目管理工具,让你和你的团队随时随地一起工作。完全免费,现在就去了解一下吧。
https://worktile.com
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)