I'm new to MVC and C#. I'm trying to get a static list to work with a DropDownList control such that the selected value rendered is set by the current Model value from the DB.
In the controller, I have:
ViewData["GenderList"] = new SelectList(new[] { "Female", "Male", "Unknown" }, donor.Gender);
In the view:
Gender:<%=Html.DropDownList("Gender", (IEnumerable<SelectListItem>)ViewData["GenderList"]) %>
In the debugger, donor.Gender is "Male", but "Female" gets rendered in the view.
I've read a number of posts related to select, but I've not found one that applies to a static list (e.g., where there's no "value" and "name" to play with). I'm probably doing something stupid...
This may sound like a stupid question but is donor.Gender a string value, and does it match case with the hard-coded values you've used EG 'Male'?
The reason I ask is because this;
ViewData["GenderList"] = new SelectList(new[] { "Female", "Male", "Unknown" }, "Male");
works a treat, but this;
ViewData["GenderList"] = new SelectList(new[] { "Female", "Male", "Unknown" }, "male");
returns your result
Thanks to Si, here's the final solution I came up with:
In the controller, this:
ViewData["GenderList"] = repo.GetGenders(donor.Gender);
In the DonorRepository, this:
public SelectList GetGenders(string selected) {
SelectList genders = new SelectList(new[] { "Female ", "Male ", "Unknown" }, (selected == null ? null : selected.ToString().PadRight(7).ToCharArray()));
return (genders);
}
Then in the View, just this:
<%= Html.DropDownList("Gender", (IEnumerable<SelectListItem>)ViewData["GenderList"], "--Select--")%>
NOTE: PadRight(7) equals the Donor.Gender DB specification of Char(7). Also note the SelectList constant space padding of "1234567" for each selectlistitem.
Related
I have found plenty of posts about this, but none of them are solving my issue. My code right now:
#Html.ListBox("SelectedNewsletter", Model.Newsletters)
and
public MultiSelectList Newsletters
{
get
{
return new MultiSelectList(
new[]
{
// TODO: Fetch from your repository
new { Id = 1, Name = "item 1" },
new { Id = 2, Name = "item 2" },
new { Id = 3, Name = "item 3" },
},
"Id",
"Name"
);
// return new MultiSelectList(PromoNewsletter.All, "IdString", "Display");
}
}
As far as I can see, it's all hard coded now, and it still gives the same error. I want to do a ListboxFor, but I am trying to just get a listbox to work. I have replaced my int id with a string representation, based on advice I found elsewhere, but now I don't see what else I can do. It just plain is not working, even with all hard coded values and not binding to a property on my ViewModel. Where am I going wrong ?
The error is occurring because you have a property in the Model or ViewData/ViewBag with the name SelectedNewsletter.
Give a different name for the ListBox if you can't rename that property.
UPDATE:
After little more experimenting I figured out that the problem is you may be setting an integer value to the SelectedNewsletter that is somewhere in the ViewData/ViewBag or Model.
You can set the values that has to be selected in the ListBox as a string or array of strings to the SelectedNewsletter.
i.e SelectedNewsletter = "1";
or
SelectedNewsletter = new[] { "1", "3" };
You can also use strongly typed helper to make things easy,
#Html.ListBoxFor(m => m.SelectedNewsletter, Model.NewsLetters);
I have a list of type stored procedure which have an ID and a Name as data in it.
i have property of int type in model and a list of same stored procedure.
now i want to bind this information into ListBoxFor
in view i have written this
#Html.ListBoxFor(x => x.HobbyId, new MultiSelectList(Model.listHobby, "pkHobbyId", "Hobby"))
but i am getting an error
The parameter 'expression' must evaluate to an IEnumerable when multiple selection is allowed.
Please Help how to bind.
try that
#Html.ListBoxFor(x => x.HobbyId, Model.listHobby.Select(f => new SelectListItem { Text = f.Hobby, Value = f.pkHobbyId.ToString() }), new { Multiple = "multiple" })
listHobby is iEnumerable list on my sample
sorry if i mislead you, rushed to answer but you cannot get the result of the multiselect listbox into a guid or int variable (whatever type is your HoobyId is) you should have an array to grab the result like
public string[] SelectedHobbyIds { get; set; }
so there must be something wrong with your View Models so its better that u would post your view models to be checked
# Chhatrapati Sharma,
In your controller, try this,
ViewData['anyName'] = new SelectList {
Text = , // text from ur function
Value = , // Value from function
Selected = // if required
}
and in view, bind the viewdata like,
<#Html.ListBox("docImages", ((IEnumerable<SelectListItem>)ViewData["anyName"]))
For testing, try a sample selectlist item as follows,
ViewData['anyName'] = new List<SelectListItem>{
new SelectListItem {Text = "First", Value = "0"},
new SelectListItem {Text = "Second"), Value = "1"},
new SelectListItem {Text = "Third", Value = "2"}
};
If this sample works, then check your function "_supp.listDocImages()" and make sure it return IList
#Html.ListBoxFor(x => x.HobbyId, Model.listHobby.Select(f => new SelectListItem { Text = f.Hobby, Value = f.pkHobbyId.ToString() }), new { Multiple = "multiple" })
HobbyId in expression must be ienumerable because you set multi select
I am quite new to MVC3, and developing a DropDownListFor which i need to get both value and text for display result purpose. Any ideas on this issue? Thanks!
In my controller:
ViewBag.vehicleSizes = totalGreenCalculator.GreenCalculator.getVehicleFuelEfficiency();
In my Model:
//Datatype: fuelEfficiency = double, vehicleSizes = string
public IEnumerable<SelectListItem> getVehicleFuelEfficiency()
{
var size = new[] {new vehicleSize {fuelEfficiency = 0.0, vehicleSizes = "Choose your vehicle size"},
//and so on
};
return size.Select(a => new SelectListItem() { Text = a.vehicleSizes, Value = a.fuelEfficiency.ToString() });
}
View:
#Html.DropDownListFor(model => model.GreenCalculator.vehicleList[i].fuelEfficiency, (IEnumerable<SelectListItem>)ViewBag.vehicleSizes)
You can recieve IDictionary on controller. Dropdownlist name must match the name of the dictionary.
Your code looks fine. It will generate the dropdownlist from the given values. But it won't preselect the default option. That's because in the first argument you have used a complex expression. If you wanted to preselect some item you could do this:
#Html.DropDownListFor(
x => x.GreenCalculator.vehicleList[i].fuelEfficiency,
new SelectList(
(IEnumerable<SelectListItem>)ViewBag.vehicleSizes,
"Value",
"Text",
Model.GreenCalculator.vehicleList[i].fuelEfficiency
)
)
I have a C#.Net MVC3 web app. I am using Drop Down lists all over the place and having success. However, there are two that I am having trouble with. The only difference is that I am creating the SelectLists on the fly in the code rather than using Lookup tables. I use lookup tables for all the other Drop Downs. When I QuickWatch the SelectLists in the code, the correct Item has the Selected property value set to true. However, when the page loads, the item with the Selected property is not displayed. The first item is. Any ideas? This is one of those werid ones. I've tried both ways below. In both cases, the ViewBag.DateToYear and the SelectList DateToYear have the right values and 'Selected' properties set
1)
//Controller
IList<string> dateToYear = new List<string>();
for (int i = 0; i < numberYears; i++)
{
dateToYear.Add(DateTime.Now.AddYears(i).Year.ToString());
}
ViewBag.DateToYear = new SelectList(dateToYear,"2014")
//View
#Html.DropDownList("DateFromYear", (SelectList)ViewBag.DateToYear )
2)
//Controller
SAME as above
//View
List<SelectListItem> DateToYear = new List<SelectListItem>();
foreach (var m in ViewBag.DateToYear)
{
DateToYear.Add(new SelectListItem { Selected = #m.Selected, Value = #m.Text, Text = #m.Text });
}
#Html.DropDownList("DateFromYear", DateToYear)
The problem is, SelectList works as designed. The bug is in the design. You may set the Selected Property in SelctedItem, but this will completely be ignored, if you traverse the list with the GetEnumerator() ( or if Mvc does that for you). Mvc will create new SelectfListItems instead.
You have to use the SelectList ctor with the SelectListItem[], the Text-Name, the Value-Name and the SelectedValue. Be aware to pass as SelectedValue the VALUE of SelectListItem, which you want to be selected, not the SelectListItem itself! Example:
Why not just do in the controller ?
Pseudo code :
//controller
ViewBag.DateToYear = new SelectList(new[]
{
new SelectListItem { Text = "10", Value = "10" },
new SelectListItem { Text = "15", Value = "15" }
new SelectListItem { Text = "25", Value = "25" },
new SelectListItem { Text = "50", Value = "50" },
new SelectListItem { Text = "100", Value = "100" },
new SelectListItem { Text = "1000", Value = "1000" },
}, "SomeText", "Value", "15");
The second option should be selected.
Not sure if this is the case, but I had some problem with dropdownboxes not getting selected a few days ago.
My problem was: I have a #model.Options and I created a #html.dropdownlist("Options", #model.Options, [...]). However, because they had the same name it somehow conflicted. When I used #html.dropdownlist("anythingElse", #model.Options, [...]) it worked fine.
When I QuickWatched return View(model) the selected options seemed to be set correct too, so it took a while to figure that out. Maybe you have the same problem?
Same thing was happening to me too, make sure you do not give same ID as the property name you gave on your Model. That is how I solved this issue...
So I got this crazy idea I could make make something cool work. I got tired of new selectlist(item, "blah", "blahblah") so I started writing an extension method (trying to get it more strongly typed) something like this ...
var selectList = projects.ToSelectList(p =>p.ProjectID, p =>p.ProjectName);
the extension method goes a little like this
public static SelectList ToSelectList<T>(this IEnumerable<T> item,
Expression<Func<T, string>> textName,
Expression<Func<T, string>> valueProperty)
{
//do cool stuff
return new SelectList(items, dataTextField, dataValueField);
}
What I need to get to is the reflection properties so I can grab the value and grab the name. Any ideas onhow I can do that? Any thoughts on doing this more better/easier? I've done this before but for the life of me I can't remember how I did it.
Edit this needed some clarification. I copied some code that was in-flight and not refined, so I've updated that code to reflect the more correct criteria.
I don't see why you have to use Reflection to do this.
public static SelectList ToSelectListItem<T>(this IEnumerable<T> items,
Func<T, string> textName, Func<T, string> valueProperty) {
{
return new SelectList(items
.Select(i => new SelectListItem {Text = textName(i), Value = valueProperty(i)}));
}
}
should would work, but I don't have the MVC dll on the current machine.
I originally tried your idea as well when I started with MVC but then I realized that some fields I wanted to format in a certain way and what about when an item is supposed to be selected by default. After handling all of that I realized it would be clearer to just write a one line LAMDA expression.
So now I usually just do a LAMDA expression to generate my SelectListItem collection.
<b>Screener: </b><%= Html.DropDownList("ScreenerOI", Model.Screeners.Select(p=>new SelectListItem() { Text = p.firstName + " " + p.lastName, Value = p.OI.ToString() })) %>
<b>Open Time: </b>
<%= Html.DropDownListFor(c => c.OpenTime, Model.HoursInDay.Select(p => new SelectListItem() { Text = p != null ? DateTime.Now.Date.Add(p.Value).ToString("h:mm tt") : "Clear Time", Value = p != null ? p.ToString() : "", Selected = Model.OpenTime == p }).ToList())%>
It seems like this is just as clear as to what is going on as what your idea is.
Another Example
<b>Screener Status: </b>
<%= Html.DropDownListFor(c => c.InfoStatusOI, Model.InfoStatuses.Select(p => new SelectListItem() { Text = p != null ? p.Status.ToString() : "", Value = p != null ? p.OI.ToString() : "", Selected = p != null && Model.InfoStatusOI == p.OI }).ToList())%>
This needs cleaned and tested for things like a zero count of the items, but here's the end result.
public static SelectList ToSelectList<T>(this IEnumerable<T> items, Expression<Func<T, object >> textName, Expression<Func<T, object >> valueProperty)
{
var dataTextField = textName.Body.ToString().Split('.')[1];
var dataValueField = valueProperty.Body.ToString().Split('.')[1];
return new SelectList(items, dataTextField, dataValueField);
}