C# Html.EnumDropDownList根据枚举变量的值设置选定的listitem

C# Html.EnumDropDownList根据枚举变量的值设置选定的listitem,c#,asp.net-mvc,asp.net-mvc-5,C#,Asp.net Mvc,Asp.net Mvc 5,这可能是一个重复,所以我已经指出,我从这个网站阅读允许我一些进展 我有一个定义如下的模型: public enum RequestType { [Display(Name = "Lovely Cold Beer")] Beer = 0, [Display(Name = "Warm Tea")] Tea = 1, [Display(Name = "Milky Coffee")] Coffee= 2 } 基于URL,我有一个变量,用于自动选择适当的列

这可能是一个重复,所以我已经指出,我从这个网站阅读允许我一些进展

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

public enum RequestType
{
    [Display(Name = "Lovely Cold Beer")]
    Beer = 0,
    [Display(Name = "Warm Tea")]
    Tea = 1,
    [Display(Name = "Milky Coffee")]
    Coffee= 2
}
基于URL,我有一个变量,用于自动选择适当的列表项,例如

http://example.com/Request/Tea
将在控制器中执行此操作

ViewBag.RequestType = RequestType.Tea.ToString();
return View("Index");
在我看来,我有一个变量可以读回这个值,然后显示相应的内容:

if (ViewBag.RequestType != null)
{
    reqType = Enum.Parse(typeof(RequestType), ViewBag.RequestType);
}
在此视图中,我使用以下命令创建下拉列表:

@Html.EnumDropDownListFor(model => model.RequestType, htmlAttributes: new { @onchange = "YadaYada();" })
这将使用为每个枚举定义的显示名称值呈现列表。我需要的是在呈现页面时自动选择与reqType值匹配的适当列表项

根据我的研究,我可以这样传入变量:

@Html.EnumDropDownListFor(model => model.RequestType, reqType.ToString(), htmlAttributes: new { @onchange = "YadaYada();" })
但这将创建一个新的列表项,其中包含枚举值而不是显示名称,例如

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

我的整个方法可能是错误的,因为我是MVC的新手,但我欢迎您的建议来解决它!我不明白为什么在控制器中,对枚举值使用ToString会产生与在EnumDropDownListFor方法中相同的结果。

您必须使用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);
    }
EnumDropDownListFor方法的第二个参数reqType.ToString使用,它添加了一个optionLabel选项,该选项带有用于验证的空值。它不会设置所选选项的值

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

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


我已经读了大约两个小时的MSDN,看看这样的东西。一个如何在我自己的代码中利用它的例子将是有益的,请…你需要HtmlExtensions,有很多例子。你不需要任何扩展方法。内置的EnumDropDownListFor可以直接完成这一切。您只需要设置属性的值。如果您的模型属性是model.RequestType=RequestType.Tea,那么将选择第二个选项model binding通过绑定到您的属性值来工作,@Html.EnumDropDownListFormodel=>model.RequestType,reqType.ToString,htmlAttributes….中的第二个参数作为旁注。。。。添加一个选项标签-例如,它添加了Tea,用于创建一个空选项,用于验证,通常类似于请选择。这与选择一个选项无关。@StephenMuecke感谢您提供了一些清晰的信息。因为这是一个联系人页面,所以我实际上并没有使用收集数据的HttpPost方法中的模型将模型传递给视图。也许这就是我错的地方?我应该在控制器中实例化一个新模型,设置RequestType属性,然后传递到视图吗?当然。您应该始终将模型传递给视图,即使它只是一个默认实例。我想你不能发布一个我可以接受的答案来帮助其他人,好吗?非常感谢。在我使用你的方法时,我只想问一个简单的问题。。。如果出于某种原因,所选项目需要更改控制器中设置的值,您如何启动所选项目的更改?我习惯于使用webforms,其中所有处理都是在代码隐藏中完成的。或者,所有这些逻辑都应该在控制器中完成,早在传递到视图之前?尽可能在渲染视图之前在控制器中完成,但是,如果需要在视图中完成,例如响应某个客户端事件,那么可以使用javascript/jquery,例如$'RequestType'.val'Tea';太好了,再次感谢你对这个答案的澄清。
public ActionResult Request(RequestType request)
{
    var model = new MyModel
    {
        RequestType = request
    };
    return View(model);
}