【问题标题】:View not binding dropdownlist selected value back to Model查看未将下拉列表选择的值绑定回模型
【发布时间】:2012-05-16 20:11:41
【问题描述】:

我正在寻找一种将模型中的枚举绑定到下拉列表的方法。我找到了this 帖子并使用了第二个答案中的代码,它在创建下拉列表时效果很好。但是,当我提交表单时,它总是将模型与枚举的第一个值一起传回。

枚举(包含在我的模型中):

public LayoutType Layout;
public enum LayoutType
{
    Undefined = 0,
    OneColumn = 1,
    TwoColumn = 2,
    ThreeColumn = 3
}

Html 辅助方法:

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

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

    private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };

    public static string GetEnumDescription<TEnum>(TEnum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

        if ((attributes != null) && (attributes.Length > 0))
            return attributes[0].Description;
        else
            return value.ToString();
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
    {
        return EnumDropDownListFor(htmlHelper, expression, null);
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
    {
        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        Type enumType = GetNonNullableModelType(metadata);
        IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();

        IEnumerable<SelectListItem> items = from value in values
                                            select new SelectListItem
                                            {
                                                Text = GetEnumDescription(value),
                                                Value = value.ToString(),
                                                Selected = value.Equals(metadata.Model)
                                            };

        // If the enum is nullable, add an 'empty' item to the collection
        if (metadata.IsNullableValueType)
            items = SingleEmptyItem.Concat(items);

        return htmlHelper.DropDownListFor(expression, items, htmlAttributes);
    }

查看:

@Html.EnumDropDownListFor(model => model.Layout)

在呈现视图时,下拉列表按预期完全填充,并且选择了正确的值。但是当我提交一个 POST 并将值传回我的控制器时,我对 Model.Layout 的值始终是“未定义”。任何帮助将不胜感激!谢谢,

【问题讨论】:

  • 为什么不能基于枚举创建一个SelectList?或者取消枚举并创建SelectList?这样你就可以使用开箱即用的助手,模型绑定就没有压力了:)
  • 你试过了吗? stackoverflow.com/questions/4656758/…(你的代码看起来不一样)

标签: asp.net-mvc-3 razor


【解决方案1】:

如果您使用的是 VB.Net - MVC4- Razor 这个答案和 Frigik 几乎一样(感谢 Frigik)

在您的模型中创建两个字段,一个是保存 SelectedItem 的字段(这里是字符串的 TagType),第二个是下拉值(TagTypeList)

模型类-Tag.vb

Imports System.Web.Mvc

Private _tagType As String
Private _tagTypeList As List(Of SelectListItem)

Public Property TagType() As String
        Get
            Return _tagType
        End Get
        Set(ByVal value As String)
            _tagType = value
        End Set
End Property

Public Property TagTypeList() As List(Of SelectListItem)
        Get
            Return _tagTypeList
        End Get
        Set(value As List(Of SelectListItem))
            _tagTypeList = value
        End Set
    End Property

'In the constructor

Sub New()
        TagTypeList = CommonUtility.LoadDropDownByName("TAGTYPE")
End Sub

在 CommonUtility 类中 - CommonUtility.vb

Imports System.Web.Mvc
Imports System.Collections.Generic


Public Shared Function LoadDropDownByName(ByVal DropDownName As String) As List(Of SelectListItem)
        Dim dt As DataTable
        Dim ds As DataSet
        Dim results As List(Of SelectListItem) = Nothing
        Try
            ds = obj.LoadDropDown(DropDownName)   'Pass the dropdown name here and get the values from DB table which is - select ddlId, ddlDesc from <table name>
            If Not ds Is Nothing Then
                dt = ds.Tables(0)
                If (dt.Rows.Count > 0) Then
                    results = (From p In dt Select New SelectListItem With {.Text = p.Item("ddlDesc").ToString(), .Value = p.Item("ddlId").ToString()}).ToList()
                End If
            End If
        Catch ex As Exception
        End Try
        Return results
    End Function

在视图中

@Html.DropDownListFor(Function(x) x.TagType, Model.TagTypeList, "", New With {.id = "ddlTagType",.class = "dropDown", .style = "width: 140px"})

这里的第三个参数(可选)为空,它将在下拉菜单中插入第一个为空的项目。第一个参数是 selectedItem,一旦值已经存在于 DB 表中,它有助于填充。

希望这对正在使用 VB.Net 的人有所帮助

【讨论】:

    【解决方案2】:

    在您的模型中创建两个字段,一个应包含选定项 (SelectedItem) 第二个下拉值 (GroupNames)

      public string SelectedItem { get; set; }
    
      [Required]
      public IEnumerable<SelectListItem> GroupNames { get; set; }
    

    然后在构造函数中填写 GroupNames 例如

    GroupNames = layer.GetAll().Select(p => new SelectListItem
                                                            {
                                                                Value = p.Id.ToString(CultureInfo.InvariantCulture),
                                                                Text = p.Name,
                                                                Selected = p.Id == someEntity.someFK
                                                            });
                SelectedItem = GroupNames.Where(p => p.Selected).Select(p => p.Value).Single();
    

    然后在视图中渲染像这样的下拉:

     @Html.DropDownListFor(x => x.SelectedItem, Model.GroupNames)
    

    所有选择的值都应该在 SelectedItem 字段中带有模型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-11
      • 2013-09-09
      • 1970-01-01
      • 2019-02-01
      • 1970-01-01
      • 2011-10-02
      • 2018-05-11
      • 2011-07-08
      相关资源
      最近更新 更多