Let's say my database has a reference table that maps the values Zebra, Goat, and Dog onto the keys 0, 1, and 2, and a DropDownList where a user can select one of these values.
#Html.DropDownListFor(
m => m.Animal,
new SelectList(
new List<Object>{
new {value = 0, text = "Zebra"},
new {value = 1, text = "Goat"},
new {value = 2, text = "Dog"}
},
"value",
"text"
),
new { #class = "form-control" }
)
After the user's selection is saved to the database, I'm trying to figure out a way to display the value for m => m.Animal. It's saved as a 2, but I want the displayed text to read Dog. How do I set the default selected value on the #Html.DropFownListFor equal to the user's selection (e.g. 2), so the selected item displays the text Dog?
I'm seeing two possible meanings to your question, so I guess I'll just cover them both.
If you're talking about making the drop down show the proper selected value, Razor should take care of this for you. However, the fact that you're defining the actual SelectList object, without specifying the selectedValue param, may be getting in the way. Technically DropDownListFor only needs IEnumerable<SelectListItem>, not an actual SelectList, and it's usually better to pass it the former as it's both easier and less prone to error:
#Html.DropDownListFor(
m => m.Animal,
new List<SelectListItem> {
new SelectListItem { Value = "0", Text = "Zebra" },
new SelectListItem { Value = "1", Text = "Goat" },
new SelectListItem { Value = "2", Text = "Dog" }
},
new { #class = "form-control" }
)
If, however, you're talking about how to translate the value 2 into Dog at some later point in your code, then you should actually employ something like an enum. For example:
public enum Animals
{
Zebra = 0,
Goat = 1,
Dog = 2
}
Then, change your Animal property to be of this type:
public Animals Animal { get; set; }
Finally, and since you're running MVC5, you can just use:
#Html.EnumDropDownListFor(m => m.Animal, new { #class = "form-control" })
You don't even need to pass a list of options because the helper will just get them from the enum the Animal property is typed to.
Then, when you want to display the selected animal type, you just use:
#Html.DisplayFor(m => m.Animal)
And Dog or whatever it's set to will be output automatically.
Related
This question already has answers here:
Can the ViewBag name be the same as the Model property name in a DropDownList?
(2 answers)
Closed 5 years ago.
I have a drop down list on my view that for some reason doesn't display the selected value no matter what I've been trying, although I can use it to choose values and update the database with them with no problem.
VIEW
So on the view I have the following code to display the field
#Html.DropDownListFor(model => model.FormType, ViewBag.FormType as SelectList, new { #class = "form-control" })
The "ViewBag.FormType" is created in the controller from a SelectList object that i'm then passing in using a viewbag object.
CONTROLLER
I'm using some code to generate the selectlist and then choose the selected value from the value in the database for that record. It's here where i'm thinking that the problem is
short FormType = 0;
if (account?.FormType != null)
{
FormType = (short)account.FormType;
}
var FormTypeList = new SelectList(
new List<object>
{
new {value = "0", text = "Please Select..."},
new {value = "1", text = "Full"},
new {value = "2", text = "Short"}
}, "value", "text", FormType);
ViewBag.FormType = FormTypeList;
At first I thought that the problem was that the value in the database was a numerical value and the "value" in the selectlist was a text, so i've tried switching them both from one to the other and it's not helped. In the example that i'm working with the value in the database is 2.
I'm very lost to what the problem could be so any help would be appreciated.
#Html.DropDownList("FormType", null, "Select", htmlAttributes: new { #class = "form-control" })
I am trying to use Html.DropDownListFor with the list of strings from a ViewBag.
Basically I got a ViewBag with a list of string like "Adam","Tom","Mike" etc...
I was wandering if it is possible to pass this list in to DropDownListFor where both Value and text are the items from my list.
I wasn't able to use foreach here...
example with hardcode:
#Html.DropDownListFor(model => model.Name, new SelectList(
new List<Object>{
new { value = "Adam" , text = "Adam" },
new { value = "Tom" , text = "Tom" },
new { value = "Mike" , text = "Mike" },
new { value = "Jake" , text = "Jake" },
},
"value",
"text",
2))
You can generate a collection of SelectListItems from the list of strings and use that with DropDownListFor helper method.
var names = new List<string> {"Adam", "Sam"};
ViewBag.Names = names.Select(f => new SelectListItem() {Value = f, Text = f});
and in the view
#Html.DropDownListFor(f=>f.Name, ViewBag.Names as IEnumerable<SelectListItem>,
"select one")
I'm having problems trying to get a preselected value to work.
I've tried to include Selected in the SelectListItem but it doesn't pre-select.
Any clues as to why it's not matching up? Thanks for any help.
RetailerId is int. (it's not defined as enumerable)
Retailer is an enum, for example:
public enum Retailer
{
Sears = 10,
Macys = 20
}
Here is the View code :
#Html.DropDownListFor(x => x.RetailerId,
Enum.GetValues(typeof(Retailer)).Cast<Retailer>()
.OrderBy(o => o.GetDescription())
.Select(o => new SelectListItem() { Text = o.GetDescription(), Value = o.ToString(), Selected = (o.ToInt() == Model.RetailerId) }),
new { #data_placeholder = "Select Retailer", #class = "form-control" })
Your generating a collection of SelectListItem where the Value is either "Sears" or "Macys" which cannot be bound to property RetailerId which is an int.
Note that the Selected property of SelectListItem is ignored when binding to a model property. Internally the method sets the Selected property based on the value of the property your binding to, and since its an int, it does not match any of your options values and the first option is selected because something has to be.
You can make this work by modifying the .Select clause to
.Select(o => new SelectListItem() { Text = o.GetDescription(), Value = ((int)o).ToString() }),
Alternatively, change the model property to
public Retailer RetailerId { get; set; }
an the .Select clause to
.Select(o => new SelectListItem() { Text = o.GetDescription(), Value = o.ToString() }),
I'm having trouble assigning the selected value to a select list (that is in a table) from a DB.
The value is defaulting to the first option even when a value is passed to it and it definitely passing from my controller to the view.
I have also tried a different select list that passes the value correctly on my form, and that select list also doesn't work. So I'm pretty sure it has something to do with the table
Here is a screenshot of the value passing.
Select List
public IEnumerable<SelectListItem> ListViewStatusOptions
{
get
{
return new[]
{
new SelectListItem { Value = "Scheduled", Text = "Scheduled" },
new SelectListItem { Value = "OFR-Out for Revision", Text = "OFR-Out for Revision" },
new SelectListItem { Value = "Tool Work Required", Text = "Tool Work Required" },
new SelectListItem { Value = "Delayed", Text = "Delayed" },
new SelectListItem { Value = "In Press", Text = "In Press" },
};
}
}
Select List in Table
#foreach (var item in Model) {
<td>
#Html.DropDownListFor(modelItem => item.ListViewStatus, item.ListViewStatusOptions, "Select", new { #id = #Html.ValueFor(modelItem => item.Id )})
</td>
}
You need to use a SelectList object new an array of SelectListItems.
Add this property to your method
public IEnumerable<SelectListItem> StatusOptions
{
get { return new SelectList(ListViewStatusOptions, "Value", "Name"); }
}
"Value" is the name of the property that contains the id of each item. You can have a list of any type of object not just SelectListItems. This is why is may seem unnecessary to pass "Value", Similarly, "Name" is the property that contains what to show the user.
Then change your razor code to
#foreach (var item in Model) {
<td>
#Html.DropDownListFor(modelItem => item.ListViewStatus, item.StatusOptions, "Select", new { #id = #Html.ValueFor(modelItem => item.Id )})
</td>
}
the proper binding for a list of values will be:
for (int i = 0; i < Model.Count; i++)
{
#Html.DropDownListFor(modelItem => modelItem[i].ListViewStatus, new SelectList(Model[i].ListViewStatusOptions, "Value", "Text", Model[i].ListViewStatus))
}
you have to use for loop instead of for-each because mvc will not generate proper input names if foreach is used and the posted data will be not resolved by action methods
My updated Razor Code.
As #ScottMacMaster explains,
You need to use a SelectList object new an array of SelectListItems.
"Value" is the name of the property that contains the id of each item.
You can have a list of any type of object not just SelectListItems.
This is why is may seem unnecessary to pass "Value", Similarly, "Name"
is the property that contains what to show the user.
I was receiving an error for Name so i changed it to Text
I then assign item.ListViewStatus as the object selected value
#Html.DropDownListFor(modelItem => item.ListViewStatus,
new SelectList(item.ListViewStatusOptions, "Value", "Text",item.ListViewStatus), "Select",
new { #id = #Html.ValueFor(modelItem => item.Id )})
I have an enum, which is a mapping for a description of a property against an index in the database. I have a property on my ViewModel that represents an instance of that enum. I've tried both returning a list of enum instances, which means I do this:
#Html.DropDownListFor(m => m.CurrentFilter,
Model.FilterTypes.Select(entry =>
new SelectListItem{ Text = entry.ToString(), Value = ((int)entry).ToString()}),
new { #class = "normalcell", style = "WIDTH: 132px;" })
and returning a list of SelectListItems, which means I do this:
#Html.DropDownListFor(m => m.CurrentFilter,
Model.FilterTypes.Select(entry =>
new SelectListItem{ Text = entry.Text, Value = entry.Value, Selected = entry.Selected}),
new { #class = "normalcell", style = "WIDTH: 132px;" })
In the second case, when I debug, I am certain that the Selected property on the entry object is true for the correct item. In both cases, there is no 'selected' attribute written in to my HTML and so the correct item is not selected. I've also set a breakpoint, and CurrentFilter DOES have the correct value and the rest of my page renders appropriately, so it's finding the value.
I've written plenty of drop lists that work, using similar code, I can't for the life of me see why this does not work, no matter how I try to do it ?
I have also tried:
#Html.DropDownListFor(m => m.CurrentFilter,
Model.FilterTypes,
new { #class = "normalcell", style = "WIDTH: 132px;" })
which seems to me to be the logical way to do it ( return a list of SelectListItems and just do no processing in the page ), but the Selected property is still ignored.
Update:
I tried to do it this way:
#Html.DropDownList("CurrentFilter", Model.FilterTypes, new { #class = "normalcell", style = "WIDTH: 132px;" })
and just read the value out of the request. It's still the case that I am returning a list with only one item that has Selected == true, and it's still the case that MVC is ignoring it.
This works, not surprisingly, but I'd love to know why all the other things don't.
<select class="normalcell" id="CurrentFilter" name="CurrentFilter" style="WIDTH: 132px;">
#foreach (SelectListItem item in Model.FilterTypes)
{
if (item.Selected)
{
<option value="#item.Value" selected="selected">#item.Text</option>
}
else
{
<option value="#item.Value">#item.Text</option>
}
}
I believe the reason is that the MVC binding engine doesn't know how to deal with Enum values. I think you need to create a "proxy" property for your view model. Something like this...
public enum MyEnum { a, b, c, d };
public MyEnum EnumVal { get; private set; }
public string EnumProxy
{
get { return EnumVal.ToString(); }
set { EnumVal = (MyEnum)Enum.Parse(typeof(MyEnum), value); }
}
Then construct the drop-down list using the Enum names:
Type t = typeof(MyEnum);
var ddList = Enum.GetNames(t).Select(
item => new SelectListItem() { Text = item, Value = item }
).ToArray();
Now you should be able to use DropDownListFor normally:
#Html.DropDownListFor(model => model.EnumProxy, ddList)
I'm not sure if there's a neater solution. This one should work though.
My DDL tutorial shows how to use enums. See See my tutorial Working with the DropDownList Box and jQuery and My blog Cascading DropDownList in ASP.Net MVC Part 2 of the tutorial explains: When the string argument (the property to bind) and the SelectList object have the same name, the selected value is not used.
Darin has a SO post on another common reason the selected value is not display. See MVC DropDownList SelectedValue not displaying correctly