Використання ASP.NET контролу Menu у проектах MVC.
На цієї сторінці я хотів би зупинитися на дуже корисному контролі ASP.NET Menu - та розповісти про мій засіб його використання у проектах MVC. Для того, щоб використовувати цей контрол - потрібно три невеличкі хитрощі:
- По-перше, щоб взагалі хоч-якось вбудувати цей котрол на Master Page у MVC-проеті, потрібно обкласти цей котрол дужками <form runat="server">.
1: <%@ Master Language="VB" Inherits="System.Web.Mvc.ViewMasterPage" %>
2:
3: <!DOCTYPE html>
4: <html>
5: <head runat="server">
.....11: </head>
12: <body>
.....37: <div class="clear hideSkiplink">
38: <form id="Form1" runat="server">
39: <asp:Menu ID="NavigationMenu" runat="server" CssClass="menu" EnableViewState="false"
40: IncludeStyleBlock="false" Orientation="Horizontal">
41: <Items>
42: <asp:MenuItem NavigateUrl="../../Home/" Text="Home" />
43: <asp:MenuItem NavigateUrl="../../Calendar/" Text="Calendar" />
44: <asp:MenuItem NavigateUrl="../../Login/" Text="Login" />
45: <asp:MenuItem NavigateUrl="../../About/" Text="About Us" />
46: </Items>
47: </asp:Menu>
48: </form>
49: </div>
.....61: </body>
62: </html>
- Але після цього контрол працює так криво, що на нього неможна дивитися. По-перше він мертвий, тобто коли переходиш мишкою з одного пункта меню на іншій - ніякого роловера чи реакції на мишку немає. Бо цей конрол має статичний стиль (у моему випадку уже налагоджений - ось такий):
159: div.hideSkiplink
160: {
161: background-color:#3a4f63;
162: width:100%;
163: }
164:
165: div.menu
166: {
167: padding: 4px 0px 4px 8px;
168: }
169:
170: div.menu ul
171: {
172: list-style: none;
173: margin: 0px;
174: padding: 0px;
175: width: auto;
176: }
177:
178 div.menu ul li a, div.menu ul li a:visited
179: {
180: background-color: #465c71;
181: border: 1px #4e667d solid;
182: color: #dde4ec;
183: display: block;
184: line-height: 1.35em;
185: padding: 4px 20px;
186: text-decoration: none;
187: white-space: nowrap;
188: }
189:
190: div.menu ul li a:hover
191: {
192: background-color: #bfcbd6;
193: color: #465c71;
194: text-decoration: none;
195: }
196:
197: div.menu ul li a:active
198: {
199: background-color: #465c71;
200: color: #cfdbe6;
201: text-decoration: none;
202: }
Контрол має дуже складну структуру наслідування стилей CSS.
Тому для того, щоб контрол ожив - треба по-перше налагодити найважливіший стиль Hover (стрічка 190), який буде перекривати основні стилі контрола, задані у стрічці 178.
- Але й після цього контрол працює криво, нестандартно та незрозуміло для користувачів сайтів, бо конкретно вибраний пункт не підсвітлюваться і не зрозуміло у якому пункті меню користувач сайту у цей час знаходиться.
Щоб подолати цю проблему, потрібно зробити третю хитрість. У першій стрічки контрола .master - замінити наслідування від мікрософтовского класу на наслідуванні від свого классу, як я це розповідав на цій сторінці - Додаток про загальний код у проектах MVC. Тобто перша стрічка Master Page буде ось така:
1: <%@ Master Language="VB" Inherits="OCMR.MasterSuperAdmin" %>
2:
3: <!DOCTYPE html>
4: <html>
5: <head runat="server">
.....
OCMR у данному випадку - це ім'я DLL (за замовчуванням ім'я проекту теж).
Далі потрібно зробити класс кода, який буде вже наслідуватися від System.Web.Mvc.ViewMasterPage - наприклад ось такий:
1: Public Class MasterShared
2: Inherits System.Web.Mvc.ViewMasterPage
3:
4:
5: Private Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
6: Dim M1 As System.Web.Mvc.ViewMasterPage = DirectCast(sender, System.Web.Mvc.ViewMasterPage)
7: Dim URL As String = M1.Request.AppRelativeCurrentExecutionFilePath.ToLower
8: Dim Menu1 As System.Web.UI.WebControls.Menu = M1.FindControl("NavigationMenu")
9: MasterSelectItem.SelectCurrent(Menu1, URL)
10: End Sub
11:
12: End Class
Цей код короткий, але важливий - у ньому будується лінк на контрол і у стрічці 9 викликається функция, яка змінить класс активного тега LI (це робиться у стрічці 85). Зрозуміло, що цей код виконується у постбеці, але для плашці сайта це, мабуть, найкраще рішення.
1: Public Class MasterSelectItem
2:
3: Shared Sub SelectCurrent(Menu1 As System.Web.UI.WebControls.Menu, URL As String)
4:
5: If URL = "~/" Or URL = "~/Home/".ToLower Or URL = "~/Home/Index/".ToLower Or URL = "~/Home".ToLower Or URL = "~/Home/Index".ToLower Then
6: SelectItems("Home", Menu1)
7: ElseIf URL = "~/Calendar/".ToLower Or URL = "~/Calendar/Index/".ToLower Or URL = "~/Calendar".ToLower Or URL = "~/Calendar/Index".ToLower Then
8: SelectItems("Calendar", Menu1)
.....21: ElseIf URL.ToLower.Contains("/login/lostpassword") Then
22: SelectItems("Login", Menu1)
23: '
.....58: ElseIf URL.ToLower.Contains("admin/index") Or URL = "~/Admin/".ToLower Or URL = "~/Admin".ToLower Then
59: SelectItems("Admin", Menu1)
60: ElseIf URL = "~/Admin/Home/".ToLower Then
.....72: ElseIf URL = "~/Admin/PrintHome/".ToLower Then
73: SelectItems("Print Home", Menu1)
74: ElseIf URL = "~/Admin/Users/".ToLower Then
75: SelectItems("Users", Menu1)
76: End If
77: End Sub
78:
79: Shared Sub SelectItems(ServerValue As String, Menu1 As System.Web.UI.WebControls.Menu)
80: For Each One As System.Web.UI.WebControls.MenuItem In Menu1.Items
81: One.Selected = False
82: Next
83: For Each One As System.Web.UI.WebControls.MenuItem In Menu1.Items
84: If One.Value = ServerValue Then
85: One.Selected = True
86: Exit Sub
87: End If
88: Next
89: End Sub
90: End Class
Виконання стрічки 88 цього коду приводить до того, що у ієрархії CSS з'являється додатковий стиль selected:
Тому остання крапка цього налаштування - це додати стиль selected з поміткою !important, щоб перекрити і головні стилі, задані у стрічці 178, і стилі Hover, задані у стрічці 190:
317: .menu a.static.selected
318: {
319: background-color: #1B1A42 !important;
320: color: #FFF !important;
321: text-decoration: none !important;
322: }
Лише після цього контрол починає працювати звично для користувачів інтернет-сайтів.
Як бачите, лише застосувавши послідовно усі три налаштування один за одним, можна застосувати старий ASP.NET контрол Menu у нових MVC-проектах, при чому лише після ціх хітрощив контрол Menu буде мати достаньо стандартну для интернета поведінку.