.NET MVC标签扩展(checkbox,radio)

.NET MVC的自动绑定功能在表单处理中非常方便,但@Html.CheckBox和@Html.RadioButton对于多个选项的绑定不够灵活。为解决这个问题,可以使用扩展方法来创建能够绑定集合的checkbox和radio。本文介绍了如何创建这些扩展方法,包括生成checkbox和radio集合以及单个元素,并给出了控制器和视图的示例代码,以帮助开发者更便捷地实现多选和单选功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      .NET  MVC里面自动绑定form表单功能(如:@Html.TextBox("Name")、@Html.Hidden("hide"),名称会自动与后台就行绑定ViewBag.Name,ViewBag,hide)很实用,但是感觉不足的就是@Html.CheckBox("check")和@Html.RadioButton("radio","1"),这两个表单只能单个进行绑定,当出现多个绑定进行选中时,用起来就相对不太方便,如下图



       想要通过集合直接绑定生成需要的多个checkbox和radiobutton,并且部分处于选中状态,还好.NET的扩展方法为我们提供了方便。扩展方法就不用多说了,就是在静态类中,建立静态方法,并且第一个参数是 (this [要扩展的对象] name),

     比如,你要给string类型扩展一个方法,要求当string长度超过10的时候只要截取前十个字符,当长度少于10的时候返回原字符串你可以这样:

namespace System
{
    public static class StringExtension
    {
       public static string SubTen(this string sourceStr) { 
            if(!string.IsNullOrEmpty(sourceStr)&&sourceStr.Length>10){
                return sourceStr.Substring(0,10);
            }
            return sourceStr;
        }
    }
}</span>
   调用的时候如下所示:
 string SS = "AASSSSSSSSSSSSSS";
  var SSS = SS.SubTen();

      这样当字符串长度大于10 的时候就会取出前十个字符。

      好了,扩展方法就说到这里,现在进入正题,对HtmlHelper要扩展四个方法,分别是生成checkbox集合,checkbox单个,radio集合和radio单个。

       方法如下,因为checkbox和radio只是type类型不同,因此,他们可以用同样的方法,只是传值的时候把类型传入进行判断就可以了。

private static IDictionary<string, object> CopyAll(this IDictionary<string, object> dicSor)
        {
            Dictionary<string, object> dicDst = new Dictionary<string, object>();
            foreach (var item in dicSor)
            {
                dicDst.Add(item.Key, item.Value);
            }
            return dicDst;
        }
这里的dictionary的扩展是方便循环的时候使用。
        /// <summary>
        /// 扩展checkbox和radio
        /// </summary>
        /// <param name="targtname">后台的取值</param>
        /// <param name="itype">标签类型</param>
        /// <param name="name">标签值name或者取后台值用到</param>
        /// <param name="selectList">传入的集合</param>
        /// <param name="htmlAttributes">Html标签属性</param>
        /// <returns></returns>
        private static MvcHtmlString RadioOrCheckBox(object targtname, string itype, string name, IEnumerable<SelectListItem> selectList, object htmlAttributes)
        {
            //不存在绑定值则返回空
            if (string.IsNullOrEmpty(name) || (targtname == null && selectList == null))
            {
                return MvcHtmlString.Create("");
            }
            //if (htmlHelper.ViewData.ContainsKey(name)) {
            //    name = htmlHelper.ViewData[name].ToString();
            //}
            string selectValues = "";
            Object selectedValues = null;
            HashSet<string> ckSet = new HashSet<string>();//用于存储选定值,不添加重复项
            List<SelectListItem> listSelectListItem = new List<SelectListItem>(); //这里可以不新建对象直接用selectList,这样下面画-----横线的代码也可以省略
            if (targtname != null)           //后台取值赋值
            {
               // selectList = new List<SelectListItem>();//---------
                if (targtname.GetType() != typeof(SelectList)) //后台传入ViewBag.AAA=new SelectList()类型
                {
                    return MvcHtmlString.Create("");
                }
                SelectList slItemlist = targtname as SelectList;
                selectedValues = slItemlist.SelectedValue ?? ""; //要选中的值
                if (selectedValues != null)
                {
                    selectValues = selectedValues.ToString();
                    string[] tempStr = selectValues.Split(','); //多个选中用逗号隔开
                    //Array.IndexOf(tempStr, "");
                    ckSet = new HashSet<string>(tempStr);
                }
                foreach (var item in slItemlist)
                {
                    if (ckSet.Contains(item.Value))
                    {
                        item.Selected = true; //选中值设为true
                    }
                    listSelectListItem.Add(item);
                }
            }
            //验证绑定的对象
            if (listSelectListItem.Count <= 0 && selectList != null && selectList.Count() > 0)//--------------
            {
                listSelectListItem.AddRange(selectList);//--------
            }
            string id = string.Empty;  //checkbox一般不带id,这几行代码其实没用
            IDictionary<string, object> htmlAttributesdic = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
            if (htmlAttributesdic.ContainsKey("id"))
            {
                id = htmlAttributesdic["id"].ToString();
                htmlAttributesdic.Remove("id");
            }
            htmlAttributesdic.Add("type", itype);//生成的类型,是checkbox或者是radio
            htmlAttributesdic.Add("name", name);
            StringBuilder sbHtml = new StringBuilder();
            foreach (SelectListItem selectItem in listSelectListItem)
            {
                IDictionary<string, object> newDicAttributes = htmlAttributesdic.CopyAll();
                newDicAttributes.Add("value", selectItem.Value);
                if (selectItem.Selected) //为true则处于选中状态
                {
                    newDicAttributes.Add("checked", "checked");
                }
                TagBuilder tagBuilder = new TagBuilder("input");//新建input表单
                tagBuilder.MergeAttributes<string, object>(newDicAttributes); //添加表单属性
                string inputAllHtml = tagBuilder.ToString(TagRenderMode.SelfClosing); //TagRenderMode枚举,自关闭类型如:<input />
                string containerFormat = @"<label> {0}  {1}</label>"; //外层套上label可以点击文字的时候选中按钮,如果想要水平垂直居中最后在加上<P></P>标签           
                sbHtml.AppendFormat(containerFormat,
                   inputAllHtml, selectItem.Text);
            }
            return MvcHtmlString.Create(sbHtml.ToString());
        }

      因为这是绑定集合数据,因此targtname和selectList参数不能同时为空,默认是以targtname绑定的数据优先,当targtname存在且类型正确的时候,绑定targtname中的数据,当targtname取后台值为null的时候再判断取selectList中的值,上面的后台取值其实可以优化更通用一点,只是感觉没那么必要了,自己定的一个约定知道赋值取值一般不会出错。其他的就不多介绍了,注释里面很详细了。

真正的扩展到了,如下:

   /// <summary>
        /// checkbox集合扩展
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="name">标签名称</param>
        /// <param name="selectList">items</param>
        /// <param name="htmlAttributes">属性html</param>
        /// <returns></returns>
        public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, object htmlAttributes)
        {
            var targtname = htmlHelper.ViewData[name];//取后台数据
            return RadioOrCheckBox(targtname, "checkbox", name, selectList, htmlAttributes);
        }

        /// <summary>
        /// radio集合扩展
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="name">name属性</param>
        /// <param name="selectList">item属性</param>
        /// <param name="htmlAttributes">额外属性</param>
        /// <returns></returns>
        public static MvcHtmlString RadioButtonList(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, object htmlAttributes)
        {
            var targtname = htmlHelper.ViewData[name];//取后台数据
            return RadioOrCheckBox(targtname, "radio", name, selectList, htmlAttributes);
        }

这样,放到静态类的静态方法就可以正常使用了,注意这个命名空间,最好用System.Web.Mvc.Html这样与其他的扩展方法命名空间一致,那样省去我们在页面还要单独引用命名空间。

namespace System.Web.Mvc.Html
{
    public static class InputExtension
    {
    }
}
在html页面中使用方式如下:

  @Html.CheckBoxList("Drop",null, new {@class = "tclass", @style = "" }) <br />
   
    @Html.RadioButtonList("Drop",null, new {@class = "tclass", @style = "" })<br/>

接下来扩展单个标签的radio和checkbox标签,方便的在循环的时候使用,少了对是否选中的判断,只要value值与是否选中的值一致,那么他就处于选中状态,不一致则不选中,不用再判断if(){}else if(){},

代码如下:

        /// <summary>
        /// 单标签为了在循环的时候使用方便
        /// </summary>
        /// <param name="itype">标签类型</param>
        /// <param name="name">标签name属性</param>
        /// <param name="value">标签value值</param>
        /// <param name="showText">radio或者checkbox要显示的名字</param>
        /// <param name="htmlAttributes">标签的其他属性</param>
        /// <param name="selectValue">选中的值</param>
        /// <returns></returns>
        private static MvcHtmlString RadioOrCheckBoxItem(string itype,string name, string value, string showText, object htmlAttributes, string selectValue = "")
        {
            //生成<input type='radio' name ='name' value='value'> name和value不能为空
            if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(value))
            {
                return MvcHtmlString.Create("");
            }
            StringBuilder sbHtml = new StringBuilder();
            IDictionary<string, object> htmlAttributesdic = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
            htmlAttributesdic.Add("type", itype); //标签类型radio或者checkbox
            htmlAttributesdic.Add("value", value);
            htmlAttributesdic.Add("name", name);
            var dd = string.Compare(value, selectValue, true);
            if (value.Equals(selectValue, StringComparison.OrdinalIgnoreCase)) //这里判断当value和selectValue一致,则处于选中状态
            {
                htmlAttributesdic.Add("checked", "checked");
            }
            TagBuilder tagBuilder = new TagBuilder("input");
            tagBuilder.MergeAttributes<string, object>(htmlAttributesdic);
            string inputAllHtml = tagBuilder.ToString(TagRenderMode.SelfClosing);
            string containerFormat = @"<label> {0}  {1}</label>";       
            sbHtml.AppendFormat(containerFormat,
               inputAllHtml, showText);

            return MvcHtmlString.Create(sbHtml.ToString());
        }

这个就不解释了,和上面那个道理一样。

       /// <summary>
        /// 单个checkbox扩展
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="name">name属性</param>
        /// <param name="value">值</param>
        /// <param name="showText">要显示的文本</param>
        /// <param name="htmlAttributes">额外属性</param>
        /// <param name="selectValue">选中的值</param>
        /// <returns></returns>
        public static MvcHtmlString CheckBoxItem(this HtmlHelper htmlHelper, string name, string value, string showText, object htmlAttributes, string selectValue = "")
        {
            return RadioOrCheckBoxItem("checkbox",name, value, showText, htmlAttributes, selectValue);
        }

     /// <summary>
        /// radio单个按钮
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="name">标签name</param>
        /// <param name="value">radio值</param>
        /// <param name="showText">显示的文本</param>
        /// <param name="htmlAttributes">额外属性</param>
        /// <param name="selectValue">选中的值</param>
        /// <returns></returns>
        public static MvcHtmlString RadioButtonItem(this HtmlHelper htmlHelper, string name, string value, string showText, object htmlAttributes, string selectValue = "")
        {
            return RadioOrCheckBoxItem("radio", name, value, showText, htmlAttributes, selectValue);
        }

好了几个扩展方法写完了,下面就到了用的时候了:

MVC控制器代码:

     public ActionResult Index()
        {
            Dictionary<string, object> dic = new Dictionary<string, object>();
            dic.Add("1", "字典一");
            dic.Add("2", "字典二");
            dic.Add("3", "字典三");
            ViewBag.DIC = new SelectList(dic, "key", "value", "3,2");

            List<DropList> listdrop = new List<DropList>(){
             new DropList(){dname="自定义集合一", dvalue="one", dother="dropvalueOne"},
             new DropList(){dname="自定义集合二", dvalue="two", dother="dropvalueTwo"},
             new DropList(){dname="自定义集合三", dvalue="three", dother="dropvalueThree"}
            };
            ViewBag.Drop = new SelectList(listdrop, "dvalue", "dname", "two");

            List<SelectListItem> ieitem = new List<SelectListItem>(){
                  new SelectListItem(){ Selected=true, Text="不存在一", Value="sdfg"},
                  new SelectListItem(){ Selected=false, Text="不存在二", Value="ryhfgh"},
                  new SelectListItem(){ Selected=true, Text="不存在三", Value="yuioi"}
            };
            ViewBag.RRR = ieitem;
          return View()
}

MVC视图代码测试radio和checkbox集合:

    <fieldset>
        <legend>这是测试集合</legend><br/>
        <label>后台不存在ViewBag.AAAA则取 ViewBag.RRR:</label> 
         @Html.CheckBoxList("AAAA", ViewBag.RRR as IEnumerable<SelectListItem>,new{ style = "" })<br /><br />
        <label>后台存在ViewBag.DIC:</label>
        @Html.CheckBoxList("DIC", null, new { @class = "tclass", @style = "" }) <br /><br />
        <label>后台存在ViewBag.Drop:</label>
        @Html.RadioButtonList("Drop", null, new { @class = "tclass", @style = "" })<br /><br />
    </fieldset>

生成结果如下图所示:



MVC视图单个radio和checkbox,如下:

    <fieldset>
        <legend>这是测试单个</legend><br/>
        <label>radio单个:</label>
         @Html.RadioButtonItem("AAA", "45", "测试radio1", new { }, "415")
         @Html.RadioButtonItem("AAA", "425", "测试radio2", new { }, "425")<br/><br/>
        <label>checkbox单个:</label>
        @Html.CheckBoxItem("BBBB", "3", "测试checkbox", new { }, "34")
        @Html.CheckBoxItem("BBBB", "34", "测试checkbox", new { }, "34") 
        @Html.CheckBoxItem("BBBB", "35", "测试checkbox", new { }, "35")       
    </fieldset>

生成的结果如下图所示:


    好了,写完了,希望对大家有所帮助,有什么不对或者需要优化的地方还请大家批评指出,我会尽快改正,谢谢!





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值