Html Helper سفارشی برای Dropdown List ایجاد شده توسط لیستی از اشیا

جمعه 2 بهمن 1394

در این مقاله DropDown لیست هایی خواهیم نوشت که یک شی را گرفته و آیتم دلخواهی از آن را برای ما نمایش دهند .در ادامه امکان انتخاب چند گانه DropDown List را توسط Helper ایی که برای آن می نویسیم ، به آن اضافه می کنیم .

 Html Helper سفارشی  برای Dropdown List ایجاد شده توسط لیستی از اشیا

در حالت عادی در Html Helper سفارشی مجبور به ارسال لیستی از آیتم های انتخابی و یا لیستی از کلاس های خاص هستید.اما اگر شما لیستی از داده هایی از نوع یک کلاس خاص داشته باشید (مثلا کلاس customer) در آن صورت ابتدا باید داده ها را به SelectListItem و یا standard class که در Html Helper از شما خواسته  میشود ، تبدیل کنید .

در این مقاله نحوه ساخت یک Html Helper برای DropdownList بدون انجام چنین تبدیلی را توضیح می دهیم .شما قادرید هر کلاسی که خواستید را به Helper ارسال کنید بدون اینکه مجبور به تبدیل آن به کلاس خاص باشید .

در نمونه ای که ضمیمه مقاله است قصد داریم DropdownList از دو کلاس خود به نام های Customer و Country داشته باشیم .در زیر کدهای مربوط به این کلاس ها آورده شده است .

public class Customer
{
    public int Customer_Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
}

کلاس Country

public class Country
{
    public int Country_Id { get; set; }
    public string Name { get; set; }
}

یک کلاس View Model به نام VM_Customer داریم که مجموعه ای از پراپرتی های هر دو کلاس قبل در آن وجود دارد

public class VM_Customer
{
    public List<Customer> CustomerList { get; set; }
    public List<Country> CountryList { get; set; }
    public int CustomerId { get; set; }
    public int CountryId { get; set; }
}

کدهای مربوط به کلاس HtmlHelper در زیر آورده شده است.

public static partial class HtmlHelperExtensions
{
    /// <summary>
    /// Creates Dropdown List for specified list of objects
    /// </summary>
    /// <typeparam name="T">Type of object for which Dropdown list needs to be created</typeparam>
    /// <param name="htmlHelper">HtmlHelper class</param>
    /// <param name="name">Name of Dropdown List</param>
    /// <param name="itemList">List of class having data to be bound in Dropdown List</param>
    /// <param name="valueField">Property name of class whose value will be used as value of Dropdown List</param>
    /// <param name="textField">Property name of class whose value will be used as text of Dropdown List</param>
    /// <param name="value">Selected value of Dropdown List</param>
    /// <param name="optionLabel">Option Label of Dropdown List</param>
    /// <param name="cssClass">CSS Class to be applied on Dropdown List control</param>
    /// <returns></returns>
    public static MvcHtmlString CustomDropdownList<T>(this HtmlHelper htmlHelper,
        string name, List<T> itemList, string valueField, string textField, int? value, 
        string optionLabel, string cssClass) where T : new()
    {
        StringBuilder sb = new StringBuilder();
        TagBuilder option;
        TagBuilder select = new TagBuilder("select");
        select.MergeAttribute("name", name, true);
        select.GenerateId(name);
        select.MergeAttribute("class", cssClass);
        select.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name));
        sb.Append(select.ToString(TagRenderMode.StartTag));
        if (!string.IsNullOrEmpty(optionLabel) && optionLabel != "null")
        {
            option = new TagBuilder("option");
            option.SetInnerText(optionLabel);
            option.MergeAttribute("Value", "0");
            if (value == 0)
            {
                option.MergeAttribute("Selected", "true");
            }
            sb.Append(option.ToString(TagRenderMode.Normal));
        }
        foreach (T ddl in itemList)
        {
            Type type = ddl.GetType();
            option = new TagBuilder("option");
            option.SetInnerText(Convert.ToString(type.GetProperty(textField).GetValue(ddl, null)));
            option.MergeAttribute("Value", Convert.ToString(type.GetProperty(valueField).GetValue(ddl, null)));
            if (Convert.ToInt32(type.GetProperty(valueField).GetValue(ddl, null)) == value)
            {
                option.MergeAttribute("Selected", "true");
            }
            sb.Append(option.ToString(TagRenderMode.Normal));
        }
        sb.Append(select.ToString(TagRenderMode.EndTag));
        return MvcHtmlString.Create(sb.ToString());
    }
}

این کلاس یک Dropdown List سفارشی همان طور که ما میخواهیم برایمان می سازد .Action ایی می سازیم و در داخل آن شی مربوطه که از نوع VM_Customer است را ساخته و به view پاس می دهیم . کد های داخل Action به صورت زیر است

  public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            List<VM_Costomer> c = new List<VM_Costomer>()
            {
              new VM_Costomer(){
                    CountryId=1,
                    CountryList=new List<Country>(){
                    new Country {Country_Id=1 ,Name="iran"},
                    new Country {Country_Id=2 ,Name="American"},
                     new Country {Country_Id=3 ,Name="south Africa"}
                    },
                    CustomerId=1,
                    CustomerList=new List<Customer>(){
                        new Customer{Address="Tehran",CustomerId=1,FirstName="Somayeh",LastName="Hatami"},
                        new Customer{Address="shiraz",CustomerId=2,FirstName="shima",LastName="ehsan"},
                         new Customer{Address="Esfahan",CustomerId=3,FirstName="sana",LastName="madani"},

}
                }
            };

            return View(c);
        }


 View مربوط به این action به صورت زیر است

@model IEnumerable<GenericHtml.Models.VM_Costomer>
@using GenericHtml.Models

@foreach (var item in Model)
{
     <div class="row">
        <div class="col-xs-2">
            <h6>Customer</h6>
        </div>
        <div class="col-xs-4">
            @(Html.CustomDropdownList<GenericHtml.Models.Customer>("CustomerId", item.CustomerList,
            "CustomerId", "FirstName", item.CustomerId, null, "form-control"))
        </div>
        <div class="col-xs-2">
            <h6>Country</h6>
        </div>
        <div class="col-xs-4">
            @(Html.CustomDropdownList<GenericHtml.Models.Country>("CountryId", item.CountryList,
                  "Country_Id", "Name", item.CountryId, null, "form-control"))
        </div>
        
    </div>
    <input type="submit" value="Save" />
   }

تا به اینجا اگر برنامه را اجرا کنید دو عدد dropDown List خواهید دید که اشیا از نوع customer و country را نمایش می دهد .

s

این حالت در داخل GenericHtmlنوشته شده است برای اجرای آن بر روی این پروژه کلیک راست کرده و set as startUp project را می زنیم .

بعد از این می خواهیم که انتخاب چند گانه از این DropDown List  داشته باشیم .این امکان در پروژه جداگانه ای به نام GenericHtml2 اضافه شده است .برای اجرای آن هم می توانید بر روی این پروژه کلیک راست کرده و set as startUp project را بزنید .در ادامه کلاس Helper که برای dropdown نوشته بودیم به صورت زیر تغییر خواهد کرد.

public static partial class HtmlHelperExtensions
{
    /// <summary>
    /// Creates Dropdown List for specified list of objects
    /// </summary>
    /// <typeparam name="T">Type of object for which Dropdown list needs to be created</typeparam>
    /// <param name="htmlHelper">HtmlHelper class</param>
    /// <param name="name">Name of Dropdown List</param>
    /// <param name="itemList">List of class having data to be bound in Dropdown List</param>
    /// <param name="valueField">Property name of class whose value will be used as value of Dropdown List</param>
    /// <param name="textField">Property name of class whose value will be used as text of Dropdown List</param>
    /// <param name="value">Selected value of Dropdown List</param>
    /// <param name="optionLabel">Option Label of Dropdown List</param>
    /// <param name="cssClass">CSS Class to be applied on Dropdown List control</param>
    /// <returns></returns>
    public static MvcHtmlString CustomDropdownList<T>(this HtmlHelper htmlHelper,
        string name, List<T> itemList, string valueField, string textField, int? value, 
        string optionLabel, string cssClass) where T : new()
    {
        StringBuilder sb = new StringBuilder();
        TagBuilder option;
        TagBuilder select = new TagBuilder("select");
        select.MergeAttribute("name", name, true);
        select.GenerateId(name);
        select.MergeAttribute("class", cssClass);
        select.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name));
        sb.Append(select.ToString(TagRenderMode.StartTag));
        if (!string.IsNullOrEmpty(optionLabel) && optionLabel != "null")
        {
            option = new TagBuilder("option");
            option.SetInnerText(optionLabel);
            option.MergeAttribute("Value", "0");
            if (value == 0)
            {
                option.MergeAttribute("Selected", "true");
            }
            sb.Append(option.ToString(TagRenderMode.Normal));
        }
        foreach (T ddl in itemList)
        {
            Type type = ddl.GetType();
            option = new TagBuilder("option");
            option.SetInnerText(Convert.ToString(type.GetProperty(textField).GetValue(ddl, null)));
            option.MergeAttribute("Value", Convert.ToString(type.GetProperty(valueField).GetValue(ddl, null)));
            if (Convert.ToInt32(type.GetProperty(valueField).GetValue(ddl, null)) == value)
            {
                option.MergeAttribute("Selected", "true");
            }
            sb.Append(option.ToString(TagRenderMode.Normal));
        }
        sb.Append(select.ToString(TagRenderMode.EndTag));
        return MvcHtmlString.Create(sb.ToString());
    }
}

و همچنین در کنترلر مربوطه دوباره همان شی را پاس خواهیم داد و در نهایت کدهای View به صورت زیر است

@model IEnumerable<GenericHtml2.Models.VM_Costomer>
@using GenericHtml2.Models
     <div class="row">
         <div class="col-xs-2">
             <h6>Customer</h6>
         </div>
         <div class="col-xs-4">
             @(Html.CustomDropdownList<GenericHtml2.Models.Customer>("CustomerId",Model.Select(p=>p.CustomerList).First(),
                      "CustomerId", "FirstName", Model.Select(t => t.CustomerId).ToArray(), null, "form-control"))
         </div>
         <div class="col-xs-2">
             <h6>Country</h6>
         </div>
         <div class="col-xs-4">
             @(Html.CustomDropdownList<GenericHtml2.Models.Country>("CountryId", Model.Select(p=>p.CountryList).First(),
                       "Country_Id", "Name", Model.Select(t => t.CountryId).ToArray(), null, "form-control"))
         </div>
     </div>
     <input type="submit" value="Save" />

بعد از اجرای برنامه (پروژه با نام GenericHtml2)  شکل زیر را خواهید دید

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید