Problem with ASP.NET MVC DropDownList not displaying selected value - asp.net

I have an aspx page which allows me to edit articles. Among things I can edit is which category the article belongs to. The category is chosen through a DropDownList as shown here,
<%= Html.DropDownList("categoryID", (IEnumerable<SelectListItem>)ViewData["CategoryID"], new { #class = "textbox" }) %>
However, the articles category isn't selected when I go to that page. The ViewData I use for the DropDownList looks like this,
ViewData["CategoryID"] = new SelectList(categories, "CategoryID", "Title", article.CategoryID);
Which should select the article.CategoryID as it's selected value.
Have I done this wrong?

You're assigning the ViewData property a SelectList, but casting it to IEnumerable<SelectListItem> - try typing directly to SelectList instead:
<%= Html.DropDownList("categoryId", (SelectList)ViewData["CategoryID"], new { #class = "textbox" }) %>

The best I could suggest is that you ensure your "Category" class has a property called "CategoryID" and is not just "ID". From what you've given us that's the best guess I can make as to the problem.
If it is just "ID", then your function will need to go:
ViewData["CategoryID"] = new SelectList(categories, "ID", "Title", article.CategoryID);

Related

Date from Model does not display in TextBoxFor

I am using Html.TextBoxFor to set and display dates from Model. They work fine when setting the values, however when I retrieve values from the database, they do not display the dates:
Here is my HTML:
#Html.TextBoxFor(x=>x.effectiveDate, "Select Effective Date", new {#class="date form-control", id= "reqEffectiveDate" })
If I switch to #Html.EditorFor, the dates display, but the element no longer displays like the other "form-control" elements on the page, and clicking in the box no longer displays the datepicker:
EditorFor doesn't apply any CSS classes by default, unless you have defined a custom editor template.
You need to pass a collection of HTML attributes to the editor:
#Html.EditorFor(x => x.effectiveDate, new { htmlAttributes = new { #class = "date form-control", id = "reqEffectiveDate" } })

DropDownListFor binding to the text displayed not the underlying id (razor)

I have a razor (cshtml) file with a dropdownlistfor:
#Html.DropDownListFor(model => model.x_nme, (SelectList) ViewData["Y"]);
The SelectList is formed in the controller as:
var = new SelectList(xList, "id", "x_nme", current.id);
ViewData["Y"] = y_var;
I want the model to bind to the "x_nme" attribute, which displays correctly in the dropdown, but instead it binds to the id attribute.
I need the id attribute as this dropdown fills several fields in the form using javascript/ajax/jquery and I could as an alternative bind to a hidden field to get the name correct.
I was wondering if there is a way to directly bind the model => model.x_nme to the text in the drop-down instead of the underlying id w/o having to have a hidden field.
Thanks in advance.
ViewData["Y"] = new SelectList(xList, "Text", "Text");
Then there is only text on the dropdown, so it will be selected!
This actually works!

Pass 'value' when 'key' is selected - MVC/Dictionary object

I am populating a dictionary object with key value pairs like this..
Dictionary<string, string> twoValues = new Dictionary<string, string>();
foreach (var item in query)
{
twoValues.Add(item.Name, item.Id);
}
return twoValues;
I am returning these value pairs to the controller and populating a MVC model (selectlists)
model.Names = new SelectList(twoValues.Keys);
model.Ids = new SelectList(twoValues.Values);
return model;
In the view I have an action link and a drop down. Drop down is populated with key values of the dictionary (in this case, key is text names, and value is ids)
//Action link
<%=Html.ActionLink("link", "Method", "Controller", new { Id = ?? })%>
//Drop down
<%=Html.DropDownList("names", Model.Names, "")%>
How do I pass the Id associated with the selected Name in drop down to the controller via action link?
I tried having another drop down list next to names with the ids .. but somehow I need to maintain the link between the two drop downs.. since I am separating the dictionary key value pairs in the view for display...
I can have something like...
//Action link
<%=Html.ActionLink("link", "Method", "Controller", new { Id = ?? })%>
//Drop down
<%=Html.DropDownList("names", Model.Names, "")%>
<%=Html.DropDownList("ids", Model.Ids, "")%>
How do I pass the id via the action link for the selected 'Name' drop down list.
You need to do some javascript trick on the click event. Read the selected value of the drop down and build the url and navigate to that.
#Html.ActionLink("Link","Method","Controller",null,new { #class="hackLink"})
<script type="text/javascript">
$(function(){
$(".hackLink").click(function(e){
e.preventDefault(); //Prevent default link click behaviour
var item=$(this);
var selectedVal=$("#names").val();
var newUrl=item.attr("href")+"?id="+selectedVal;
window.location.href=newUrl;
});
});
</script>
Assuming names is the ID of your DropDown.
Alternatively, you can listen to the change event of the Dropdown and then set the value href attribute of the link.
I would recommend creating one dropdown that will have the value of the options equal to your id field and the text equal to your names. You should be able to create it using something this:
Controller:
IEnumerable<SelectListItem> items = yourQueryCode.Select(c => new SelectListItem
{
Value = c.ID.ToString(),
Text = c.Name
});
ViewBag.Names = items;
HTML:
<%= Html.DropDownList("Names", (IEnumerable<SelectListItem>) ViewBag.Names) %>
This will allow you to get the ID linked to the name as the value of the dropdown when you do $('#dropdown').val().
Preferably you would have the SelectList as part of your model that you return to the view, but the above will work as well. There will only have to be a few minor changes when you switch to returning via the model and the transition is pretty simple. Hopefully this is enough to get you headed in the right direction.

My dropdownlist is not selecting an item as expected (MVC 1)

OK so I have 2 pages where this kind of behaviour is implemented. It works on one but doesn't work in another and I have no idea why. Despite the data containing a list of selectitems and one of them is selected the dropdown list is not displaying this selection (ie. it resets to the blank item).
I don't know how to further debug this.
In my page:
<%= Html.DropDownList("CampusId", ViewData.Model.Campuses, new { #class = "large search_box" })%>
In my controller.
Campuses = AdminRepository
.ListAll<Campus>(a => a.Description)
.ToSelectListItem<Campus>(a => a.CampusId, a => a.Description, criteria.CampusId, true);
I can see that campuses does have the correct list item marked as selected - so why when it is displayed on the page is it no longer marked as selected?! I can't see anything else obviously modifying the list.
Thanks :)
OK so in trying different google search terms I came across this:
ASP.NET MVC Html.DropDownList SelectedValue
The issue was my drop down list had the same name as in the model. So I changed my html to be
<%= Html.DropDownList("CampusIdDD", ViewData.Model.Campuses, new { #class = "large search_box" })%>
So problem solved!!! Hopefully we'll be able to upgrade from MVC 1 !!
Model.Campuses
Model.CampusId
<%= Html.Hidden("CampusId") %>
<%= Html.DropDownList("CampusId", ViewData.Model.Campuses, new { #class = "large search_box" })%>

How to bind Lists of a custom view model to a dropDownList an get the selected value after POST in ASP.NET MVC?

I have following problem. In my view model I defined some list properties as follows:
public class BasketAndOrderSearchCriteriaViewModel
{
List<KeyValuePair> currencies;
public ICollection<KeyValuePair> Currencies
{
get
{
if (this.currencies == null)
this.currencies = new List<KeyValuePair>();
return this.currencies;
}
}
List<KeyValuePair> deliverMethods;
public ICollection<KeyValuePair> DeliveryMethods
{
get
{
if (this.deliverMethods == null)
this.deliverMethods = new List<KeyValuePair>();
return this.deliverMethods;
}
}
}
This view model is embedded in another view model:
public class BasketAndOrderSearchViewModel
{
public BasketAndOrderSearchCriteriaViewModel Criteria
{
[System.Diagnostics.DebuggerStepThrough]
get { return this.criteria; }
}
}
I use 2 action methods; one is for the GET and the other for POST:
[HttpGet]
public ActionResult Search(BasketAndOrderSearchViewModel model){...}
[HttpPost]
public ActionResult SubmitSearch(BasketAndOrderSearchViewModel model){...}
In the view I implement the whole view model by using the EditorFor-Html Helper which does not want to automatically display DropDownLists for List properties!
1. Question: How can you let EditorFor display DropDownLists?
Since I could not figure out how to display DropDownLists by using EditorFor, I used the DropDownList Html helper and filled it through the view model as follows:
public IEnumerable<SelectListItem> DeliveryMethodAsSelectListItem()
{
List<SelectListItem> list = new List<SelectListItem>();
list.Add(new SelectListItem()
{
Selected = true,
Text = "<Choose Delivery method>",
Value = "0"
});
foreach (var item in this.DeliveryMethods)
{
list.Add(new SelectListItem()
{
Selected = false,
Text = item.Value,
Value = item.Key
});
}
return list;
}
My 2. question: As you can see I pass my view model to the action metho with POST attribute! Is there a way to get the selected value of a DropDownList get binded to the passed view model? At the moment all the DropDownList are empty and the selected value can only be fetched by the Request.Form which I definitely want to avoid!
I would greatly appreciate some ideas or tips on this!
For those like me that got to this post these days I'd recommend you to fully download the tutorial from http://www.asp.net/mvc/tutorials/mvc-music-store-part-1 which covers this and most of the common techniques related with .NET MVC applications.
Anyway Really usefull your post and answers man (If I could vote you I would :)
Let's try to take on this one:
Answer to Question 1: How can you let EditorFor display DropDownLists?
When you call Html.EditorFor() you can pass extra ViewData values to the EdiorTemplate View:
<%: Html.EditorFor(model => Model.Criteria, new { DeliveryMethods = Model.DeliveryMethods, Currencies = Model.Currencies}) %>
Now you have ViewData["DeliveryMethods"] and ViewData["Currencies"] initialized and available inside your EditorTemplate.
In your EditorTemplate you somehow need to call and convert those entries into DropDowns / SelectLists.
Assuming you've got an ascx file of type System.Web.Mvc.ViewUserControl<BasketAndOrderSearchCriteriaViewModel> you could do the following:
<%: Html.LabelFor(model => model.DeliveryMethods) %>
<%: Html.DropDownList("SelectedDeliveryMethod", new SelectList(ViewData["DeliveryMethods"] as IEnumerable, "SelectedDeliveryMethod", "Key", "value", Model.SelectedDeliveryMethod)) %>
Same goes for the Currencies.
<%: Html.LabelFor(model => model.Currencies) %>
<%: Html.DropDownList("SelectedCurrency", new SelectList(ViewData["Currencies"] as IEnumerable, "SelectedDeliveryMethod", "Key", "value", Model.SelectedCurrency)) %>
This setup will make your DeliveryMethodAsSelectListItem() obsolete and you can use any kind of list. Means you are not bound to KeyValuePairs. You'll just need to adjust your call on Html.DropDownList() from now on.
As you can see, I have introduced some new properties to your BasketAndOrderSearchCriteriaViewModel:
Model.SelectedDeliveryMethod
Model.SelectedCurrency
They are used to store the currently selected value.
Answer to Question 2: Is there a way to get the selected value of a DropDownList get binded to the passed view model?
In the EditorFor template we are passing the newly created Model.SelectedDeliveryMethod and Model.SelectedCurrency properties as the SelectedValue Parameter (See 4th Overload of the DropDownList Extension Method).
Now that we have the View doing it's job: How can we get the currently selected value inside the POST Action?
This is really easy now:
[HttpPost]
public ActionResult SubmitSearch(BasketAndOrderSearchViewModel model)
{
...
var selectedDeliveryMethod = model.Criteria.SelectedDeliveryMethod;
var selectedCurrency model.Criteria.SelectedDeliveryMethod;
...
}
Note: I don't have an IDE to test it right now, but it should do the trick or at least show you in which direction to go.

Resources