在建設網站當中,生成下拉框本來是一件非常微不足道的事,但是在實際應用當中,我常常會碰到這樣的一個場景:剛開始設計時僅固定爲幾個下拉選項,但是經過幾次迭代和需求更改之後,這個下拉選項會不斷地被要求改來改去。
當然,我們希望這個下拉框是動態讀取數據庫中的數據,並實現動態的後臺可視化管理,但有些場景下並不會提供一張表數據。
所以在一次開發中,我突然冒出一個想法。借用類似Dictionary的鍵值映射關係,因爲下拉框元素也剛好可以看成這樣的鍵-值對的形式。
所以我自定義了一個映射的類如下:
<span style="font-family:Courier New;">public class MapEntity
{
#region 屬性
/// <summary>
/// 鍵
/// </summary>
public long Key { set; get; }
/// <summary>
/// 值
/// </summary>
public string Value { get; set; }
/// <summary>
/// 是否啓用
/// </summary>
public bool Enable { get; set; }
#endregion
#region 構造方法
/// <summary>
/// 默認
/// </summary>
public MapEntity() { }
/// <summary>
/// 構造函數
/// </summary>
/// <param name="key">主鍵</param>
/// <param name="value">值</param>
/// <param name="enable">是否啓用標誌, 默認啓用</param>
public MapEntity(long key, string value, bool enable = true)
{
this.Key = key;
this.Value = value;
}
#endregion
}</span>
因爲在這種景中,所的供的下拉選項僅僅是幾種狀態或是各種選項,這個狀態選項又是跟其它的業務相關聯的,故定義一個枚舉,示例如下:
<span style="font-family:Courier New;">public enum ActiveStatusEnum : int
{
/// <summary>
/// 未審覈
/// </summary>
[Description("未審覈")]
UnAudit = 1,
/// <summary>
/// 等待
/// </summary>
[Description("等待")]
Wait = 2,
/// <summary>
/// 就緒
/// </summary>
[Description("就緒")]
Ready = 3,
/// <summary>
/// 開始
/// </summary>
[Description("開始")]
Start = 4,
/// <summary>
/// 完成
/// </summary>
[Description("完成")]
Finish = 5,
/// <summary>
/// 停止
/// </summary>
[Description("停止")]
Stop = -1
}</span>
然後寫一個輔助類,封裝 方法:
<span style="font-family:Courier New;">public class MapHelper
{
public static MapEntity[] WorkList = new MapEntity[] {
new MapEntity( (int)ActiveStatusEnum.UnAudit, "未審覈" ),
new MapEntity( (int)ActiveStatusEnum.Wait, "等待" ),
new MapEntity( (int)ActiveStatusEnum.Ready, "準備" ),
new MapEntity( (int)ActiveStatusEnum.Start, "開始" ),
new MapEntity( (int)ActiveStatusEnum.Finish, "完成" ),
new MapEntity( (int)ActiveStatusEnum.Stop, "終止", false),
};
#region 生成下拉框元素集合
/// <summary>
/// 生成下拉框元素集合
/// </summary>
/// <param name="fillArray"></param>
/// <param name="pId"></param>
/// <param name="IsNeedAll"></param>
/// <returns></returns>
public static List<SelectListItem> GetDropDownList(MapEntity[] fillArray, long pId, bool IsNeedAll = false )
{
List<SelectListItem> ReturnObj = new List<SelectListItem>();
if (pId == Int32.MinValue) //如果等於最小值,則直接返回
{
return ReturnObj;
}
foreach (var item in fillArray) //遍歷數組元素生成下拉框
{
SelectListItem ItemObj = new SelectListItem();
ItemObj.Text = item.Value;
ItemObj.Value = item.Key.ToString();
ItemObj.Selected = item.Key == pId;
ReturnObj.Add(ItemObj);
}
if (IsNeedAll) //是否需要插入全部選項
{
SelectListItem ItemObj = new SelectListItem();
ItemObj.Text = "全部";
ItemObj.Value = "-1";
ItemObj.Selected = pId == -1;
ReturnObj.Add(ItemObj);
}
return ReturnObj;
}
#endregion
#region 通過
/// <summary>
/// 通過鍵 獲取映射值
/// </summary>
/// <param name="fillArray">集合對象</param>
/// <param name="key">指定鍵</param>
/// <param name="IsIgnoreEnable">是否忽略"是否啓用"選項,默認否</param>
/// <returns></returns>
public static string GetMappingValueByKey(MapEntity[] fillArray, long key, bool IsIgnoreEnable = false)
{
foreach (var item in fillArray)
{
if (item.Key == key)
{
if ( ( !IsIgnoreEnable && item.Enable ) || IsIgnoreEnable )
{
return item.Value;
}
}
}
return string.Empty;
}
/// <summary>
/// 通過鍵 獲取映射值
/// </summary>
/// <param name="fillArray">集合對象</param>
/// <param name="Value">值</param>
/// <param name="IsIgnoreEnable">是否忽略"是否啓用"選項,默認否</param>
/// <param name="IsIgnoreCase">是否忽略大小寫,默認否</param>
/// <returns>如果集合中的鍵存在-999,則不適合此方法</returns>
public static long GetMappingKeyByValue(MapEntity[] fillArray, string Value, bool IsIgnoreCase = false, bool IsIgnoreEnable = false)
{
if (string.IsNullOrEmpty(Value))
{
return -999;
}
foreach (var item in fillArray)
{
if (IsIgnoreCase)
{
//忽略大小寫
if (item.Value.ToLower().Equals(Value.ToLower()))
{
if ((!IsIgnoreEnable && item.Enable) || IsIgnoreEnable)
{
return item.Key;
}
}
}
else
{
//不忽略大小寫
if (item.Value.Equals(Value))
{
if ((!IsIgnoreEnable && item.Enable) || IsIgnoreEnable)
{
return item.Key;
}
}
}
}
return -999;
}
#endregion
}</span>
最後調用時,如下:
<span style="font-family:Courier New;"> public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
ViewData["DDList"] = MapHelper.GetDropDownList(
MapHelper.WorkList, (int)ActiveStatusEnum.UnAudit);
return View();
}
}</span>
所以在下次進行變更的時候,只需要設置Enabled屬性,可以設置啓用或者不啓用,也可以隨時添加新的選項。這樣非常的靈活方便。
當然,這裏其實可以有另外的一種方法,那就是通過反射機制。代碼如下:
<span style="font-family:Courier New;"> /// <summary>
///
/// </summary>
/// <param name="EnumType">枚舉對象的類型</param>
/// <param name="pId">指定的枚舉名稱</param>
/// <param name="IsNeedAll">是否需要添加全部選項</param>
/// <returns></returns>
public static List<SelectListItem> GetDropDownList(Type EnumType, string pId, bool IsNeedAll = false)
{
List<SelectListItem> ResultObj = new List<SelectListItem>();
//獲取當前對象類型的所有成員
MemberInfo[] MemberArray = EnumType.GetMembers()
.Where(s => s.MemberType.Equals(MemberTypes.Field) && !s.Name.Equals("value__")).ToArray();
bool IsFind = false;
foreach (var memberItem in MemberArray)
{
//獲取當前成員的自定義特性
IEnumerable<CustomAttributeData> CustomArray = memberItem.CustomAttributes;
SelectListItem SelObj = new SelectListItem();
foreach(var customItem in CustomArray)
{
//這裏因爲只設置了DescriptionAttribute,所以在讀取第一條後直接跳出
SelObj.Text = customItem.ConstructorArguments[0].Value.ToString();
break;
}
SelObj.Value = memberItem.Name;
SelObj.Selected = IsFind = memberItem.Name.Equals(pId);
ResultObj.Add(SelObj);
}
if (IsNeedAll)
{
if (IsNeedAll) //是否需要插入全部選項
{
SelectListItem ItemObj = new SelectListItem();
ItemObj.Text = "全部";
ItemObj.Value = "-1";
ItemObj.Selected = !IsFind;
ResultObj.Add(ItemObj);
}
}
return ResultObj;
}</span>
在調用時,只需要傳入如下參數示例:
ViewData["DDList2"] = MapHelper.GetDropDownList(typeof(ActiveStatusEnum), ActiveStatusEnum.UnAudit.ToString());
雖然反射機制也是可以實現,但是卻少了一些控制上的靈活性以及多了一些性能上的損耗,相比之下,自定義的映射類,可以自定義屬性控制開關,添加額外的信息等等。
這只是在寫代碼過程中一些小的思考,希望自己能有更多的這樣的思考,積少成多!加油!