MVC ile uğraşanlar bilirler. MVC'nin kendi Helper'ları bazen istediklerinizi yapamazlar :(
Bizlerde bu tür durumlarda oturur 3rd party uygulamalara yöneliriz ki bazen onlarda bizim ihtiyacımızı göremezler. Neyse lafı çok fazla uzatmadan konuya gelelim. DropDownList (HTML Select) nesnesi kullanımında özel bir duruma ihtiyaç duydum. Option nesnelerine özel eklemek istediğim attribute ler vardı ama MVC Helper ile bunu yapmanın bir yolunuda bulamadım :( ve oturdum kendi MVC Helper'ımı yazdım :) diğer adı ile namı değer DropDownList.
İlk olarak kodumuz .net 4.5 ve MVC 4.0 üzerinde geliştirildi.
En çok eklediğimiz Seçiniz, Hepsi ve her ikisinin birlikte kullanıldığı durumları otomatik olarak ekliyor siz başka seçenekleri de ekleyebilirsiniz :)
Kodda İlk olarak Enum'larımız ve Struct'larımı ile başlayalım;
namespace CustomDropDownList.Core
{
public class Enums
{
public enum SelectListDataSource
{
DataInternal = 1,
External = 2
}
public enum SelectListAddOption
{
Select = 1,
All = 2,
SelectAndAll = 3,
None = 4
}
}
}
namespace CustomDropDownList.Core
{
public class DropDownListValues
{
public const short SelectValue = -1;
public const short SelectAllValue = -2;
}
}
İkinci olarak SelectListItem ile devam edelim;
using System.Collections.Generic;
using System.Text;
namespace CustomDropDownList.Extensions
{
public class SelectListItem
{
public Dictionary<string, object> OptionAttribute { get; set; }
public Dictionary<string, object> HtmlAttribute { get; set; }
public bool Selected { get; set; }
public string Text { get; set; }
public object Value { get; set; }
public SelectListItem()
{}
public SelectListItem(string text, string value)
{
Text = text;
Value = value;
}
public SelectListItem(string text, string value, Dictionary<string, object> optionAttribute) : this(text, value)
{
OptionAttribute = optionAttribute;
}
public SelectListItem(string text, string value, Dictionary<string, object> optionAttribute = null, Dictionary<string, object> htmlAttribute = null) : this(text, value, optionAttribute)
{
HtmlAttribute = htmlAttribute;
}
public override string ToString()
{
var opAttr = new StringBuilder();
if (OptionAttribute != null)
foreach (var o in OptionAttribute)
opAttr.Append(string.Format(" data-{0}=\"{1}\"", o.Key, o.Value));
if (HtmlAttribute != null)
foreach (var h in HtmlAttribute)
opAttr.Append(string.Format(" {0}=\"{1}\"", h.Key, h.Value));
if (Selected)
opAttr.Append(" selected=\"selected\"");
return string.Format("<option value=\"{0}\"{2}>{1}</option>", Value, Text, opAttr);
}
}
}
Üçüncü olarak SelectList ile devam edelim;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using CustomDropDownList.Core;
namespace CustomDropDownList.Extensions
{
public class SelectList
{
public List<SelectListItem> OptionItems { get; private set; }
public string OptionItemsHtml { get; private set; }
public IEnumerable Items { get; private set; }
public string DataTextField { get; private set; }
public string DataValueField { get; private set; }
public object SelectedValue { get; set; }
public Dictionary<string, object> OptionAttributes { get; private set; }
public Dictionary<string, object> HtmlAttributes { get; private set; }
public Enums.SelectListDataSource OptionDataType { get; private set; }
public SelectList(IEnumerable items,
string dataValueField,
string dataTextField,
object selectedValue = null,
Dictionary<string, object> optionFields = null,
Dictionary<string, object> htmlAttribute = null,
Enums.SelectListDataSource optionDataType = Enums.SelectListDataSource.DataInternal)
{
DataTextField = dataTextField;
DataValueField = dataValueField;
OptionAttributes = optionFields;
HtmlAttributes = htmlAttribute;
OptionDataType = optionDataType;
Items = items;
SelectedValue = selectedValue;
OptionItems = new List<SelectListItem>();
Generator();
}
private void Generator()
{
var htmlString = new StringBuilder();
foreach (var i in Items)
{
var dv = i.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).SingleOrDefault(p => p.Name == DataValueField);
var dt = i.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).SingleOrDefault(p => p.Name == DataTextField);
if (dv != null && dt != null)
{
OptionItems.Add(new SelectListItem
{
Value = dv.GetValue(i),
Text = dt.GetValue(i).ToString(),
OptionAttribute = AttributeGenerator(OptionAttributes, i, true),
HtmlAttribute = AttributeGenerator(HtmlAttributes, i),
Selected = SelectedValue != null && dv.GetValue(i).ToString() == SelectedValue.ToString()
});
htmlString.Append(OptionItems.Last().ToString());
}
}
OptionItemsHtml = htmlString.ToString();
}
private Dictionary<string, object> AttributeGenerator(Dictionary<string, object> attributes, object item, bool isOptionAttribute = false)
{
var attr = new Dictionary<string, object>();
if (attributes != null)
{
foreach (var h in attributes)
{
if (!string.IsNullOrWhiteSpace(h.Key) && h.Value != null)
{
object attrDataValue = null;
if (isOptionAttribute && OptionDataType == Enums.SelectListDataSource.DataInternal)
{
var entityData = item.GetType().GetProperties().SingleOrDefault(p => p.Name == h.Value.ToString());
if (entityData != null)
attrDataValue = entityData.GetValue(item);
}
else
{
attrDataValue = h.Value;
}
if (attrDataValue != null && !string.IsNullOrWhiteSpace(attrDataValue.ToString()))
{
attr.Add(h.Key, attrDataValue);
}
}
}
}
return attr;
}
}
}
Dördüncü olarak SelectExtension ile devam edelim;
using System.Collections.Generic;
using System.Web.Mvc;
using CustomDropDownList.Core;
namespace CustomDropDownList.Extensions
{
public static class SelectExtension
{
public static string Name { get; set; }
public static string ID { get; set; }
public static SelectList SelectList { get; set; }
public static Dictionary<string, object> HtmlAttributes { get; set; }
public static Enums.SelectListAddOption AddOption { get; set; }
private static MvcHtmlString Generator()
{
var builder = new TagBuilder("select");
builder.MergeAttribute("name", Name);
if (!string.IsNullOrWhiteSpace(ID))
builder.MergeAttribute("id", ID);
if (HtmlAttributes != null)
foreach (var h in HtmlAttributes)
builder.MergeAttribute(h.Key, h.Value.ToString());
switch (AddOption)
{
case Enums.SelectListAddOption.Select:
builder.InnerHtml += string.Format("<option value=\"{0}\">{1}</option>", DropDownListValues.SelectValue, "Select") + "\n";
break;
case Enums.SelectListAddOption.All:
builder.InnerHtml += string.Format("<option value=\"{0}\">{1}</option>", DropDownListValues.SelectAllValue, "All") + "\n";
break;
case Enums.SelectListAddOption.SelectAndAll:
builder.InnerHtml += string.Format("<option value=\"{0}\">{1}</option>", DropDownListValues.SelectValue, "Select") + "\n";
builder.InnerHtml += string.Format("<option value=\"{0}\">{1}</option>", DropDownListValues.SelectAllValue, "All") + "\n";
break;
}
builder.InnerHtml += SelectList.OptionItemsHtml + "\n";
return MvcHtmlString.Create(builder.ToString(TagRenderMode.Normal));
}
public static MvcHtmlString DropDownList(this HtmlHelper htmlHelper,
string name,
SelectList selectList,
Enums.SelectListAddOption addOption = Enums.SelectListAddOption.None,
string id = "",
Dictionary<string, object> htmlAttributes = null)
{
Name = name;
ID = id;
SelectList = selectList;
AddOption = addOption;
HtmlAttributes = htmlAttributes;
return Generator();
}
}
}
Ve son adım olarak cshtml içersinde örnek kullanım ile bitirelim;
@using CustomDropDownList.Extensions
@using CustomDropDownList.Core
@{
ViewBag.Title = "Custom DropDownList Test";
}
@Html.DropDownList("Cities",
new CustomDropDownList.Extensions.SelectList(
ViewBag.Cities, // Data Items
"CityID", // DataValueField
"Name", // DataTextField
null, // SelectedValue
new Dictionary<string, object> {
{ "NationalName", "NationalName" }
}, // Option Attributes
null, //HTML Attributes
Enums.SelectListDataSource.DataInternal
),
Enums.SelectListAddOption.Select, // DropDownList Select Options
"Cities", // DropDownList Html ID
new Dictionary<string, object> { // DropDownList Custom Html Attributes
{ "class", "location-items"}
})
Umarım işinize yarar ve lütfen unutmayın ki oldukça hızlı yazdığım bir kod atladığım yerler olabilir af ola :)
Sevgiler,
Cihan.