2013-11-04 58 views
2

我從數據庫填充Dropdownlist,並且想通過設置其「class」屬性以紅色顯示某些元素。所以,我嘗試了很多方法,後來我爲Dropdownlist創建了一個自定義HTML助手。但它沒有任何意義,雖然它似乎添加了class屬性,但此參數無法傳遞到Controller的Razor View。你能幫忙嗎?爲MVC4中的Dropdownlist的某些記錄設置類屬性

MyHelper.cs:

public static MvcHtmlString Custom_DropdownList(this HtmlHelper helper, string name, IEnumerable<SelectListItem> list, object htmlAttributes) 
{   
    TagBuilder dropdown = new TagBuilder("select"); 
    dropdown.Attributes.Add("name", name); 
    dropdown.Attributes.Add("id", name); 
    StringBuilder options = new StringBuilder(); 
    foreach (var item in list) 
    {    
     options = options.Append("<option value='" + item.Value + "'>" + item.Text + "</option>"); 
    } 
    dropdown.InnerHtml = options.ToString(); 
    dropdown.MergeAttributes(new RouteValueDictionary(htmlAttributes)); 
    return MvcHtmlString.Create(dropdown.ToString(TagRenderMode.Normal)); 
} 


控制器:

private void PopulateMeetingsDropDownList(object selectedMeetings = null) 
{ 
    var meetingsQuery = repository.Meetings 
    .Join(repository.Cities, m => m.MeetingCityId, c => c.CityID, 
    (m, c) => new 
    { 
     CityID = c.CityID, 
     CityName = c.CityName, 
     MeetingDate = m.MeetingStartDate 
    } 
    ) 
    .OrderBy(x => x.CityID) 
    .AsEnumerable() 
    .Select(
    i => new 
    { 
     CityID = i.CityID, 
     Name = string.Format(
     "{0} ({1:dd MMMM yyyy})", 
     i.CityName, i.MeetingDate), 
     Expired = i.MeetingDate < DateTime.UtcNow 
    } 
    ).ToList(); 

    var selectItems = new List<SelectListItem>(meetingsQuery.Count); 
    foreach (var record in meetingsQuery) 
    { 
     var item = new SelectListItem 
     { 
      Text = record.Name, 
      Value = record.Name 
     }; 
     if (record.Expired) 
     { 
      item.Attributes.Add("class", "disabled"); //!!! Problem on this line 
     } 
      selectItems.Add(item); 
    } 
    ViewData["MeetingId"] = new SelectList(meetingsQuery, "CityID", "Name", selectedMeetings); 
} 

但以這種方法,我做了錯誤「 'System.Web.Mvc.SelectListItem' 後不包含「屬性」的定義,也沒有包含「接受類型的第一個參數」的擴展方法「屬性」。因此,我認爲我需要使用其他屬性或幫助程序將類屬性分配給自定義racords(對「if(record.Expired)」 line)過濾記錄沒有問題。


查看:

@Html.Custom_DropdownList("MeetingId", ViewData["MeetingId"] as SelectList, new { id = "meetingId"}) 

你能澄清我怎麼提供呢?提前致謝。



這裏是具有兩個類和禁用屬性能力改性殼聚糖代碼:

更新的代碼(用於MyDropdownListFor):

定製HTML輔助類別:

public static class MyHelpers 
{ 
    public class MySelectItem : SelectListItem 
    { 
     public string Class { get; set; } 
     public string Disabled { get; set; } 
    } 

    public static MvcHtmlString MyDropdownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<MySelectItem> list, string optionLabel, object htmlAttributes) 
    { 
     return MyDropdownList(htmlHelper, ExpressionHelper.GetExpressionText(expression), list, optionLabel, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)); 
    } 

    public static MvcHtmlString MyDropdownList(this HtmlHelper htmlHelper, string name, IEnumerable<MySelectItem> list, string optionLabel, IDictionary<string, object> htmlAttributes) 
    { 
     TagBuilder dropdown = new TagBuilder("select"); 
     dropdown.Attributes.Add("name", name); 
     dropdown.Attributes.Add("id", name); 
     StringBuilder options = new StringBuilder(); 

     // Make optionLabel the first item that gets rendered. 
     if (optionLabel != null) 
      options = options.Append("<option value='" + String.Empty + "'>" + optionLabel + "</option>"); 

     foreach (var item in list) 
     { 
      if(item.Disabled == "disabled") 
       options = options.Append("<option value='" + item.Value + "' class='" + item.Class + "' disabled='" + item.Disabled + "'>" + item.Text + "</option>"); 
      else 
       options = options.Append("<option value='" + item.Value + "' class='" + item.Class + "'>" + item.Text + "</option>"); 
     } 
     dropdown.InnerHtml = options.ToString(); 
     dropdown.MergeAttributes(new RouteValueDictionary(htmlAttributes)); 
     return MvcHtmlString.Create(dropdown.ToString(TagRenderMode.Normal)); 
    } 
} 


控制器:

private void PopulateMeetingsDropDownList(object selectedMeetings = null) 
    { 
     var meetingsQuery = repository.Meetings 
      .Join(repository.Cities, m => m.MeetingCityId, c => c.CityID, 
       (m, c) => new 
       { 
        CityID = c.CityID, 
        CityName = c.CityName, 
        MeetingDate = m.MeetingStartDate 
       } 
      ) 
      .OrderBy(x => x.CityID) 
      .AsEnumerable() 
      .Select(
       i => new 
       { 
        Value = i.CityID.ToString(), 
        DisplayValue = string.Format(
         "{0} ({1:dd MMMM yyyy})", 
         i.CityName, i.MeetingDate), 
        Expired = i.MeetingDate < DateTime.UtcNow 
       } 
      ).ToList(); 


     var selectItems = new List<MyHelpers.MySelectItem>(meetingsQuery.Count); 
     foreach (var record in meetingsQuery) 
     { 
      var item = new MyHelpers.MySelectItem 
      { 
       Text = record.DisplayValue, 
       Value = record.Value 
      }; 
      if (record.Expired) 
      { 
       item.Class = "disabled"; 
       item.Disabled = "disabled"; 
      } 
      selectItems.Add(item); 
     } 
     ViewBag.MeetingData = selectItems; 
    } 


檢視:

<label>Meeting</label>   
@Html.MyDropdownListFor(m => m.MeetingId, ViewBag.MeetingData as List<MyHelpers.MySelectItem>, "---- Select ----", 
new { name = "meetingId", id = "meetingId"}) 


+0

退房這樣的回答:[http://stackoverflow.com/a/7537628/674700](http://stackoverflow.com/a/7537628/674700)。 –

+0

這是一個靜態列表,我認爲該主題與我的問題沒有太大關係。 –

+0

最簡單的方法是連接文本屬性與文本和類的東西像文本#類,然後在助手分裂它......從代碼的角度來看它是不正確的..但這件事不會改變你現有的代碼...如果將來你想添加更多的屬性或樂趣,那麼斯拉沃的答案是正確的...創建自定義的一個.. –

回答

2

TL; DR;您正在使用SelectList,但您不需要。

創建一個新的視圖模型類,您將傳遞給視圖。它將包含所有你需要的屬性,可能是這樣的:

自定義類以保存有關項目的信息:

public class CustomSelectItem 
{ 
    public string Text {get;set;} 
    public string Value {get;set;} 
    public string Class {get;set;} 
    public bool Selected {get;set;} 
} 

既然你逝去的ViewData使用這些數據,你不必一個限制,你可以把任何東西放在那裏。我建議你使用ViewBag而不是ViewData。

在您的控制器中,您可以創建一個新的List<CustomSelectItem>並通過它。在構建集合時,如果項目已過期,只需將Class屬性設置爲「disabled」或您正在使用的任何內容。下面是代碼(我跳過了部分你在哪裏得到的會議):

控制器:

var selectItems = new List<CustomSelectItem>(meetingsQuery.Count); 
foreach (var record in meetingsQuery) 
{ 
    var item = new CustomSelectItem 
    { 
     Text = record.Name, 
     Value = record.Name 
    }; 
    if (record.Expired) 
    { 
     item.Class = "disabled"; 
    } 
    selectItems.Add(item); 
} 
ViewBag.MeetingData = selectItems; 

然後修改您已經創建了接受CustomSelectItem而不是SelectListItem集合定製的輔助方法。您可以直接編寫HTML,因爲您可以訪問Class屬性。

定製的輔助方法:

public static MvcHtmlString Custom_DropdownList(this HtmlHelper helper, string name, IList<CustomSelectItem> list, object htmlAttributes) 
{ 
    TagBuilder dropdown = new TagBuilder("select"); 
    dropdown.Attributes.Add("name", name); 
    dropdown.Attributes.Add("id", name); 
    StringBuilder options = new StringBuilder(); 
    foreach (var item in list) 
    { 
     options = options.Append("<option value='" + item.Value + "' class='" + item.Class + "'>" + item.Text + "</option>"); 
    } 
    dropdown.InnerHtml = options.ToString(); 
    dropdown.MergeAttributes(new RouteValueDictionary(htmlAttributes)); 
    return MvcHtmlString.Create(dropdown.ToString(TagRenderMode.Normal)); 
} 

一旦做到這一點,你可以從視圖調用助手如下:

查看:

@Html.Custom_DropdownList("MeetingId", ViewBag.MeetingData as List<CustomListItem>, new { id = "meetingId"}) 
+0

感謝您的回覆。但是,如果可以編輯包含View和Controller上的其他更改的回覆(如果還需要Custom HTML helper)。 BR。 –

+0

我也嘗試應用這個邏輯。但是我遇到了「無法將lambda表達式轉換爲'string'類型,因爲它不是委託類型」錯誤。那麼,你能否給我在View類中使用DDL和在新類中使用Helper方法?謝謝。 –

+0

我用代碼更新了我的答案。 – Slavo

2

你可以繼承SelectList並將自己的屬性添加到類中,如下所示:

public class MySelectListItem : SelectListItem 
{ 
    public bool Highlighted { get; set; } 
} 

一旦你有了自定義類,就可以根據它編寫你的幫助器。您可以應用不同的CSS類或更改樣式屬性。

public static class MyHtmlHelpers 
{ 
    public static MvcHtmlString DropDownListHighlighted(this HtmlHelper helper, string name, IEnumerable<MySelectListItem> itens) 
    { 
     StringBuilder dropDown = new St(); 
     dropDown.AppendFormat("<select id='{0}' name='{0}'>", name); 

     foreach (var item in itens) 
     { 
      dropDown.AppendFormat("<option selected='{2}' value='{1}' class='{3}'>{0}</option>", 
       item.Text, 
       item.Value, 
       item.Selected ? "selected" : "", 
       item.Highlighted ? "highlighted" : "normal"); 
     } 

     dropDown.Append("</select>"); 

     return MvcHtmlString.Create(dropDown.ToString()); 
    } 
} 

在您的視圖(不要忘記在web.config中或在視圖中添加你的HTML輔助類的命名空間):

@Html.DropDownListHighlighted("DropDown", ViewData["DropDownOptions"] as List<MySelectListItem>) 

DropDownListHighlightedFor

你可以這樣做來實現一個簡單的DropDownListHighlightedFor:

public static MvcHtmlString DropDownListHighlightedFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<MySelectListItem> itens) 
{ 
    return DropDownListHighlighted(htmlHelper, ExpressionHelper.GetExpressionText(expression), itens); 
} 

在視圖:

@Html.DropDownListHighlightedFor(x => x.Option, ViewData["DropDownOptions"] as List<MySelectListItem>) 
+0

試圖應用此邏輯,我遇到第一個「不能轉換爲類型'字符串',因爲它不是一個委託類型的lambda表達式」,然後「擴展方法必須在非泛型靜態類中定義」錯誤。在查找錯誤之後,我應用了關於論壇的所有建議,但是當我使用static關鍵字時,我得到了另一個錯誤。因此,您可以查看上面的代碼,並給出一個示例,指出DropDownListHighlighted使用行的HTML Helper和View代碼,如@ Html.DropDownListHighlighted(「meetingId」,ViewData [「MeetingId」]爲MySelectListItem)。 –

+0

我在答案處添加了視圖代碼。請注意,該助手期待一個IEnumerable。 –

+0

關於第二個錯誤,您的擴展方法必須在靜態類中定義(更多詳細信息:[擴展方法](http://msdn.microsoft.com/en-us/library/vstudio/bb383977.aspx)。 –

相關問題