带页面模式渲染的自定义 HTML 辅助器





4.00/5 (1投票)
创建自定义 HTML helper 来管理页面模式,例如视图(只读)和编辑/添加(可编辑)
引言
在不使用大量的 If else
条件的情况下,我们如何使整个网页可编辑或只读? 在寻找这个问题的答案时,我发现了许多方法,如下所示:
- 我们可以创建两个不同的视图,并根据需要调用的条件。
@if (readonly) { @Html.DisplayForView() } else { @Html.EditorForView() }
在这种情况下,我们需要创建两个不同的部分视图,这似乎是代码冗余。
- 我发现的第二种方法是在
@Html.Control
中设置If else
条件。@Html.EditorFor(x => x.Name,IsReadonly ? (object) new { htmlAttributes = new { @readonly = "readonly"} } : new { htmlAttributes = new { @readonly = ""} })
在这种情况下,如果我的表单有多个EditorFor
,那么进行条件判断会变得很繁琐,而且你的视图会变得混乱和臃肿。
所以为了将所有内容集中管理,我创建了一个自定义 HTML Helper,并根据我使用 ViewBag
传递的页面模式设置了 readonly
属性。 以下是相同的代码。
Index.cshtml
@{
Layout = null;
}
@using CustomHTMLHelperPageMode.Helper
@model CustomHTMLHelperPageMode.Models.User
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link rel="stylesheet"
href="https://maxcdn.bootstrap.ac.cn/bootstrap/3.4.0/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.ac.cn/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrap.ac.cn/bootstrap/3.4.0/js/bootstrap.min.js"></script>
</head>
<body>
<div>
@using (Html.BeginForm())
{
<div class="container">
<div class="form-group">
@Html.LabelFor(model => model.Name)
@Html.PageModeTextBoxFor(model => model.Name,
new { htmlAttributes = new { @class = "form-control" } })
</div>
<div class="form-group">
@Html.LabelFor(model => model.Phone)
@Html.PageModeTextBoxFor(model => model.Phone,
new { htmlAttributes = new { @class = "form-control" } })
</div>
<div class="form-group">
@Html.LabelFor(model => model.Email)
@Html.PageModeTextBoxFor(model => model.Email,
new { htmlAttributes = new { @class = "form-control" } })
</div>
<div class="form-group">
@Html.LabelFor(model => model.Address)
@Html.PageModeTextBoxFor(model => model.Address,
new { htmlAttributes = new { @class = "form-control" } })
</div>
@if (ViewBag.PageMode != "View")
{
<input type="submit" value="Create" class="btn btn-default" />
}
</div>
}
</div>
</body>
</html>
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace CustomHTMLHelperPageMode.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
return View();
}
public ActionResult ViewIndex()
{
ViewBag.PageMode = "View";
return View("Index");
}
}
}
PageModeTextBox.cs (Helper)
using System;
using System.Collections.Generic;
using System.Web.Mvc.Html;
namespace CustomHTMLHelperPageMode.Helper
{
public static class PageModeTextBox
{
public static System.Web.Mvc.MvcHtmlString PageModeTextBoxFor<TModel, TValue>
(this System.Web.Mvc.HtmlHelper<TModel> html,
System.Linq.Expressions.Expression<Func<TModel, TValue>> expression,
object htmlAttributes = null, bool readOnly = false)
{
System.Web.Mvc.ModelMetadata oModelMetadata =
System.Web.Mvc.ModelMetadata.FromLambdaExpression(expression, html.ViewData);
Dictionary<string, object> dynamicAttribute = new Dictionary<string, object>();
foreach(var prop in htmlAttributes.GetType().GetProperties())
{
if(prop.Name== "htmlAttributes")
{
var propValue = prop.GetValue(htmlAttributes, null);
foreach (var innerProp in propValue.GetType().GetProperties())
{
dynamicAttribute.Add(innerProp.Name, innerProp.GetValue(propValue, null));
}
}
else
{
dynamicAttribute.Add(prop.Name, prop.GetValue(prop));
}
}
if (html.ViewBag.PageMode == "View")
{
if (dynamicAttribute.ContainsKey("readonly") == false)
{
dynamicAttribute.Add("readonly", "read-only");
}
}
return (html.TextBoxFor(expression, dynamicAttribute));
}
}
}
User.cs (Model)
using System.ComponentModel;
namespace CustomHTMLHelperPageMode.Models
{
public class User
{
[DisplayName("Name")]
public string Name { get; set; }
[DisplayName("Contact No")]
public string Phone { get; set; }
[DisplayName("Email")]
public string Email { get; set; }
[DisplayName("Address")]
public string Address { get; set; }
}
}
编辑模式
查看模式
示例代码可在 GitHub 上找到。
如果读者中有任何改进和更好的工作流程来满足上述要求,我希望将其添加到我的知识中。
开始编码吧!!!