2011-10-03 23 views
0

我跟隨this blog可以從ViewModels中需要的幾個枚舉創建DropDownLists。如何添加 - 從DropDownList中選擇一些東西 - 從枚舉中創建

到目前爲止,我的代碼看起來像這樣:

public static class HtmlDropDownExtensions 
{ 
    private static readonly SelectListItem [] SingleEmptyItem = new[]{new SelectListItem{Text = string.Empty, Value = string.Empty}}; 

public static MvcHtmlString EnumDropDownList<TEnum>(this HtmlHelper htmlHelper, string modelPropertyName, TEnum selectedValue) 
{ 
    Type baseEnumType = Enum.GetUnderlyingType(typeof(TEnum)); 
    IEnumerable<TEnum> values = Enum.GetValues(typeof (TEnum)).Cast<TEnum>(); 
    IEnumerable<SelectListItem> items = GetSelectListItems(values, selectedValue, baseEnumType); 

    return htmlHelper.DropDownList(modelPropertyName, items); 
} 

public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression) 
{ 
    var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); 
    Type enumType = GetNonNullableModelType(metadata); 

    Type baseEnumType = Enum.GetUnderlyingType(enumType); 
    IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>(); 
    IEnumerable<SelectListItem> items = GetSelectListItems(values, metadata.Model, baseEnumType); 

    if (metadata.IsNullableValueType) 
     items = SingleEmptyItem.Concat(items); 

    return htmlHelper.DropDownListFor(expression, items); 
} 

private static Type GetNonNullableModelType(ModelMetadata modelMetadata) 
{ 
    Type realModelType = modelMetadata.ModelType; 

    Type underlyingType = Nullable.GetUnderlyingType(realModelType); 
    if(underlyingType != null) 
     realModelType = underlyingType; 

    return realModelType; 
} 

private static IEnumerable<SelectListItem> GetSelectListItems<TEnum>(IEnumerable<TEnum> values, object selectedValue, Type underlyingType) 
{ 
    return from value in values 
      select new SelectListItem 
      { 
       Text = value.ToString(), 
       Value = Convert.ChangeType(value, underlyingType).ToString(), 
       Selected = (value.Equals(selectedValue)) 
      }; 
    } 
} 

現在我需要的是能夠有一個提示用戶的第一選擇,以選擇一個選項,是因爲空白或不選擇什麼字段是必需的,並且不能有任何默認值。

更新: 我在想,也許「EnumDropDownList」的方法也可以在創建的DropDownList並返回字符串前加空SelectListItem。我還沒有嘗試過,但我認爲MVC工程將嘗試將其綁定到ViewModel時會出現錯誤,因爲無法將該值解析到ViewModel的枚舉屬性中。

感謝您的幫助。

+0

在列表的開始處插入默認項:dropdownlist.Insert(0,defaultItem); – MrFox

+0

@MFFOX:對不起,糾正我,如果我錯了,但我認爲這隻會在Web窗體解決方案,而不是在MVC之一。 –

回答

0

其實你已經擁有了一切實現的:

if (metadata.IsNullableValueType) 
    items = SingleEmptyItem.Concat(items); 

如果模型的屬性是Nullable<YourEnum>類型的,這個代碼將在DropDownList中的開頭添加默認項。

但是,如果屬性不允許空值,則不會呈現默認值。這是正確的行爲 - 應該要求用戶輸入內容並且不應該看到任何默認項目。

如果要更改默認值的文本,去SingleEmptyItem定義:

private static readonly SelectListItem [] SingleEmptyItem = new[]{new SelectListItem{Text = "Your text here", Value = string.Empty}}; 
+0

所以,如果我正確理解我將不得不做的是使所有我的枚舉屬性可以爲空,並創建一些自定義DataAnotaion必需屬性來驗證該屬性不爲空。對?這是這個要求的最佳解決方案還是我讓事情變得複雜?非常感謝你的想法。 –

+0

如果您不想讓枚舉屬性接受空值,那麼爲什麼要將空值添加到相應的下拉列表中?就我個人而言,我沒有看到任何理由。但是,如果您仍想在下拉列表中選擇默認值「--Select--」,但需要禁用空值,則可以將枚舉屬性設置爲空,並使用「System.ComponentModel.DataAnnotations.RequiredAttribute'屬性對其進行裝飾。由於您的默認值爲「」,因此此屬性將導致驗證失敗,並且用戶需要從下拉列表中選擇任何內容。希望能幫助到你! – Andrei

+0

請允許我解釋一下。我正在構建一個入口表單,其中有許多由枚舉形成的下拉字段。例如,一個字段是出生國家。由於用戶不僅可以選擇他的出生國,而且還可以發送預先選擇的數據,這樣會使我們的數據不正確,因此用戶不能提交表格。這就是爲什麼我問這個問題還是我過分複雜的問題? –