SelectList doesn't show the selected item - asp.net-mvc-3

This is pared down a bit, but essentially I've got a model that looks something like this:
public class PersonCreateEditViewModel
{
public string Title { get; set; }
public IEnumerable<SelectListItem> Titles { get; set; }
}
and on my edit page I want to display the person's current title in a DropDownList so we can change their title. That code looks like this:
#Html.DropDownListFor(model => model.Title, new SelectList(Model.Titles, "Value", "Text", Model.Title))
and I populate it in my action like so by retrieving a bunch of strings:
IEnumerable<SelectList> titles = somelistoftitles.Select(
c => new SelectListItem
{
Value = c,
Text = c
};
var viewModel = new PersonCreateEditViewModel()
{
Title = model.Title,
Titles = sometitles
};
return View(viewModel);
and this populates the DropDownList with the values but does not select the person's current title. So, I'm obviously doing something wrong here. Looking at the underlying html, I see that the selected attribute is not set for the option corresponding to the person's Title. I thought that specifying Model.Title there as the third argument would select it.
Ideas?
Update
I added the setting of the Selected property as qntmfred suggested below, and that'll set the right one in the list to true but the <option> doesn't have the selected attribute on it.
SOLVED
So, this was subtle. I just so happened to have a ViewBag entry named "Title" - something like this:
#{
ViewBag.Title = "Edit Person"
}
and this evidently caused the selection to not work since my model has a "Title" property as well. I solved the problem by renaming the property.

SOLVED
As I wrote at the end of my question, this wasn't an obvious thing. I just so happened to have a ViewBag entry named "Title" - something like this:
#{
ViewBag.Title = "Edit Person"
}
and this evidently caused the selection to not work since my model has a "Title" property as well. I solved the problem by renaming the property.
Way too much time wasted on this problem this morning.
Lesson learned.

You need to set the Selected property on your SelectListItem
IEnumerable<SelectList> titles = somelistoftitles.Select(
c => new SelectListItem
{
Value = c,
Text = c,
Selected = (c.Equals(model.Title))
};

Related

Loop through IEnumerable in #Html.DropDownListFor (MVC3)

I have a collection of models that I am passing to my view and I want to display each model.property in the dropdownlist. The problem is there is a bug in my code where it shows two duplicate items.
#model IEnumerable<UserManager.Models.vw_UserManager_Model>
#Html.Label("BRAD Module:")&nbsp
#Html.DropDownListFor(model => model.FirstOrDefault().module_name, Model.Select(x => new SelectListItem { Text = x.module_name, Value = x.module_name }), new { id = "ddlSelectedBrad", onchange = "chkSelection()" })
I am currently using FirstOrDefault() to access the module name for each model in my collection of models. But by doing this I have a duplicate value.
See screenshots below:
MARKET:LEISURE is showing twice
Intelligence is showing twice. If I change this dropdown value and return to this screen it will show two duplicate values.
Summary
Does anyone know a better way of writing the LINQ query?
Thanks.
Instead of
Model.Select(x => new SelectListItem { Text = x.module_name, Value = x.module_name })
Try
Model.GroupBy(x => x.module_name).Select(x => new SelectListItem { Text = x.First().module_name, Value = x.First().module_name })
This should filter the duplicate records.

asp mvc 3 multiselect listbox. map each selected option to collection element

For example we have a view model with fields:
public List<string> SelectedTestItems { get; set; }
public List<SelectListItem> AllTestItems { get; set; }
and view with:
#Html.ListBoxFor(x=>x.SelectedTestItems, Model.AllTestItems)
And now when i open the view, select 3 items in listbox and submit the form(via jquery $.post and $.serialize ), for some reason in controller I get view model with one item in SelectedTestItems collection, and this item is comma separated values that i selected in listbox (SelectedTestItems[0] = "1,2,3")
is it possible to map listbox to something like this:
SelectedTestItems[0] = "1",
SelectedTestItems[1] = "2",
SelectedTestItems[2] = "3" ?
Thank You !
I had tested here and I received each value separated. Can you show all your code? Maybe we can see what is wrong.

ViewBag oddity in creating a MultiSelectList

I have spent a lot of time scouring the various forums for help on MultiSelectLists in asp.net MVC3. Finally figured out how to solve my issue now I'm trying to cut down on my code and I've come across something weird with ViewBags. First the code, than I'll explain the behavior.
My function that creates the MultiSelectList to used by the Controller
public MultiSelectList GetPermissionList(string[] selectedValues)
{
List<SelectListItem> permissions = new List<SelectListItem>()
{
new SelectListItem{ Value = "", Text = "None"},
new SelectListItem{ Value = "View", Text = "View"},
new SelectListItem{ Value = "Add", Text = "Add"},
new SelectListItem{ Value = "Edit", Text = "Edit"},
new SelectListItem{ Value = "Delete", Text = "Delete"}
};
return new MultiSelectList(permissions, "Value", "Text", selectedValues);
}
partial code from the edit action from the controller
public ActionResult Edit(int id)
{
ViewBag.Title = "Edit a Security Role";
SecurityRoles securityroles = Repository.Details(id);
ViewBag.Orders = securityroles.Orders.Split(',');
ViewBag.OrdersListBox = GetPermissionList(ViewBag.Orders);
return View(securityroles);
}
partial code from the View
<td class="rightAlign topAlign editor-label">
#Html.MyLabel(m => m.Orders, "lblOrders")
</td>
<td class="editor-field">
#Html.ListBoxFor(m => m.Orders, ViewBag.OrdersListBox as MultiSelectList, new { size = "5" })
</td>
Keep in mind I've cut out a large chunk of code from the edit Action, I have roughly 9 list boxes I'm creating for this security role manager.
My goal, in the edit action is to simply have 1 line of code, calling the GetPermissionList and having it return to the viewbag so I can just display that in the view, as opposed to the 2 lines per listbox that I currently have.
Just looking at the code, it seems obvious if I were to make the call this way:
ViewBag.OrdersListBox = GetPermissionList(securityroles.Orders.Split(','));
It should work, but the selected values do not come through. To compound the oddity, here is something else I tried and it worked fine, but it makes no sense why.
ViewBag.Orders = securityroles.Orders.Split(',');
ViewBag.OrdersListBox = GetPermissionList(securityroles.Orders.Split(','));
ViewBag.Orders plays no role in the ViewBag.OrdersListBox nor is it used in the view, but when I simply assign it a value than the 2nd line of code works.
Does this make sense to anyone? Any suggestions on how to create a way for the GetPermissionList to simply work correctly by sending it a string array instead of passing it the ViewBag object?
I think, You have to set Orders because that is what the selected values are being bound to when the selection happens. You could just pass a string[] if you didn't want to have anything preselected. Check out Darin's answer in this post. He is using a model but i think the same concept applies to view bag.
Multiselect with ViewModel

dropdownlist set selected value in MVC3 Razor

Here is my model:
public class NewsCategoriesModel {
public int NewsCategoriesID { get; set; }
public string NewsCategoriesName { get; set; }
}
My controller:
public ActionResult NewsEdit(int ID, dms_New dsn) {
dsn = (from a in dc.dms_News where a.NewsID == ID select a).FirstOrDefault();
var categories = (from b in dc.dms_NewsCategories select b).ToList();
var selectedValue = dsn.NewsCategoriesID;
SelectList ListCategories = new SelectList(categories, "NewsCategoriesID", "NewsCategoriesName",selectedValue);
// ViewBag.NewsCategoriesID = new SelectList(categories as IEnumerable<dms_NewsCategory>, "NewsCategoriesID", "NewsCategoriesName", dsn.NewsCategoriesID);
ViewBag.NewsCategoriesID = ListCategories;
return View(dsn);
}
And then my view:
#Html.DropDownList("NewsCategoriesID", (SelectList)ViewBag.NewsCategoriesID)
When i run, the DropDownList does not select the value I set.. It is always selecting the first option.
You should use view models and forget about ViewBag Think of it as if it didn't exist. You will see how easier things will become. So define a view model:
public class MyViewModel
{
public int SelectedCategoryId { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
}
and then populate this view model from the controller:
public ActionResult NewsEdit(int ID, dms_New dsn)
{
var dsn = (from a in dc.dms_News where a.NewsID == ID select a).FirstOrDefault();
var categories = (from b in dc.dms_NewsCategories select b).ToList();
var model = new MyViewModel
{
SelectedCategoryId = dsn.NewsCategoriesID,
Categories = categories.Select(x => new SelectListItem
{
Value = x.NewsCategoriesID.ToString(),
Text = x.NewsCategoriesName
})
};
return View(model);
}
and finally in your view use the strongly typed DropDownListFor helper:
#model MyViewModel
#Html.DropDownListFor(
x => x.SelectedCategoryId,
Model.Categories
)
just in case someone comes with this question, this is how I do it, please forget about the repository object, I'm using the Repository Pattern, you can use your object context to retrieve the entities. And also don't pay attention to my entity names, my entity type Action has nothing to do with an MVC Action.
Controller:
ViewBag.ActionStatusId = new SelectList(repository.GetAll<ActionStatus>(), "ActionStatusId", "Name", myAction.ActionStatusId);
Pay attention that the last variable of the SelectList constructor is the selected value (object selectedValue)
Then this is my view to render it:
<div class="editor-label">
#Html.LabelFor(model => model.ActionStatusId, "ActionStatus")
</div>
<div class="editor-field">
#Html.DropDownList("ActionStatusId")
#Html.ValidationMessageFor(model => model.ActionStatusId)
</div>
I think it is pretty simple, I hope this helps! :)
I drilled down the formation of the drop down list instead of using #Html.DropDownList(). This is useful if you have to set the value of the dropdown list at runtime in razor instead of controller:
<select id="NewsCategoriesID" name="NewsCategoriesID">
#foreach (SelectListItem option in ViewBag.NewsCategoriesID)
{
<option value="#option.Value" #(option.Value == ViewBag.ValueToSet ? "selected='selected'" : "")>#option.Text</option>
}
</select>
Well its very simple in controller you have somthing like this:
-- Controller
ViewBag.Profile_Id = new SelectList(db.Profiles, "Id", "Name", model.Profile_Id);
--View (Option A)
#Html.DropDownList("Profile_Id")
--View (Option B) --> Send a null value to the list
#Html.DropDownList("Profile_Id", null, "-- Choose --", new { #class = "input-large" })
Replace below line with new updated working code:
#Html.DropDownList("NewsCategoriesID", (SelectList)ViewBag.NewsCategoriesID)
Now Implement new updated working code:
#Html.DropDownListFor(model => model.NewsCategoriesID, ViewBag.NewsCategoriesID as List<SelectListItem>, new {name = "NewsCategoriesID", id = "NewsCategoriesID" })
I want to put the correct answer in here, just in case others are having this problem like I was. If you hate the ViewBag, fine don't use it, but the real problem with the code in the question is that the same name is being used for both the model property and the selectlist as was pointed out by #RickAndMSFT
Simply changing the name of the DropDownList control should resolve the issue, like so:
#Html.DropDownList("NewsCategoriesSelection", (SelectList)ViewBag.NewsCategoriesID)
It doesn't really have anything to do with using the ViewBag or not using the ViewBag as you can have a name collision with the control regardless.
I prefer the lambda form of the DropDownList helper - see MVC 3 Layout Page, Razor Template, and DropdownList
If you want to use the SelectList, then I think this bug report might assist - http://aspnet.codeplex.com/workitem/4932
code bellow, get from, goes
Controller:
int DefaultId = 1;
ViewBag.Person = db.XXXX
.ToList()
.Select(x => new SelectListItem {
Value = x.Id.ToString(),
Text = x.Name,
Selected = (x.Id == DefaultId)
});
View:
#Html.DropDownList("Person")
Note:
ViewBag.Person and #Html.DropDownList("Person") name should be as in view model
To have the IT department selected, when the departments are loaded from tblDepartment table, use the following overloaded constructor of SelectList class. Notice that we are passing a value of 1 for selectedValue parameter.
ViewBag.Departments = new SelectList(db.Departments, "Id", "Name", "1");
For anyone that dont want to or dont make sense to use dropdownlistfor, here is how I did it in jQuery with .NET MVC set up.
Front end Javascript -> getting data from model:
var settings = #Html.Raw(Json.Encode(Model.GlobalSetting.NotificationFrequencySettings));
SelectNotificationSettings(settings);
function SelectNotificationSettings(settings) {
$.each(settings, function (i, value) {
$("#" + value.NotificationItemTypeId + " option[value=" + value.NotificationFrequencyTypeId + "]").prop("selected", true);
});
}
In razor html, you going to have few dropdownlist
#Html.DropDownList(NotificationItemTypeEnum.GenerateSubscriptionNotification.ToString,
notificationFrequencyOptions, optionLabel:=DbRes.T("Default", "CommonLabels"),
htmlAttributes:=New With {.class = "form-control notification-item-type", .id = Convert.ToInt32(NotificationItemTypeEnum.GenerateSubscriptionNotification)})
And when page load, you js function is going to set the selected option based on value that's stored in #model.
Cheers.

MVC DropDownListFor() Selected Item is not Selected / Required Validation not run

I am having trouble getting my DropDownList to set the selected item to the value from the model.
The field in the model is just a string for the Title of the users name (Mr, Miss etc..) Below is my code so far.
<td>
#{ var list = new List<SelectListItem>(new[] {
new SelectListItem{ Selected = string.IsNullOrEmpty(Model.Title), Text="",Value=""},
new SelectListItem{ Selected = Model.Title.Equals("Mr"), Text="Mr",Value="Mr"},
new SelectListItem{ Selected = Model.Title.Equals("Mrs"), Text="Mrs",Value="Mrs"},
new SelectListItem{ Selected = Model.Title.Equals("Miss"), Text="Miss",Value="Miss"},
new SelectListItem{Selected = Model.Title.Equals("Ms"), Text="Ms",Value="Ms"}
});
}
#Html.DropDownListFor(m=>m.Title, list)
</td>
I had this problem with MVC 3 and it turned out that I had set ViewBag.Title on my View (using it for the page title). As soon as I changed it to ViewBag.PageTitle, the dropdownlist code started working : #Html.DropDownListFor(model => model.Title, Model.MySelectList)
The reason for this is that in MVC 2/3, any ViewBag / ViewData properties with the same name as those in the Model object get used in preference in DropDownListFor(), so you need to rename them to make sure they don't conflict. Because that seems really flaky, I just stopped using ViewBag entirely and now rely only on the View Model for passing stuff into the View.
The reason this problem is so prevalent is that ViewBag.Title is used in many introductory tutorials and demo code to set the HTML title element, and so inevitably gets adopted as a "best-practice" approach. However, Title is a natural Model property name for use in dropdowns on a "User Details" view.
So it turns out that the only reason it doesn't work is because my field name is Title, I changed it to Prefix and my exact code works. Way too much time spent finding that out...
Here is working code.
<td>
#{ var list = new List<SelectListItem>(new[] {
new SelectListItem {
Selected = string.IsNullOrEmpty(Model.Prefix),
Text="",
Value=""
},
new SelectListItem {
Selected = Model.Prefix.Equals("Mr"),
Text="Mr",
Value="Mr"
},
new SelectListItem {
Selected = Model.Prefix.Equals("Mrs"),
Text="Mrs",
Value="Mrs"
},
new SelectListItem {
Selected = Model.Prefix.Equals("Miss"),
Text="Miss",
Value="Miss"
},
new SelectListItem {
Selected = Model.Prefix.Equals("Ms"),
Text="Ms",
Value="Ms"
}
});
}
#Html.DropDownListFor(m => m.Prefix, list)
</td>

Resources