问题
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.
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
.
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.
回答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.
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.
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}
)
public ActionResult Request(RequestType request)
{
var model = new MyModel
{
RequestType = request
};
return View(model);
}
回答2:
You must use html extensions. Example,
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);
}
来源:https://stackoverflow.com/questions/35800531/html-enumdropdownlistfor-set-selected-listitem-based-on-enum-variables-value