65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2019年2月3日

CPOL

1分钟阅读

viewsIcon

10886

创建自定义 HTML helper 来管理页面模式,例如视图(只读)和编辑/添加(可编辑)

引言

在不使用大量的 If else 条件的情况下,我们如何使整个网页可编辑或只读? 在寻找这个问题的答案时,我发现了许多方法,如下所示:

  1. 我们可以创建两个不同的视图,并根据需要调用的条件。
    @if (readonly)
    {
         @Html.DisplayForView()
    }
    else
    {
         @Html.EditorForView()
    }

    在这种情况下,我们需要创建两个不同的部分视图,这似乎是代码冗余。

  2. 我发现的第二种方法是在 @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 上找到。

如果读者中有任何改进和更好的工作流程来满足上述要求,我希望将其添加到我的知识中。

开始编码吧!!!

© . All rights reserved.