原文:MVC生成CheckBoxList并对其验证

通过扩展方法,可以让CheckBox水平排列,生成CheckBoxList,正如"MVC扩展生成CheckBoxList并水平排列"一文。但,如何对生成的CheckBoxList验证呢?比如要求至少勾选一项:

 

□ 思路

在强类型视图页中,@Html.EditorFor(model => model.属性, "模版名称", new{ ...路由数据...}),模版名称对应Views/Shared/EditorTemplates/CheckBoxList.cshtml部分视图,路由数据用来传递生成CheckBoxList所需要的一切,并在CheckBoxList.cshtml中显示错误信息,最后CheckBoxList的生成交给扩展方法。

□ Model

    public class Course
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

using System.ComponentModel.DataAnnotations;

namespace MvcApplication1.Models
{
    public class Student
    {
        [Display(Name = "姓名")]
        [Required(ErrorMessage = "必填")]
        [StringLength(100, ErrorMessage = "最大长度100")]
        public string Name { get; set; }

        [Display(Name = "所选课程")]
        [Required(ErrorMessage = "至少选择一个课程")]
        public string Courses{ get; set; }
    }
}

 

□ 在_Layout.cshtml中启用客户端异步验证

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("/bundles/jqueryval") //启用客户端异步验证
    @RenderSection("scripts", required: false)

 

□ Home/Index.cshtml

@using MvcApplication1.Infrastructure.Enums
@model MvcApplication1.Models.Student
 
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
 
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
 
    <fieldset>
        <legend>Student</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
        
        <div class="editor-label">
            @Html.LabelFor(model => model.Courses)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Courses, "CheckBoxList", new
            {
                TagName = "Courses",
                CheckBoxItems = ViewBag.Course,
                Position = Position.Horizontal,
                Numbers = 3
            })
        </div>
        
        <p>
            <input type="submit" value="创建"/>
        </p>
    </fieldset>
}
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

其中,用到了有关CheckBoxList水平或垂直排列的一个枚举:

namespace MvcApplication1.Infrastructure.Enums

{

    public enum Position

    {

        Horizontal,

        Vertical

    }

}  

生成CheckBoxList的路由数据,以及模版名称:

            @Html.EditorFor(model => model.Courses, "CheckBoxList", new

            {

                TagName = "Courses",

                CheckBoxItems = ViewBag.Course,

                Position = Position.Horizontal,

                Numbers = 3

            })

 

□ Views/Shared/EditorTemplates/CheckBoxList.cshtml

@using MvcApplication1.Infrastructure.Enums
@{
    var required = false;
    object validationMessage = string.Empty;
 
    //获取客户端验证属性
    var validationAttributes = Html.GetUnobtrusiveValidationAttributes(""); 
    if (validationAttributes.ContainsKey("data-val") && validationAttributes.ContainsKey("data-val-required"))
    {
        required = true;
        if (!validationAttributes.TryGetValue("data-val-required", out validationMessage))
        {
            validationMessage = "This field is required.";
        }
        validationAttributes.Add("required","required");
    }
 
    var tagName = ViewData["TagName"] == null ? "CheckBoxList" : (string)ViewData["TagName"];
    var checkboxItems = ViewData["CheckBoxItems"] == null ? new List<SelectListItem>() : (IEnumerable<SelectListItem>)ViewData["CheckBoxItems"];
    var position = ViewData["Position"] == null ? Position.Horizontal : (Position)ViewData["Position"];
 
    var numbers = 0;
    if (ViewData["Numbers"] == null)
    {
        numbers = 1;
    }
    else if (!int.TryParse(ViewData["Numbers"].ToString(), out numbers))
    {
        numbers = 1;
    }
    else
    {
        numbers = (int)ViewData["Numbers"];
    }
}
 
@Html.CheckBoxList(
tagName,
checkboxItems,
new RouteValueDictionary(validationAttributes),
position,
numbers)
 
@if (required)
{
    <span class="field-validation-valid" data-valmsg-for="@(tagName)" data-valmsg-replace="false">
        @validationMessage
    </span>
}
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

□ 生成CheckBoxList的扩展方法

using System.Collections.Generic;
using System.Linq;
using System.Text;
using MvcApplication1.Infrastructure.Enums;
 
namespace System.Web.Mvc
{
    public static class CheckBoxListExtensions
    {
        #region 水平方向
        /// <summary>
        /// CheckBoxList
        /// </summary>
        /// <param name="htmlHelper">HTML helper</param>
        /// <param name="name"></param>
        /// <param name="listInfo"></param>
        /// <param name="htmlAttributes"></param>
        /// <param name="number">每行显式的个数</param>
        /// <returns></returns>
        public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper,
            string name,
            IEnumerable<SelectListItem> listInfo,
            IDictionary<string, object> htmlAttributes,
            int number)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentException("必须给CheckBoxList一个name值", "name");
            }
            if (listInfo == null)
            {
                throw new ArgumentNullException("listInfo", "List<SelectListItem> listInfo不能为null");
            }
 
            var selectListItems = listInfo as SelectListItem[] ?? listInfo.ToArray();
            if (!selectListItems.Any())
            {
                throw new ArgumentException("List<SelectListItem> listInfo 至少有一组资料", "listInfo");
            }
 
            var sb = new StringBuilder();
            var lineNumber = 0;
            foreach (var info in selectListItems)
            {
                lineNumber++;
                var builder = new TagBuilder("input");
                if (info.Selected)
                {
                    builder.MergeAttribute("checked", "checked");
                }
                builder.MergeAttributes(htmlAttributes);
                builder.MergeAttribute("type", "checkbox");
                builder.MergeAttribute("value", info.Value);
                builder.MergeAttribute("name", name);
                builder.MergeAttribute("id", string.Format("{0}_{1}", name, info.Value));
                sb.Append(builder.ToString(TagRenderMode.Normal));
 
                var labelBuilder = new TagBuilder("label");
                labelBuilder.MergeAttribute("for", string.Format("{0}_{1}", name, info.Value));
                labelBuilder.InnerHtml = info.Text;
                sb.Append(labelBuilder.ToString(TagRenderMode.Normal));
 
                if (number == 0 || (lineNumber % number == 0))
                {
                    sb.Append("<br />");
                }
            }
            return MvcHtmlString.Create(sb.ToString());
        }
 
        public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper,
            string name,
            IEnumerable<SelectListItem> listInfo)
        {
            return htmlHelper.CheckBoxList(name, listInfo, (IDictionary<string, object>) null, 0);
        }
        #endregion
 
        #region 垂直方向
 
        public static MvcHtmlString CheckBoxListVertical(this HtmlHelper htmlHelper,
            string name,
            IEnumerable<SelectListItem> listInfo,
            IDictionary<string, object> htmlAttributes,
            int columnNumber = 1)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentException("必须给CheckBoxList的name属性赋值", "name");
            }
            if (listInfo == null)
            {
                throw new ArgumentNullException("listInfo", "List<SelectListInfo> listInfo不能为null");
            }
 
            var selectListItmes = listInfo as SelectListItem[] ?? listInfo.ToArray();
            if (!selectListItmes.Any())
            {
                throw new ArgumentException("List<SelectListItem> listInfo不能为null","listInfo");
            }
 
            var dataCount = selectListItmes.Count();
            var rows = Convert.ToInt32(Math.Ceiling(Convert.ToDecimal(dataCount)/Convert.ToDecimal(columnNumber)));
            if (dataCount <= columnNumber || dataCount - columnNumber == 1)
            {
                rows = dataCount;
            }
 
            var wrapBuilder = new TagBuilder("div");
            wrapBuilder.MergeAttribute("style","float:left; line-height:25px; padding-right:5px;");
            var wrapStart = wrapBuilder.ToString(TagRenderMode.StartTag);
            var wrapClose = string.Concat(wrapBuilder.ToString(TagRenderMode.EndTag),
                " <div style=\"clear:both;\"></div>");
            var wrapBreak = string.Concat("</div>", wrapBuilder.ToString(TagRenderMode.StartTag));
 
            var sb = new StringBuilder();
            sb.Append(wrapStart);
 
            var lineNumber = 0;
            foreach (var info in selectListItmes)
            {
                var builder = new TagBuilder("input");
                if (info.Selected)
                {
                    builder.MergeAttribute("checked","checked");
                }
                builder.MergeAttributes(htmlAttributes);
                builder.MergeAttribute("type","checkbox");
                builder.MergeAttribute("value", info.Value);
                builder.MergeAttribute("name", name);
                builder.MergeAttribute("id", string.Format("{0}_{1}",name, info.Value));
                sb.Append(builder.ToString(TagRenderMode.Normal));
 
                var labelBuilder = new TagBuilder("label");
                labelBuilder.MergeAttribute("for", string.Format("{0}_{1}", name, info.Value));
                labelBuilder.InnerHtml = info.Text;
                sb.Append(labelBuilder.ToString(TagRenderMode.Normal));
 
                lineNumber++;
 
                if (lineNumber.Equals(rows))
                {
                    sb.Append(wrapBreak);
                    lineNumber = 0;
                }
                else
                {
                    sb.Append("<br />");
                }
            }
            sb.Append(wrapClose);
            return MvcHtmlString.Create(sb.ToString());
        }
        #endregion
 
        #region 水平或垂直方向
 
        public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper,
            string name,
            IEnumerable<SelectListItem> listInfo,
            IDictionary<string, object> htmlAttributes,
            Position position = Position.Horizontal,
            int number = 0)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentException("必须给CheckBoxList的name属性赋值","name");
            }
            if (listInfo == null)
            {
                throw new ArgumentNullException("listInfo", "List<SelectListItem> listInfo不能为null");
            }
            var selectListItems = listInfo as SelectListItem[] ?? listInfo.ToArray();
            if (!selectListItems.Any())
            {
                throw new ArgumentException("List<SelectListItem> listInfo至少要一组资料","listInfo");
            }
 
            var sb = new StringBuilder();
            var lineNumber = 0;
            switch (position)
            {
                case Position.Horizontal:
                    foreach (var info in selectListItems)
                    {
                        lineNumber++;
                        sb.Append(CreateCheckBoxItem(info, name, htmlAttributes));
 
                        if (number == 0 || (lineNumber%number == 0))
                        {
                            sb.Append("<br />");
                        }
                    }
                    sb.Append("<br />");
                    break;
                case Position.Vertical:
                    var dataCount = selectListItems.Count();
                    var rows = Convert.ToInt32(Math.Ceiling(Convert.ToDecimal(dataCount)/Convert.ToDecimal(number)));
                    if (dataCount <= number || dataCount - number == 1)
                    {
                        rows = dataCount;
                    }
 
                    var wrapBuilder = new TagBuilder("div");
                    wrapBuilder.MergeAttribute("style","float:left; line-height:25px; padding-right:5px;");
                    var wrapStart = wrapBuilder.ToString(TagRenderMode.StartTag);
                    var wrapClose = string.Concat(wrapBuilder.ToString(TagRenderMode.EndTag), " <div style=\"clear:both;\"></div>");
                    var wrapBreak = string.Concat("</div>", wrapBuilder.ToString(TagRenderMode.StartTag));
                    sb.Append(wrapStart);
 
                    foreach (var info in selectListItems)
                    {
                        lineNumber++;
                        sb.Append(CreateCheckBoxItem(info, name, htmlAttributes));
 
                        if (lineNumber.Equals(rows))
                        {
                            sb.Append(wrapBreak);
                            lineNumber = 0;
                        }
                        else
                        {
                            sb.Append(wrapClose);
                        }
                    }
                    sb.Append(wrapClose);
                    break;
            }
            return MvcHtmlString.Create(sb.ToString());
        }
 
        internal static string CreateCheckBoxItem(SelectListItem info, string name,
            IDictionary<string, object> htmlAttributes)
        {
            var sb = new StringBuilder();
            var builder = new TagBuilder("input");
            if (info.Selected)
            {
                builder.MergeAttribute("checked","checked");
            }
            builder.MergeAttributes(htmlAttributes);
            builder.MergeAttribute("type", "checkbox");
            builder.MergeAttribute("value", info.Value);
            builder.MergeAttribute("name", name);
            builder.MergeAttribute("id", string.Format("{0}_{1}", name, info.Value));
            sb.Append(builder.ToString(TagRenderMode.Normal));
 
            var labelBuilder = new TagBuilder("label");
            labelBuilder.MergeAttribute("for", string.Format("{0}_{1}", name, info.Value));
            labelBuilder.InnerHtml = info.Text;
            sb.Append(labelBuilder.ToString(TagRenderMode.Normal));
 
            return sb.ToString();
        }
        #endregion
    }
}
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

□ HomeController

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication1.Infrastructure.Services;
using MvcApplication1.Models;
 
namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {
        private readonly  CourseService service = new CourseService();
 
        private List<SelectListItem> coursesSelectListItems
        {
            get
            {
                var courses = this.service.GetCourses();
                var items = new List<SelectListItem>();
                foreach (var c in courses)
                {
                    items.Add(new SelectListItem()
                    {
                        Value = c.Id.ToString(),
                        Text = c.Name
                    });
                }
                return items;
            }
 
        }
 
        public ActionResult Index()
        {
            ViewBag.Course = this.coursesSelectListItems;
            return View();
        }
 
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Index(Student stu)
        {
            ViewBag.Course = this.coursesSelectListItems;
            if (ModelState.IsValid)
            {
                return View();
            }
            return View(stu);
        }
 
    }
}
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

□ CouseService.cs

using System.Collections.Generic;
using MvcApplication1.Models;
 
namespace MvcApplication1.Infrastructure.Services
{
    public class CourseService
    {
        public IEnumerable<Course> GetCourses()
        {
            return new List<Course>()
            {
                new Course(){Id = 1, Name = "语文"},
                new Course(){Id = 2, Name = "数学"},
                new Course(){Id = 3, Name = "哲学"},
                new Course(){Id = 4, Name = "英语"},
                new Course(){Id = 5,Name = "法语"},
                new Course(){Id = 6, Name = "物理"},
                new Course(){Id = 7, Name = "化学"},
                new Course(){Id = 8, Name = "工程"}
            };
        }
    }
}            
 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

参考资料:

ASP.NET MVC - CheckBoxList与ValidationMessage

MVC生成CheckBoxList并对其验证的更多相关文章

  1. 再议ASP.NET MVC中CheckBoxList的验证

    在ASP.NET MVC 4中谈到CheckBoxList,经常是与CheckBoxList的显示以及验证有关.我在"MVC扩展生成CheckBoxList并水平排列"中通过扩展H ...

  2. MVC中CheckBoxList的3种实现方式

    比如,当为一个用户设置角色的时候,角色通常以CheckBoxList的形式呈现.用户和角色是多对多关系: using System.Collections.Generic; using System. ...

  3. MVC扩展生成CheckBoxList并水平排列

    本篇体验生成CheckBoxList的几个思路,扩展MVC的HtmlHelper生成CheckBoxList,并使之水平排开.     通过遍历从控制器方法拿到的Model集合 □ 思路 比如为一个用 ...

  4. [ASP.NET MVC 小牛之路]16 - Model 验证

    上一篇博文 [ASP.NET MVC 小牛之路]15 - Model Binding 中讲了MVC在Model Binding过程中如何根据用户提交HTTP请求数据创建Model对象.在实际的项目中, ...

  5. MVC中的数据注解和验证

    数据注解和验证 用户输入验证在客户端浏览器中需要执行验证逻辑. 在客户端也需要执行. 注解是一种通用机制, 可以用来向框架注入元数据, 同时, 框架不只驱动元数据的验证, 还可以在生成显示和编辑模型的 ...

  6. ASP.NET MVC 5 学习教程:添加验证

    原文 ASP.NET MVC 5 学习教程:添加验证 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 通过控 ...

  7. 【译】ASP.NET MVC 5 教程 - 10:添加验证

    原文:[译]ASP.NET MVC 5 教程 - 10:添加验证 在本节中,我们将为Movie模型添加验证逻辑,并确认验证规则在用户试图使用程序创建和编辑电影时有效. DRY 原则 ASP.NET M ...

  8. ASP.NET MVC基于标注特性的Model验证:将ValidationAttribute应用到参数上

    原文:ASP.NET MVC基于标注特性的Model验证:将ValidationAttribute应用到参数上 ASP.NET MVC默认采用基于标准特性的Model验证机制,但是只有应用在Model ...

  9. ASP.NET没有魔法——ASP.NET MVC使用Oauth2.0实现身份验证

    随着软件的不断发展,出现了更多的身份验证使用场景,除了典型的服务器与客户端之间的身份验证外还有,如服务与服务之间的(如微服务架构).服务器与多种客户端的(如PC.移动.Web等),甚至还有需要以服务的 ...

随机推荐

  1. vmWare虚拟机下ubuntu配置代理上网

    最终用上了linux,windows下用vmWare安装虚拟机,挂ubuntu 14.04,,认为非常不习惯,非常难侍候. 而且遇到的客观困难还不少,这两天着实费了不少功夫.主要是上班这里上网要配置代 ...

  2. 完美世界3D格斗手游[格斗宝贝]今日公測

    狗刨学习网报道 / 经过近两年井喷式的发展,国内手游市场洗牌的信号愈加强烈.用户体验的提升.以及对产品核心品质的要求.促进了手游的精品化.而白热化的市场竞争,也催生了各大厂商在细分市场的抢滩.当中.更 ...

  3. Binary Tree Inorder Traversal(转)

    Given a binary tree, return the inorder traversal of its nodes' values. For example: Given binary tr ...

  4. ipad pro注定是失败的!

    ipad pro注定是失败的! 把一个玩具操作系统装在生产力工具上就能产生生产力了? so young so simple!

  5. 修改Hosts不生效的一个场景-web(转)

    Update: 如果浏览器使用了代理工具,修改 Hosts 也不会生效.这里是因为,浏览器会优先考虑代理工具(如添加 pac 文件.SwitchySharp等)的代理,建议调试的时候先关闭这些代理. ...

  6. Android4.0(Phone)来电过程分析

    在开机时.系统会启动PhoneApp类,那是由于在AndroidManifest.xml文件里配置了 <application android:name="PhoneApp" ...

  7. Eclipse-----jrebel实现jetty热部署

    步骤1:下载jrebel将文件解压缩到任意文件夹 步骤2:配置jetty watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVrZXdhbmd6aQ==/f ...

  8. 配置Apacheserver

    配置Apacheserver 一.目的 能够有一个測试的server,不是全部的特殊网络服务都能找到免费得! 二.为什么我们要用"Apache"? Apache是眼下使用最广的we ...

  9. java RC4加密和解码

    package com.*; public class RC4 { public static String decry_RC4(byte[] data, String key) { if (data ...

  10. JVM可支持的最大线程数(转)

    摘自:http://sesame.iteye.com/blog/622670 工作中碰到过这个问题好几次了,觉得有必要总结一下,所以有了这篇文章,这篇文章分为三个部分:认识问题.分析问题.解决问题. ...