DropDownListFor - why selected element is always the first? - asp.net-mvc

I have a DropDownListFor in my View:
#model UserProfileViewModel
#Html.DropDownListFor(x => x.PreferredLangID,
new SelectList(Model.PreferredLanguages,
"LanguageID",
"DisplayName",
Model.PreferredLang))
Controller action:
public ActionResult EditProfile()
{
List<Language> languages = Code.LanguageLogic.GetAllLanguages();
UserProfile profile = Code.ProfileLogic.GetUserProfile();
var viewModel = new UserProfileViewModel
{
UserID = profile.UserID,
PreferredLanguages = languages,
PreferredLang = profile.PreferredLang
};
return View(viewModel);
}
I thought, that if I gave Model.PreferredLang as 4th paramater in SelectList's contructor, that element will be selected in dropdown, when page loads. But selected element is always the first one in list.
The Model:
public class UserProfileViewModel
{
public Guid UserID { get; set; }
public Language PreferredLang { get; set; }
public int PreferredLangID { get; set; }
public IEnumerable<Language> PreferredLanguages { get; set; }
//...
}

I don't know the details of the type, so I can't say for sure, but I'm guessing you might need:
#Html.DropDownListFor(x => x.PreferredLangID,
new SelectList(Model.PreferredLanguages,
"LanguageID",
"DisplayName",
Model.PreferredLang.PreferredLangId))
ETA:
Or, with your addition:
#Html.DropDownListFor(x => x.PreferredLangID,
new SelectList(Model.PreferredLanguages,
"LanguageID",
"DisplayName",
Model.PreferredLangId))

The second snipped for View was correct:
#Html.DropDownListFor(x => x.PreferredLangID,
new SelectList(Model.PreferredLanguages,
"LanguageID",
"DisplayName",
Model.PreferredLangId))
But the Controller was also missing something. Model.PreferredLangID must be also set:
var viewModel = new UserProfileViewModel
{
UserID = profile.UserID,
IsAdministrator = profile.IsAdministrator,
PreferredLanguages = languages,
PreferredLangID = profile.PreferredLang.LanguageID
};
I'm not sure, why this didn't work with
new SelectList(Model.PreferredLanguages,
"LanguageID",
"DisplayName",
Model.PreferredLang.LanguageID))

Related

How to clear text from a search textbox after search is complete in MVC

I have two dropdown lists and two textboxes
Search By: ByHtml.DropDownList("Search1", "Please Select...")
Html.TextBox("searchString1")
Search By: Html.DropDownList("Search2", "Please Select...")
#Html.TextBox("searchString2")
<input type="submit" value="Filter" />
When I make my selection from whichever DDL and type text into the textbox and hit filter my search returns, however after the search the text remains in the textbox, is there a way of clearing it after the search so that the textbox is empty again? I tried
ModelState.Remove("");
but it didn't work.
A sample from My controller code is
public class MainController : Controller
{
private DBEntities db = new DBEntities();
// GET: /Main/
public ActionResult Index(string searchString1, string searchString2, string Search1, string Search2)
{
//Create a Dropdown list
var SearchOptionList = new List<string>();
SearchOptionList.Add("LandLord");
SearchOptionList.Add("Postcode");
SearchOptionList.Add("Street Address");
ViewBag.Search1 = new SelectList(SearchOptionList);
ViewBag.Search2 = new SelectList(SearchOptionList);
var mylist = from m in "mydatabase" select m;
//This statement runs if the user selects a parameter from Search2 and leaves Search1 empty
if (String.IsNullOrEmpty(Search1) && !String.IsNullOrEmpty(Search2))
{
if (Search2 == "Postcode")
{
mylist = mylist.Where(s => s.Postcode.Contains(searchString2));
}
if (Search2 == "LandLord")
{
mylist = mylist.Where(s => s.Name.Contains(searchString2));
}
if (Search2 == "Street Address")
{
mylist = mylist.Where(s => s.StreetAddress.Contains(searchString2));
}
}
return View(mylist.ToList());
}
Your should have a view model containing properties searchString1 and searchString2 and the select lists
public class SearchVM
{
public string searchString1 { get; set; }
public string searchString2 { get; set; }
public SelectList SearchList1 { get; set; }
public SelectList SearchList2 { get; set; }
}
Controller
public ActionResult Search()
{
SearchVM model = new SearchVM();
model.SearchList1 = new SelctList(...);
model.SearchList2 = new SelctList(...);
return View(model);
}
View
#model SearchVM
#using(Html.BeginForm())
{
....
#Html.DropDownListFor(m => m.searchString1, Model.SearchList1, "--Please select--")
#Html.DropDownListFor(m => m.searchString2, Model.SearchList2, "--Please select--")
....
}
Post
[HttpPost]
public ActionResult Search(SearchVM model)
{
// to clear all modelstate and reset values
ModelState.Clear();
model.searchString1 = null;
model.searchString2 = null;
// or to clear just one property and reset it
ModelState.Remove("searchString1");
model.searchString1 = null;
// repopulate select lists if your returning the view
return View(model);
}
At the end of my public ActionResult Index method but before return View() I placed the following code which worked perfectly
ModelState.Remove("searchString1");
ModelState.Remove("searchString2");
ModelState.Remove("Search1");
ModelState.Remove("Search2");
I know is an old question, but I fall in the same issue. So I put my solution.
View:
#Html.TextBox("Search", null, new { #autofocus = "autofocus" })
Controller:
ViewBag.Search= null;
ModelState.Remove("Search");
return View(list.ToList());
Hope to help someone

Drop down list value returns to ---select--- after page refresh

So in my application the user will select a name from the drop down list, click 'view' and the corresponding values will display on page.
A hyperlink is then used to sort the list in ascending order. For this to happen the page refreshes and displays the new order of the list.
The value of the drop down list returns back to its original value of 'select' instead of remaining the name of the person selected.
My Model:
public class HolidayList
{
public List<Holiday> HList4DD { get; set; }
public List<Person> PList4DD { get; set; }
public int currentPersonID { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
public HolidayList()
{
HList4DD = new List<Holiday>();
PList4DD = new List<Person>();
}
}
}
my controller:
[HttpPost]
public ViewResult Index(int HolidayDate)
{
var holidays = db.Holidays.Include("Person");
HolidayList model = new HolidayList();
model.currentPersonID = HolidayDate;
model.PList4DD = db.People.ToList();
model.Categories = holidays.Select(x => new SelectListItem
{
Value = x.Id.ToString(),
Text = x.Person.Name
}
);
int data = HolidayDate;
model.HList4DD = db.Holidays.Where(h => h.PersonId == HolidayDate).ToList();
return View(model);
}
[HttpGet]
public ViewResult Index(string sortOrder, int? currentPersonID)
{
var holidays = db.Holidays.Include("Person");
HolidayList model = new HolidayList();
//not null
if (currentPersonID.HasValue)
{
model.currentPersonID = currentPersonID.Value;
}
else
{
model.currentPersonID = 0;
}
model.PList4DD = db.People.ToList();
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "date" : "";
var dates = from d in db.Holidays
where d.PersonId == currentPersonID.Value
select d;
switch (sortOrder)
{
case "date":
dates = dates.OrderBy(p => p.HolidayDate);
break;
}
model.HList4DD = dates.ToList();
return View(model);
}
my view
i've tried a number of different attempts here, the following code worked but has the drop list problem
#Html.DropDownListFor(model => model.HList4DD.First().HolidayDate,
new SelectList(Model.PList4DD, "Id", "Name"),
// Model.currentPersonID
"---Select---"
) *#
my attempts to resolve this are:
#Html.DropDownList("HolidayDate", Model.Categories, "---Select---")
#Html.DropDownListFor("HolidayDate", x => x.HolidayDate, Model.Categories)
Any help much appreciated
You are binding the DropDownFor to a wrong property.
Basically what you want to do is in your Model, create a new Property to bind the value selected by the dropdown.
public int SelectedDate {get;set;}
Then in your code front you wanted to use dropdownFor to bind the property like this
#Html.DropDownListFor(model => model.SelectedDate ,
new SelectList(Model.PList4DD, "Id", "Name"),
// Model.currentPersonID
"---Select---"
)
Not this.
#Html.DropDownListFor(model => model.HList4DD.First().HolidayDate ,
new SelectList(Model.PList4DD, "Id", "Name"),
// Model.currentPersonID
"---Select---"
)
Finnaly, in the action that you wanted to do the sorting, you will need to pass the SelectedDate into the action. Then before you returning it, assign it to Model. And the whole thing will work like magic.

MVC DropDownList SelectedValue not displaying correctly

I tried searching and didn't find anything that fixed my problem. I have a DropDownList on a Razor view that will not show the the item that I have marked as Selected in the SelectList. Here is the controller code that populates the list:
var statuses = new SelectList(db.OrderStatuses, "ID", "Name", order.Status.ID.ToString());
ViewBag.Statuses = statuses;
return View(vm);
Here is the View code:
<div class="display-label">
Order Status</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.StatusID, (SelectList)ViewBag.Statuses)
#Html.ValidationMessageFor(model => model.StatusID)
</div>
I walk through it and even in the view it has the correct SelectedValue however the DDL always shows the first item in the list regardless of the selected value. Can anyone point out what I am doing wrong to get the DDL to default to the SelectValue?
The last argument of the SelectList constructor (in which you hope to be able to pass the selected value id) is ignored because the DropDownListFor helper uses the lambda expression you passed as first argument and uses the value of the specific property.
So here's the ugly way to do that:
Model:
public class MyModel
{
public int StatusID { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
// TODO: obviously this comes from your DB,
// but I hate showing code on SO that people are
// not able to compile and play with because it has
// gazzilion of external dependencies
var statuses = new SelectList(
new[]
{
new { ID = 1, Name = "status 1" },
new { ID = 2, Name = "status 2" },
new { ID = 3, Name = "status 3" },
new { ID = 4, Name = "status 4" },
},
"ID",
"Name"
);
ViewBag.Statuses = statuses;
var model = new MyModel();
model.StatusID = 3; // preselect the element with ID=3 in the list
return View(model);
}
}
View:
#model MyModel
...
#Html.DropDownListFor(model => model.StatusID, (SelectList)ViewBag.Statuses)
and here's the correct way, using real view model:
Model
public class MyModel
{
public int StatusID { get; set; }
public IEnumerable<SelectListItem> Statuses { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
// TODO: obviously this comes from your DB,
// but I hate showing code on SO that people are
// not able to compile and play with because it has
// gazzilion of external dependencies
var statuses = new SelectList(
new[]
{
new { ID = 1, Name = "status 1" },
new { ID = 2, Name = "status 2" },
new { ID = 3, Name = "status 3" },
new { ID = 4, Name = "status 4" },
},
"ID",
"Name"
);
var model = new MyModel();
model.Statuses = statuses;
model.StatusID = 3; // preselect the element with ID=3 in the list
return View(model);
}
}
View:
#model MyModel
...
#Html.DropDownListFor(model => model.StatusID, Model.Statuses)
Make Sure that your return Selection Value is a String and not and int when you declare it in your model.
Example:
public class MyModel
{
public string StatusID { get; set; }
}
Create a view model for each view. Doing it this way you will only include what is needed on the screen. As I don't know where you are using this code, let us assume that you have a Create view to add a new order.
Create a new view model for your Create view:
public class OrderCreateViewModel
{
// Include other properties if needed, these are just for demo purposes
// This is the unique identifier of your order status,
// i.e. foreign key in your order table
public int OrderStatusId { get; set; }
// This is a list of all your order statuses populated from your order status table
public IEnumerable<OrderStatus> OrderStatuses { get; set; }
}
Order status class:
public class OrderStatus
{
public int Id { get; set; }
public string Name { get; set; }
}
In your Create view you would have the following:
#model MyProject.ViewModels.OrderCreateViewModel
#using (Html.BeginForm())
{
<table>
<tr>
<td><b>Order Status:</b></td>
<td>
#Html.DropDownListFor(x => x.OrderStatusId,
new SelectList(Model.OrderStatuses, "Id", "Name", Model.OrderStatusId),
"-- Select --"
)
#Html.ValidationMessageFor(x => x.OrderStatusId)
</td>
</tr>
</table>
<!-- Add other HTML controls if required and your submit button -->
}
Your Create action methods:
public ActionResult Create()
{
OrderCreateViewModel viewModel = new OrderCreateViewModel
{
// Here you do database call to populate your dropdown
OrderStatuses = orderStatusService.GetAllOrderStatuses()
};
return View(viewModel);
}
[HttpPost]
public ActionResult Create(OrderCreateViewModel viewModel)
{
// Check that viewModel is not null
if (!ModelState.IsValid)
{
viewModel.OrderStatuses = orderStatusService.GetAllOrderStatuses();
return View(viewModel);
}
// Mapping
// Insert order into database
// Return the view where you need to be
}
This will persist your selections when you click the submit button and is redirected back to the create view for error handling.
I hope this helps.
For me, the issue was caused by big css padding numbers ( top & bottom padding inside the dropdown field). Basically, the item was being shown but not visible because it was way down. I FIXED it by making my padding numbers smaller.
I leave this in case it helps someone else. I had a very similar problem and none of the answers helped.
I had a property in my ViewData with the same name as the selector for the lambda expression, basically as if you would've had ViewData["StatusId"] set to something.
After I changed the name of the anonymous property in the ViewData the DropDownList helper worked as expected.
Weird though.
My solution was this...
Where the current selected item is the ProjectManagerID.
View:
#Html.DropDownList("ProjectManagerID", Model.DropDownListProjectManager, new { #class = "form-control" })
Model:
public class ClsDropDownCollection
{
public List<SelectListItem> DropDownListProjectManager { get; set; }
public Guid ProjectManagerID { get; set; }
}
Generate dropdown:
public List<SelectListItem> ProjectManagerDropdown()
{
List<SelectListItem> dropDown = new List<SelectListItem>();
SelectListItem listItem = new SelectListItem();
List<ClsProjectManager> tempList = bc.GetAllProductManagers();
foreach (ClsProjectManager item in tempList)
{
listItem = new SelectListItem();
listItem.Text = item.ProjectManagerName;
listItem.Value = item.ProjectManagerID.ToString();
dropDown.Add(listItem);
}
return dropDown;
}
Please find sample code below.
public class Temp
{
public int id { get; set; }
public string valueString { get; set; }
}
Controller
public ActionResult Index()
{
// Assuming here that you have written a method which will return the list of Temp objects.
List<Temp> temps = GetList();
var tempData = new SelectList(temps, "id", "valueString",3);
ViewBag.Statuses = tempData;
return View();
}
View
#Html.DropDownListFor(model => model.id, (SelectList)ViewBag.Statuses)
#Html.ValidationMessageFor(model => model.id)

Html.Dropdonlist and selected value

I have the following code:
int StatusID = ViewBag.DefaultStatus.StatusID;
List<NEOGOV_Ideas.Models.Status> statusList = ViewBag.StatusList;
#Html.DropDownList("DefaultStatus", new SelectList(statusList, "StatusID", "StatusName", StatusID))
but selected value does not set. Why?
Try like this in your controller action:
// set to a value that you want to be preselected
ViewBag.DefaultStatus = 123;
ViewBag.StatusList = ...
and in the view:
#{ List<NEOGOV_Ideas.Models.Status> statusList = ViewBag.StatusList; }
#Html.DropDownList(
"DefaultStatus",
new SelectList(statusList, "StatusID", "StatusName")
)
But I would recommend you using view models:
public class MyViewModel
{
public int SelectedStatusID { get; set; }
public SelectList Statuses { get; set; }
}
then in your controller action populate this view model and pass it to the view:
public ActionResult Foo()
{
List<NEOGOV_Ideas.Models.Status> statusList = ...
var model = new MyViewModel
{
// set to a value that you want to be preselected
SelectedStatusID = 123,
Statuses = new SelectList(statusList, "StatusID", "StatusName")
};
return View(model);
}
and finally in your strongly typed view:
#model MyViewModel
#Html.DropDownListFor(x => x.SelectedStatusID, Model.Statuses)

DropDownListFor selection not working -- again

Yeah, I know, this question's been asked/answered 34798796873.5 times. I looked through all 3 bajillion of them, and I still have the problem. What am I missing here?
I tried several approaches and none of them work. Here are my latest attempts:
<%:Html.DropDownList("Author",
Model.AuthorItems.Select(i =>
new SelectListItem
{
Text = i.Name,
Value = i.Id.ToString(),
Selected = i.Id == Model.Author.Id
}), "無し")%>
<%:Html.DropDownListFor(m => m.Author,
new SelectList(Model.AuthorItems,
"Id",
"Name",
Model.Author),
"無し") %>
My view model is very straightforward:
public class EditArticleViewModel
{
public AuthorItem Author { get; set; }
public IList<AuthorItem> AuthorItems { get; set; }
public class AuthorItem
{
public int Id { get; set; }
public string Name { get; set; }
}
}
I made sure my action is working correctly; sure enough, Author has an Id of 5, and AuthorItems has an entry whose Id is 5.
I even tried overriding Equals and GetHashCode in the model.
Blahhhhh!!1
In your view model replace:
public AuthorItem Author { get; set; }
with
public int? SelectedAuthorId { get; set; }
and in your view bind the dropdown list to this SelectedAuthorId:
<%:Html.DropDownListFor(
m => m.SelectedAuthorId,
new SelectList(Model.AuthorItems, "Id", "Name"),
"無し"
) %>
Now as long as you provide a valid SelectedAuthorId value in your controller action:
model.SelectedAuthorId = 123;
The HTML helper that renders the dropdown will correctly preselect the item from the list that has this given id.
The reason for this is that in a dropdown list you can select only a single value (a scalar type) and not an entire Author (all that is sent in the HTTP request when you submit the form is this selected value).
DropDownList/DropDownListFor used ModelState value. So set ViewDataDictionary selectedValue in controller.
public ActionResult Index()
{
var model = new EditArticleViewModel
{
Author = new EditArticleViewModel.AuthorItem() {Id = 3, Name = "CCC"},
AuthorItems = new List<EditArticleViewModel.AuthorItem>()
{
new EditArticleViewModel.AuthorItem() {Id = 1, Name = "AAA"},
new EditArticleViewModel.AuthorItem() {Id = 2, Name = "BBB"},
new EditArticleViewModel.AuthorItem() {Id = 3, Name = "CCC"},
new EditArticleViewModel.AuthorItem() {Id = 4, Name = "DDD"},
}
};
ViewData["Author"] = model.Author.Id;
return View(model);
}
View code simple.
<%:Html.DropDownList("Author",
new SelectList(Model.AuthorItems,
"Id",
"Name"), "無し")%>
<%:Html.DropDownListFor(m => m.Author,
new SelectList(Model.AuthorItems,
"Id",
"Name"),
"無し")%>
ViewData key "Author" is using model state binding for selected value.
Hope this help.

Resources