[Asp.Net Mvc] 我的下拉列表扩展

一、思考

      之前读了一篇Artech大神写的关于列表控件绑定的博文[ASP.NET MVC]通过对HtmlHelper扩展简化“列表控件”的绑定,很受益。

  不过在具体的使用中往往会遇到一些问题,就是列表中的数据往往不是我们预先能够知道的,或者说填充列表的数据一般都是从数据库里面读取得来的,这个时候怎么做呢?

二、假设的场景

  现在我们要做一个简单的新闻系统,只考虑新闻和类别两个实体。下面给出新闻和类别的类定义:

    /// <summary>
    /// 新闻类别
    /// </summary>
    public class Category
    {
        [DisplayName("Id")]
        public Int32 Id { get; set; }

        [DisplayName("名称")]
        public String OfName { get; set; }

        [DisplayName("标签")]
        public String Label { get; set; }
    }

    /// <summary>
    /// 新闻
    /// </summary>
    public class OurNews
    {
        public Guid Id { get; set; }

        [DisplayName("分类")]
        public Int32 CategoryId { get; set; }

        [DisplayName("标题")]
        public String Title { get; set; }

        [DisplayName("内容")]
        public String Content { get; set; }
    }

  先预先添加一些新闻类别的数据,在contreller的构造函数中添加。并添加一个“AddNews”的Action:

        private List<Category> prevCategories;
        public HomeController()
        {
            prevCategories = new List<Category>() { 
                new Category{ Id = 0, OfName="生活", Label="SH"},
                new Category{ Id = 1, OfName="体育", Label="TY"},
                new Category{ Id = 2, OfName="学习", Label="XX"}
            };
        }

        public ActionResult AddNews()
        {
            this.ViewBag.prevCategories = this.prevCategories;  // 新闻类别数据,用于填充下拉列表的数据
            return View();
        }

  然后转到添加新闻的视图,在添加新闻时,我们一般都会把分类那一栏做成一个下拉列表,而我们一般做的都是构建一个List<SelectListItem>,然后直接调用Html.DropDownList即可;然而我们为了视图的整洁经常会做去扩展Html.DropDownList这个方法,就如下面给出的视图代码。1是一般的方法,2是经过扩展之后的方法。下面是两种方式书写的代码:

@{ var prevCategories = this.ViewBag.prevCategories as List<Category>;}
        <div class="editor-label">
            @Html.LabelFor(model => model.CategoryId)
        </div>
        <div class="editor-field">
            <table>
                <tr>
                    <td>1.一般流</td>
                    @{var items = new List<SelectListItem>();
                      foreach (var category in prevCategories)
                      {
                          items.Add(new SelectListItem { Text = category.OfName, Value = category.Id.ToString() });
                      }
                    }
                    <td>@Html.DropDownList("Id",items,"=请选择=")</td>
                </tr>
                <tr>
                    <td rowspan="2">2.扩展流</td>
                    <td>@(Html.DropDownList<Category>("Id", "OfName", "Id", prevCategories, "=请选择=", new { }))</td>  @*反射*@
                </tr>
                <tr>
                    <td>@(Html.DropDownList<Category>("Id", c => c.OfName,c=>c.Id.ToString(), prevCategories, "=请选择=", new { }))</td>  @*委托*@
                </tr>
            </table>
        </div>

  先看一下效果图吧

  DropDownList的扩展用了两种不同的方法,所以有两种写法。现在开始步入正题了

  第1种方法的不好之处呢就是看起来有些冗余了,是不是每一次遇到这种情况都要构建List<SelectListItem>这么来一下。当然没这个必要了,那就用第二种方式吧,扩展DropDownList。

三、扩展DropDownList

  扩展DropDownList的目的就是不想再重复构建List<SelectListItem>类,那就把List<SelectListItem>的构建放到扩展方法中来,构建时遇到的问题就是如何从获取数据源类型和填充的字段,由于在数据源类型是可变的,所以就需要用到泛型,用了泛型之后对于字段的填充问题出现了,解决的方法有两种,一个就是用到反射,另外一个就是用到委托

public static class DropDownListExtensions
    {
        /// <summary>
        /// 反射
        /// </summary>
        public static MvcHtmlString DropDownList<TEntity>(this HtmlHelper html, String name, String textField, String valueField, IList<TEntity> entityList, String optionLabel, object htmlAttributes)
        {
            var items = new List<SelectListItem>();
            var type = typeof(TEntity);
            foreach (var entity in entityList)
            {
                var textPropety = type.GetProperty(textField);
                var valuePropety = type.GetProperty(valueField);
                items.Add(new SelectListItem { Text = textPropety.GetValue(entity, null).ToString(), Value = valuePropety.GetValue(entity, null).ToString() });
            }
            return html.DropDownList(name, items, optionLabel, htmlAttributes);
        }

        /// <summary>
        /// 委托
        /// </summary>
        public static MvcHtmlString DropDownList<TEntity>(this HtmlHelper html, String name, Func<TEntity, String> textField, Func<TEntity, String> valueField, IList<TEntity> entityList, String optionLabel, object htmlAttributes)
        {
            var items = new List<SelectListItem>();
            foreach (var entity in entityList)
            {
                items.Add(new SelectListItem { Text = textField(entity), Value = valueField(entity) });
            }
            return html.DropDownList(name, items, optionLabel, htmlAttributes);
        }
    }

四、总结

   感觉道理说得不是很清楚,但是用的时候还是觉得蛮方便的,所以就分享给大家了。

  示例程序:点击这里下载

 

作者:Xanthondont

出处:http://www.cnblogs.com/hbq-fczzw/archive/2012/04/18/2455813.html 

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

posted @ 2012-04-18 19:20  xanthodont  阅读(877)  评论(0编辑  收藏  举报