Html。EnumDropDownListFor根据enum变量的值设置选定的listitem

时间:2021-08-29 11:55:42

This may be a duplicate, so I have indicated where my reading from this site has allowed me some progress...

这可能是一份副本,所以我已经指出我在这个网站上的阅读让我取得了一些进步……

I have a model defined as follows:

我有一个定义如下的模型:

public enum RequestType
{
    [Display(Name = "Lovely Cold Beer")]
    Beer = 0,
    [Display(Name = "Warm Tea")]
    Tea = 1,
    [Display(Name = "Milky Coffee")]
    Coffee= 2
}

Based on the URL, I have a variable that will be used to automatically select the appropriate list item, e.g.

基于URL,我有一个变量,用于自动选择适当的列表项。

http://example.com/Request/Tea

will do this in the controller...

会在控制器中做这个…

ViewBag.RequestType = RequestType.Tea.ToString();
return View("Index");

In my view I have a variable to read this value back, which then displays appropriate content:

在我看来,我有一个变量来读取这个值,然后显示适当的内容:

if (ViewBag.RequestType != null)
{
    reqType = Enum.Parse(typeof(RequestType), ViewBag.RequestType);
}

In this view I create a drop down list using:

在这个视图中,我使用以下方法创建一个下拉列表:

@Html.EnumDropDownListFor(model => model.RequestType, htmlAttributes: new { @onchange = "YadaYada();" })

This renders the list using the Display Name values defined for each Enum. What I need is to automatically select the appropriate list item when the page is rendered, that matches the value of reqType.

这将使用为每个枚举定义的显示名称值来呈现列表。我需要的是在呈现页面时自动选择适当的列表项,该列表项与reqType的值匹配。

From my research I see that I can pass in the variable like so:

通过我的研究,我发现我可以像这样传递变量:

@Html.EnumDropDownListFor(model => model.RequestType, reqType.ToString(), htmlAttributes: new { @onchange = "YadaYada();" })

But this creates a new list item containing the enum value and not the display name, e.g.

但这会创建一个包含枚举值的新列表项,而不是显示名称。

Tea <-- This should not be created, instead 'Warm Tea' should be selected
Lovely Cold Beer
Warm Tea
Milky Coffee

My entire approach may be wrong as I'm new to MVC, but I'd welcome advice to fix it please! I don't understand why in the controller, using ToString on the enum value creates a different outcome to doing the same in the EnumDropDownListFor method.

我的整个方法可能是错误的,因为我是MVC的新手,但是我欢迎大家的建议来修复它。我不明白为什么在控制器中,在enum值上使用ToString会创建不同的结果,从而在EnumDropDownListFor方法中执行相同的操作。

2 个解决方案

#1


1  

The second parameter (reqType.ToString()) of your EnumDropDownListFor() method is using the overload which adds an optionLabel (an option with a null value used for validation). It does not set the value of the selected option.

您的EnumDropDownListFor()方法的第二个参数(reqType.ToString())使用了添加optionLabel的重载(一个带有null值的选项,用于验证)。它不设置所选选项的值。

Model binding features of MVC work by binding to your property and since the default value of your RequestType is "Beer" , then that option will be selected.

MVC的模型绑定特性通过绑定到您的属性来工作,并且由于您的RequestType的默认值是“Beer”,因此将选择该选项。

You need to set the value of the property in the model before you pass the model to the view, for example (assumes you have a specific route for /Request/{request})

例如,在将模型传递给视图之前,您需要设置模型中属性的值(假设您有针对/Request/{Request}的特定路由)

public ActionResult Request(RequestType request)
{
    var model = new MyModel
    {
        RequestType = request
    };
    return View(model);
}

#2


0  

You must use html extensions. Example,

您必须使用html扩展。的例子,

 public static string GetInputName<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
    {
        if (expression.Body.NodeType == ExpressionType.Call)
        {
            MethodCallExpression methodCallExpression = (MethodCallExpression)expression.Body;
            string name = GetInputName(methodCallExpression);
            return name.Substring(expression.Parameters[0].Name.Length + 1);

        }
        return expression.Body.ToString().Substring(expression.Parameters[0].Name.Length + 1);
    }

    private static string GetInputName(MethodCallExpression expression)
    {
        // p => p.Foo.Bar().Baz.ToString() => p.Foo OR throw...
        MethodCallExpression methodCallExpression = expression.Object as MethodCallExpression;
        if (methodCallExpression != null)
        {
            return GetInputName(methodCallExpression);
        }
        return expression.Object.ToString();
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes) where TModel : class
    {
        string inputName = GetInputName(expression);
        var value = htmlHelper.ViewData.Model == null
            ? default(TProperty)
            : expression.Compile()(htmlHelper.ViewData.Model);

        return htmlHelper.DropDownList(inputName, ToSelectList(typeof(TProperty), value.ToString()), htmlAttributes);
    }

#1


1  

The second parameter (reqType.ToString()) of your EnumDropDownListFor() method is using the overload which adds an optionLabel (an option with a null value used for validation). It does not set the value of the selected option.

您的EnumDropDownListFor()方法的第二个参数(reqType.ToString())使用了添加optionLabel的重载(一个带有null值的选项,用于验证)。它不设置所选选项的值。

Model binding features of MVC work by binding to your property and since the default value of your RequestType is "Beer" , then that option will be selected.

MVC的模型绑定特性通过绑定到您的属性来工作,并且由于您的RequestType的默认值是“Beer”,因此将选择该选项。

You need to set the value of the property in the model before you pass the model to the view, for example (assumes you have a specific route for /Request/{request})

例如,在将模型传递给视图之前,您需要设置模型中属性的值(假设您有针对/Request/{Request}的特定路由)

public ActionResult Request(RequestType request)
{
    var model = new MyModel
    {
        RequestType = request
    };
    return View(model);
}

#2


0  

You must use html extensions. Example,

您必须使用html扩展。的例子,

 public static string GetInputName<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
    {
        if (expression.Body.NodeType == ExpressionType.Call)
        {
            MethodCallExpression methodCallExpression = (MethodCallExpression)expression.Body;
            string name = GetInputName(methodCallExpression);
            return name.Substring(expression.Parameters[0].Name.Length + 1);

        }
        return expression.Body.ToString().Substring(expression.Parameters[0].Name.Length + 1);
    }

    private static string GetInputName(MethodCallExpression expression)
    {
        // p => p.Foo.Bar().Baz.ToString() => p.Foo OR throw...
        MethodCallExpression methodCallExpression = expression.Object as MethodCallExpression;
        if (methodCallExpression != null)
        {
            return GetInputName(methodCallExpression);
        }
        return expression.Object.ToString();
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes) where TModel : class
    {
        string inputName = GetInputName(expression);
        var value = htmlHelper.ViewData.Model == null
            ? default(TProperty)
            : expression.Compile()(htmlHelper.ViewData.Model);

        return htmlHelper.DropDownList(inputName, ToSelectList(typeof(TProperty), value.ToString()), htmlAttributes);
    }