zoukankan      html  css  js  c++  java
  • asp.net mvc下通用连动下拉框剖析(二)--FormModel们(最新完善版)

    导读:

    代码可以在https://files.cnblogs.com/bighuiwolf/Chinasoft.rar下载。

    第一篇:http://www.cnblogs.com/bighuiwolf/archive/2010/07/10/1774871.html

    第二篇:http://www.cnblogs.com/bighuiwolf/archive/2010/07/10/1774920.html

    第三篇:http://www.cnblogs.com/bighuiwolf/archive/2010/07/10/1774955.html

    本篇为第二篇

    该说FormModel了,最核心的就是DropDownList需要用到的数据了,想一想,它需要哪些东东呢?可以先看下代码,稍有点复杂,不要急,后面再做逐步的分析,下面是代码:

      1 
      2     public class DdlFormModel
      3     {
      4         public DdlFormModel()
      5         {
      6         }
      7 
      8         public DdlFormModel(string ddlKeyConfig, string ddlName, SelectList ddlData)
      9         {
     10             DdlKeyConfig = ddlKeyConfig;
     11             DdlName = ddlName;
     12             DdlData = ddlData;
     13         }
     14 
     15         public string DdlKeyConfig { getset; }
     16         public string DdlName { getset; }
     17         public SelectList DdlData { getset; }
     18         private string _onchange;
     19         public object HtmlAttributes
     20         {
     21             get
     22             {
     23                 if (!string.IsNullOrEmpty(_onchange))
     24                     return new { onchange = _onchange };
     25                 return null;
     26             }
     27         }
     28 
     29         public void SetChilds(string childIds, string childKey)
     30         {
     31             if (childIds != null && childIds.Length > 0)
     32             {
     33                 string[] childIdArray = childIds.Split(',');
     34                 string subChildIds = null;
     35                 int idx = childIds.IndexOf(",");
     36                 if (idx > -1)
     37                     subChildIds = childIds.Substring(idx + 1);
     38 
     39                 StringBuilder sb = new StringBuilder();
     40                 for (int i = 1; i < childIdArray.Length; i++)
     41                 {
     42                     sb.AppendFormat("ClearChilds('{0}');", childIdArray[i]);
     43                 }
     44                 sb.AppendFormat("GetChilds(this.id, '{0}', '{1}', '{2}', '{3}');"
     45                     ,DdlKeyConfig, childIdArray[0], childKey, subChildIds);
     46 
     47                 if (_onchange == null)
     48                 {
     49                     _onchange = sb.ToString();
     50                 }
     51                 else
     52                 {
     53                     _onchange += sb.ToString();
     54                 }
     55             }
     56         }
     57 
     58         public static DdlFormModel CreateInstance(
     59             string ddlKeyConfig
     60             , string ddlName
     61             , IHasParent hasParent
     62             , int parentId
     63             , int? selectedValue
     64             , string childIds
     65             , string childKey)
     66         {
     67             SelectList selectList = hasParent.GetSelectListByParentId(parentId, selectedValue);
     68             var instance = new DdlFormModel(ddlKeyConfig, ddlName, selectList);
     69             if (!string.IsNullOrEmpty(childIds))
     70             {
     71                 instance.SetChilds(childIds, childKey);
     72             }
     73             return instance;
     74         }
     75 
     76         public static DdlFormModel CreateInstance(
     77             string ddlKeyConfig
     78             , string ddlName
     79             , IHasParent hasParent
     80             , int parentId
     81             , int? selectedValue)
     82         {
     83             return CreateInstance(ddlKeyConfig, ddlName, hasParent, parentId, selectedValue, nullnull);
     84         }
     85 
     86         public static DdlFormModel CreateInstance(
     87             string ddlKeyConfig
     88             , string ddlName
     89             , SelectList selectList
     90             , string childIds
     91             , string childKey)
     92         {
     93             var instance = new DdlFormModel(ddlKeyConfig, ddlName, selectList);
     94             if (!string.IsNullOrEmpty(childIds))
     95             {
     96                 instance.SetChilds(childIds, childKey);
     97             }
     98             return instance;
     99         }
    100     }

    FormModel跟View要一块儿看才清楚,我定义了以下PartialView即用户控件来作为DropDownList的呈现逻辑:

    1 <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Chinasoft.Models.DdlFormModel>" %>
    2 <% if (Model != null)
    3    { %>
    4 <%= Html.DropDownList(Model.DdlName, Model.DdlData, Model.HtmlAttributes)%>
    5 <% }
    6    else
    7    { %>
    8 Model为空
    9 <% } %>|<%= DateTime.Now %>

    可以看到,里面用到了DdlFormModel的DdlName, DdlData, HtmlAttributes三个属性。它的构造函数里有三个参数(string ddlKeyConfig, string ddlName, SelectList ddlData),可能后两个参数大家能看明白,ddlName就是控件名,ddlData就是从SelectListProviderBase(顶级)或IHasParent(子级)获取到的数据。而ddlKeyConfig不容易看明白,它与配置文件有关,我们都知道级连的东西要定义一个级连的顺序,我把这个顺序定义在了web.config里:

    1 
    2     <appSettings>
    3         <add key="Ddl_Keys_Address" value="Ddl_City,Ddl_Suburb,Ddl_Street"/>
    4         <add key="Ddl_City" value="Chinasoft.Models.Cities"/>
    5         <add key="Ddl_Suburb" value="Chinasoft.Models.Suburbs"/>
    6         <add key="Ddl_Street" value="Chinasoft.Models.Streets"/>
    7     </appSettings>

    进一步看为Form获取数据的代码会更明白一点,以下是后面例子(本系列第三篇)中要调用的为View提供数据的代码(DdlSampleFormModel的定义稍后贴出),因为是Demo,所以用了些俗称硬编码的东东,嘿嘿:

    其中定义如下接口:

    1 
    2     public interface IDdlSampleRepository
    3     {
    4         DdlSampleFormModel GetInfo();
    5     }

    然后具体类:

     1 
     2     public class DdlSampleRepository : IDdlSampleRepository
     3     {
     4         public DdlSampleFormModel GetInfo()
     5         {
     6             DdlSampleFormModel model = new DdlSampleFormModel();
     7             model.Data = new AddressDetailModel(0000"Other info");
     8 
     9             var ddlKeyConfig = "Ddl_Keys_Address";
    10 
    11             var countrySelectList = new Countries().GetSelectList(model.Data.Country);
    12             model.Countries = DdlFormModel.CreateInstance(
    13                 ddlKeyConfig
    14                 , "County"
    15                 , countrySelectList
    16                 , "City,Suburb,Street"
    17                 , "Ddl_City");
    18 
    19             model.Cities = DdlFormModel.CreateInstance(
    20                 ddlKeyConfig
    21                 , "City"
    22                 , new Cities()
    23                 , model.Data.Country
    24                 , model.Data.City
    25                 , "Suburb,Street"
    26                 , "Ddl_Suburb");
    27 
    28             model.Suburbs = DdlFormModel.CreateInstance(
    29                 ddlKeyConfig
    30                 , "Suburb"
    31                 , new Suburbs()
    32                 , model.Data.City
    33                 , model.Data.Suburb
    34                 , "Street"
    35                 , "Ddl_Street");
    36 
    37             model.Streets = DdlFormModel.CreateInstance(
    38                 ddlKeyConfig
    39                 , "Street"
    40                 , new Streets()
    41                 , model.Data.Suburb
    42                 , model.Data.Street);
    43 
    44             return model;
    45         }
    46     }

    其中的var ddlKeyConfig = "Ddl_Keys_Address";对应配置文件中的第一个配置的key,它定义了层次顺序,同时也可以看出来DdlFormModel的第三个CreateInstance方法重载是用于顶级下拉框的(这里用于国家),第一个CreateInstance方法重载是用于既有父又有子的下拉框的(这里是城市、区县),第二个CreateInstance方法重载是用于底层下拉框的(这里是Street)。

    配置文件里的第二、三、四个配置,是用于利用反射来获取下拉框后续数据的,简单说就是当国家变了时候用Ajax来更新城市、区县、街道时候用的。具体在第三篇里讨论。

    下面是DdlSampleFormModel的代码(它用于Views\DdlSample\Index.aspx提供数据,在第三篇可以看到Views\DdlSample\Index.aspx):

    1 
    2     public class DdlSampleFormModel
    3     {
    4         public AddressDetailModel Data { getset; }
    5         public DdlFormModel Countries { getset; }
    6         public DdlFormModel Cities { getset; }
    7         public DdlFormModel Suburbs { getset; }
    8         public DdlFormModel Streets { getset; }
    9     }

    后四个参数类型在本文的开始已经贴过了,是为下拉框用户控件提供的数据。第一个参数Data当然是对地址的一个封装,代码如下:

     1 
     2     public class AddressDetailModel
     3     {
     4         public int Country { getset; }
     5         public int City { getset; }
     6         public int Suburb { getset; }
     7         public int Street { getset; }
     8         public string OtherInfo { getset; }
     9 
    10         public AddressDetailModel()
    11         {
    12         }
    13         public AddressDetailModel(int country, int city, int suburb, int street, string otherInfo)
    14         {
    15             Country = country;
    16             City = city;
    17             Suburb = suburb;
    18             Street = street;
    19             OtherInfo = otherInfo;
    20         }
    21     }

    题目虽为FormModel们,但是光看Model不容易看明白,所以把有关上下文的代码都贴了上来,以帮助理解。细心的人应该会注意到DdlFormModel类里一定也用到Javascript了吧,JS代码会在第三篇里贴出。

    忘了有一个工具类了,它是在HasParentBase和SelectListProviderBase中使用到的,一共2个功能,第一个功能是根据基础数据生成SelectList,第二个是添加空选项:

     1 
     2     public static class RepositoryHelper
     3     {
     4         public static SelectList GetSelectList
     5             (IEnumerable<KeyValuePair<stringstring>> values, int? selectedValue)
     6         {
     7             SelectList list;
     8             if (selectedValue.HasValue)
     9             {
    10                 list = new SelectList(values, "Key""Value", selectedValue);
    11             }
    12             else
    13             {
    14                 list = new SelectList(values, "Key""Value");
    15             }
    16             return list;
    17         }
    18 
    19         public static void AddEmpty(List<KeyValuePair<stringstring>> list)
    20         {
    21             list.Insert(0new KeyValuePair<stringstring>(""""));
    22         }
    23     }

    欢迎扔鸡蛋!

  • 相关阅读:
    vant toast 样式引入
    Error: Can‘t resolve ‘swiper/css/swiper.css‘ 解决方案
    Vue中使用provide/inject实现页面reload的方法
    vue 中 关于路径 @ 以及 ~的意义
    ValidationError: Invalid options object. Stylus Loader has been initialized using an options object that does not match the API schema.
    vue 去除链接后的#
    centos7安装elk
    Flask+Celery 异步任务
    centos7用zimg搭建图片存储服务器
    centos7部署nginx与vue搭配及403排错
  • 原文地址:https://www.cnblogs.com/bighuiwolf/p/1774920.html
Copyright © 2011-2022 走看看