加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

[ASP.NET MVC]通过对HtmlHelper扩展简化“列表控件”的绑定

发布时间:2020-12-16 09:11:28 所属栏目:asp.Net 来源:网络整理
导读:在众多表单元素中,有一类select元素用于绑定一组预定义列表。传统的ASP.NET Web Form中,它对应着一组重要的控件类型,即ListControl,我们经常用到DropDownList, ListBox、CheckBoxList和RadioButtonList都是其子类。ASP.NET MVC通过对HtmlHelper和HtmlHe

在众多表单元素中,有一类<select>元素用于绑定一组预定义列表。传统的ASP.NET Web Form中,它对应着一组重要的控件类型,即ListControl,我们经常用到DropDownList, ListBox、CheckBoxList和RadioButtonList都是其子类。ASP.NET MVC通过对HtmlHelper和HtmlHelper<TModel>的扩展实现了对不同类型的<select>元素的绑定,它们以扩展方法的形式定义在SelectExtensions中。当我们在操作这些扩展方法的时候,必须手工地提供以 IEnumerable<SelectListItem>对象表示的列表项。如果我们建立一个独立的组件来维护这些预定的列表,那么我们就可以定义一些更加简单的扩展方法以避免手工地指定列表项。[源代码从这里下载]

一、创建一个独立的列表维护组件

我们将这些绑定在<select>元素中的预定义列表中的元素称为Code。作为简单的演示模拟,我们创建了一个名为CodeManager的组件。我们先来看看用于描述单一Code的CodeDescription类型的定义,如下面的代码所示,CodeDescription具有ID、Code、Description、EffectiveStartDate 和EffectiveEndDate。以表示国家的列表为例,Code代表某个国家的代码(比如CN),Description则是一个可读性的描述(比如China)。EffectiveStartDate 和EffectiveEndDate决定了Code的有效期限,比如一组表示“税率”的列表,在不同的时间范围内可能采用不同的列表。换言之,作为统一类别(通过Category属性表示)的列表中可能具有“多套”,它们可以共享相同的Code,我们通过ID来区分这些具有相同Code的列表项。

   1: public class CodeDescription
   3:     string Id { get; set; }
   5:     string Description { get; set; }
   7:     public DateTime EffectiveStartDate { get; set; }
   9:? 
  11:     {
  13:         this.Code = code;
  15:         this.Category = category;
  17:         this.EffectiveEndDate = DateTime.MaxValue;
  19: }

如下所示的CodeCollection 表示一组CodeDescription列表,它直接继承自Collection<CodeDescription>类型。由于CodeDescription具有有效期限的概念,我们需要筛选出当前有效的Code,所以我们定义了如下一个GetEffectiveCodes方法。

public IEnumerable<CodeDescription> GetEffectiveCodes()
   5:         return this.Where(code => code.EffectiveStartDate <= DateTime.Today && code.EffectiveEndDate >= DateTime.Today).ToList();
   7: }

在进行Code绑定的时候,我们都是“类别”为单位的。我们总是获取某一个类别(比如国家、性别、婚姻状况和政治面貌等)的Code列表绑定到界面上。如下所示的CodeManager定义了一个GetCode方法获取指定类别的Code列表。而作为Code存储,我们采用了静态字段的形式,从如下所示的代码可以看出我们实际定义了三类Code,即Gender、MaritalStatus和Country,分别表示性别、婚姻状况和国籍。

private static CodeDescription[] codes = new CodeDescription[]
   6:         "F",1)">"Female",
  13:     };
  16:         CodeCollection codeCollection = new CodeCollection();
  18:         {
  20:         }
  22:     }
class BindingOption
string TextTemplate { get; set; }
   6:? 
   8:     {
this.TextTemplate = "{Description}";
  12:     }
class SelectExtensions
   5:         bindingOption = bindingOption ?? new BindingOption();
return htmlHelper.DropDownList(name,listItems,bindingOption.OptionalLabel);
   9:     static MvcHtmlString DropDownListFor<TModel,TProperty>(this HtmlHelper<TModel> htmlHelper,Expression<Func<TModel,TProperty>> expression,1)" id="lnum10">  10:     {
  15:? 
  17:     {
  19:         var listItems = GenerateListItems(codeCategory,bindingOption);
  21:     }
  24:         bindingOption = bindingOption ??   25:         var listItems = GenerateListItems(codeCategory,1)" id="lnum26">  26:         return htmlHelper.ListBoxFor<TModel,listItems);
  28:? 
  30:     {
  32:         foreach (var code in CodeManager.GetCodes(codeCategory).GetEffectiveCodes())
  34:             var item = new SelectListItem
  36:                 Text = FormatTemplate(bindingOption.TextTemplate,code),1)" id="lnum37">  37:                 Value = FormatTemplate(bindingOption.ValueTemplate,code)
  39:             items.Add(item);
  41:         return items;
  43:? 
  45:     {
  47:             .Replace("{Code}",code.Code)
  49:     }
class Person
string Gender { get; set; }
string MaritalStatus { get; set; }
   8: }
  11: {
  13:     {
  15:         {
  20:         });
   1: @model CodeBinding.Models.Person
   3:     ViewBag.Title = "Index";
   5:? 
tr>
  14:        {
  18:        })  19:       20:      >m.MaritalStatus)  22:         > m.MaritalStatus,"MaritalStatus",new BindingOption
  24:            OptionalLabel = "Please select your marital status...",1)" id="lnum25">  25:            TextTemplate = "{Code}-{Description}",1)" id="lnum26">  26:            ValueTemplate = "{Code}"