ASP.NET MVC : 创建工具栏控件
在 ASP.NET MVC 中创建工具栏控件
引言
背景
设计考虑
- 控件应封装所有必需的 HTML、Java 脚本、样式表
- 渲染视图应该只关心提供控制器信息和需要与工具栏绑定的操作
- 并非控制器中的所有操作都需要与工具栏绑定
实现
控件实现灵感来自 Seth juarez 的文章。
一个设计考虑是并非所有控制器的操作都需要与工具栏绑定,我们如何实现这一点。
我有两个选择
- 在视图中创建控件时,我传递要与工具栏绑定的操作列表
- 为操作方法创建一个自定义属性,在控制器中应用此属性。在渲染控件时,控件检查此属性并创建所需的工具栏项目。
我选择了第二个选项,因为我可以跨多个视图重用我的工具栏项目定义,并且我不必在创建工具栏时手动传递要使用的操作。
因此,让我们创建自定义属性 ToolBarItemAttribute
[AttributeUsage(AttributeTargets.Method, AllowMultiple=false,Inherited=false)]
public sealed class TooBarItemAttribute:Attribute
{
public string ToolTip { get; set; }
}
我创建了一个具有单个属性 tooltip 的自定义属性,该属性稍后将用于显示控制器操作的用户友好文本。Attribut usage 设置为 method,因为我们希望确保此属性只能应用于方法。
创建 ToolBar 控件
工具栏控件只不过是一系列封装在 HTML <form> 标记中的按钮。为了在客户端更改 <form> 元素的 action,我们需要一个 Java 脚本,该脚本根据按下的按钮修改表单元素的 action 属性。我们需要在渲染控件时注入此 Javascript,因此让我们创建 RenderJavaScript
private string RenderJavaScript()
{
StringBuilder JavaScript = new StringBuilder();
JavaScript.AppendFormat(@"<script language=""javascript"" type=""text/javascript"">{0}",Environment.NewLine);
JavaScript.AppendFormat(@" function OnToolBarClick(action){0}",Environment.NewLine);
JavaScript.AppendFormat(@" {{{0}", Environment.NewLine);
JavaScript.AppendFormat(@" var form = document.getElementById(""{1}_Form"");{0}", Environment.NewLine, _formname);
JavaScript.AppendFormat(@" form.action = action;{0}",Environment.NewLine);
JavaScript.AppendFormat(@" form.submit();{0}",Environment.NewLine);
JavaScript.AppendFormat(@" }}{0}", Environment.NewLine);
JavaScript.AppendFormat(@"</Script>{0}", Environment.NewLine);
return JavaScript.ToString();
}
其次,我们需要一个函数来创建 Action URL
private string GetActionUrl(string actionName) { string controllerName = _controllerType.Name; if (controllerName.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)) { controllerName = controllerName.Remove(controllerName.Length - 10, 10); } RouteValueDictionary values = new RouteValueDictionary(); values = values ?? new RouteValueDictionary(); values.Add("controller", controllerName); values.Add("action", actionName); VirtualPathData vpd = RouteTable.Routes.GetVirtualPath(_helper.ViewContext, values); return (vpd == null) ? null : vpd.VirtualPath; }
第三,我们需要一个函数来渲染工具栏项目。此函数迭代控制器的所有方法,这些方法具有 ToolBarItemAttirbut 设置和零参数长度。在按钮中,我们在 onclick 事件上设置我们的 javascript 函数来更改主表单 action 属性。此函数调用 GetActionURL
private void WriteToolBarItems() { var methods = from method in _controllerType.GetMethods() where method.GetCustomAttributes(typeof(TooBarItemAttribute),false).Length > 0 & method.GetParameters().Length == 0 select method; StringBuilder sb = new StringBuilder(); sb.AppendFormat(@"<div>{0}", Environment.NewLine); if (methods.Count() == 0) sb.AppendFormat(@"<span><strong>{0} doesn't have any action with Attribute ToolBarItem<Strong></span>",_controllerType.Name); foreach (MethodInfo method in methods) { sb.AppendFormat(@"<span>{0}", Environment.NewLine); sb.AppendFormat(@"<button onclick=""OnToolBarClick('{1}')"" value=""{2}"">{2}</button>{0}",Environment.NewLine,GetActionUrl(method.Name),GetActionToolTip(method)); sb.AppendFormat(@"</span>{0}", Environment.NewLine); } sb.AppendFormat(@"</div>{0}", Environment.NewLine); _context.Response.Write(sb.ToString()); }
工具栏控件中还有一些用于完成标记的函数,不值得提及,您可以在代码中检查这些函数。
最后,我们有一个构造函数,它在创建控件方面起着非常重要的作用。Htmlhelper 使我们可以访问响应上下文、控制器类型以检索和设置操作、自动创建的表单元素的 formname,以及工具栏相对于您可能创建的其他表单子控件的对齐方式(顶部、底部)
public ToolBar(HtmlHelper helper, Type controllerType, string formName, ToolBarAlignment alignment): this(helper,controllerType,formName,FormMethod.Post,alignment) { } private ToolBar(HtmlHelper helper,Type controllerType,string formName,FormMethod formMethod, ToolBarAlignment alignment) { _helper = helper; _context = helper.ViewContext.HttpContext; _controllerType = controllerType; _formname = formName; _formMethod = formMethod; _toolBarAlignment = alignment; WriteStartTag(); if (_toolBarAlignment == ToolBarAlignment.Top) WriteToolBarItems(); }
使用代码
此代码需要 ASP.NET Prview 4 和 visiual sudio 2008
使用此工具栏是一个两步过程
1 将 ToolBarItemAttriibute 应用于控制器中您要与工具栏绑定的方法
public class CustomerController:Controller { public ActionResult Index() { return View(); } [TooBarItem(ToolTip="Add Customer")] public ActionResult Add() { string CustomerName = this.ReadFromRequest("CustomerName"); ViewData["CustomerName"] = CustomerName; return View(); } }
<%using(Html.ToolBarControl(typeof(MVCToolBarExp.Controllers.CustomerController),"formWithToolBar",ToolBarAlignment.Top)) %>
<%{%>
<div><span>Customer Name:</span><%=Html.TextBox("CustomerName") %></div>
<%} %>
附加的源代码包含工具栏控件源代码以及 dumy 测试项目。请告诉我您的意见以及任何替代实施方式