DropDownListFor(...) selecting boolean false by default - asp.net-mvc

I have typical YesNo kind of dropdown in the application. For that, I have developed model (rather ViewModel Utility) class for future extension prupose.
public string Text { get; set; } // represents text part
public bool Value { get; set; } // represent value
public List<DropDown> DropDowns { get; set; } //list for binding
public void BuildYesNoDropDown()
{
DropDowns = new List<DropDown>();
DropDowns.Add(new DropDown { Text = "Yes", Value = true });
DropDowns.Add(new DropDown { Text = "No", Value = false });
}
Then, I bind it in view like following:
#Html.DropDownListFor(x => x.SelectedValue, new SelectList(Model.DropDowns, "Value", "Text",1),"Select") //last para - OptionLabel
On the view, all three parameters are getting display i.e. "Select", "Yes" and "No". But, by default "No" has been selected. If I make "Value" property as integer then it works fine and by default "Select" gets selected, but as mentioned in the code, if I tend to go with bool type then "No" gets selected.
How to get normal behavior when DataValueField is bool?

ViewModel
public bool flag { get; set; }
View
#Html.DropDownListFor(model => model.flag, new List<SelectListItem>()
{
new SelectListItem() { Text = "Yes", Value = "True" },
new SelectListItem() { Text = "No", Value = "False"}
}, "Select.....", new { #id = "flag", #class="form-control" })
#Html.ValidationMessageFor(model => model.flag)

Model:
public bool? Value { get; set; }
View:
#Html.EditorFor(model => model.Value)
This makes a drop down list automatically with 3 states that match the 3 states of a nullable bool: null, true, false. If you require that Value be answered you can use data annotations like so:
Model:
[Required]
public bool? Value { get; set; }
The takeaway is your model needs to be a real model -- it needs to model the input values from unset to set. If you need to input a int, you'll likely want to use a nullable int (so int?) and require the value. That way the initial value is null instead of 0. It is similar with other data types except string which is already nullable.

In my case I had a bunch of these dropdowns on the same page and I thought I'd be clever and reuse the select list, e.g.
var YesOrNoTriState = new List<SelectListItem> {
new SelectListItem { Text = "Select", Value = "" },
new SelectListItem { Text = "Yes", Value = true.ToString() },
new SelectListItem { Text = "No", Value = false.ToString() }
};
and in the view
<%: Html.DropDownListFor(x => x.Field1, Model.YesOrNoTriState) %>
<%: Html.DropDownListFor(x => x.Field2, Model.YesOrNoTriState) %>
that wasn't working. I initialized a separate select list for each dropdown and that fixed the problem

I know this is a old topic but I thought that for others this might come in handy to know a little background about.
no is selected by default because the default value of a bool is false
if you just set the model to be a
null-able Bool like this in your view model then it should by default select your default value. :
public bool? Value { get; set; }
and then you just set your dropdownlist like this in the view:
#Html.DropDownListFor(x => x.SelectedValue, new SelectList(Model.DropDowns, "Value", "Text",1),"{Default Select Value}")
the result of this should be that when the bool is null the automatically selected option should be your default value {Default Select Value}

Related

Dropdownlistfor returns null value

I have a customer class with a property Gender. I created a list of Gender type which contains and id number and Gender type. When form is submitted, I am getting null value.
View
#model MovieRentals.ViewModel.CustomerView
<div class="form-group">
<h4>#Html.LabelFor(l => l.Customer.BirthDate)</h4>
#Html.DropDownListFor(l => l.CustomerGender, new SelectList(Model.CustomerGender, "GenderId", "GenderType"), "Select Gender", new { #class = "form-control" })
</div>
Model
public class CustomerView
{
public IEnumerable<MembershipType> MembershipTypes{ get; set; }
public Customer Customer { get; set; }
public List<GenderClass> CustomerGender{ get; set; }
}
public class GenderClass
{
public int GenderId { get; set; }
public string GenderType { get; set; }
}
Controller
public ActionResult New()
{
var MembershipTy = _context.MemebershipType.ToList();
var ViewModel = new CustomerView();
ViewModel.CustomerGender = new List<GenderClass>()
{
new GenderClass(){ GenderId = 1, GenderType = "Male"},
new GenderClass() { GenderId = 2, GenderType = "Female"}
};
ViewModel.MembershipTypes = MembershipTy;
return View(ViewModel);
}
You need two properties: one to hold the selected value and one to hold the options. The one that holds the options should be IEnumerable<SelectListItem>. Your GenderClass class is completely superfluous.
Also, using an integer id as the value doesn't make sense when the meaning of that value is not obvious. Here, the fact that 1 means Male only exists in the New action. Anywhere else, you will then have to repeat this logic (which introduces opportunities for errors, e.g. was male 1 or 0). Further, if you decide to change those values, you must remember to change them everywhere. If you want to use an integer id, then you should abstract away the meaning somewhere, be it an enum, static class, database table, etc. The far better choice is to just keep it a string, and use the dropdown merely to enforce normalization of that string value.
public string CustomerGender { get; set; }
public IEnumerable<SelectListItem> CustomerGenderChoices
{
get
{
return new List<SelectListItem>
{
new SelectListItem { Value = "Male", Text = "Male" },
new SelectListItem { Value = "Female", Text = "Female" }
}
}
}
Then, in your view:
#Html.DropDownListFor(m => m.CustomerGender, Model.CustomerGenderChoices, "Select Gender", new { #class = "form-control" })
Alternatively, if you were to use an enum:
public enum Genders
{
Male = 1,
Female = 2
}
Then, in your view model, you would only need one property, just to store the value:
public Genders CustomerGender { get; set; }
Then, in your view, you can make use of EnumDropDownListFor:
#Html.EnumDropDownListFor(m => m.CustomerGender, "Select Gender", new { #class = "form-control" })
As an enum, the value stored would be an int, but the benefit here is that you have a strongly-typed association between those integer values and what they mean. For example, rather than doing something like:
if (customer.CustomerGender == 1) // Male
You can do:
if (customer.CustomerGender == Genders.Male)
Obviously, the second version is much more obvious in meaning.

dropdownlistfor not displaying correct value

My query is getting all the correct values and the selectlist is populated, but my dropdownlist only shows the first value in the selectlist. how can i get it to show the returned value of Captain?
Viewmodel:
public class EditTeamsView : BaseCommunityView
{
...
public IList<Domain.Team> ExistingTeams { get; set; }
...
public EditTeamsView()
{
ExistingTeams = new List<Domain.Team>();
}
}
public class Team
{
...
public string Captain { get; set; }
public IEnumerable<SelectListItem> MemberSelectList { get; set; }
}
View:
#for (var c = 0; c < Model.ExistingTeams.Count; c++)
{
#Html.DropDownListFor(x => x.ExistingTeams[c].Captain, Model.ExistingTeams[c].MemberSelectList,
new { #class = "form-control "})
}
Each option in the dropdown will need a value property and a display property so you may need to change up your Team class's MemberSelectList object to IEnumerable that contains value and text properties.
To set the default value of a drop down list based on a string value like what you have, new up a SelectList that requires an IEnumerable list of objects like what you have, a value property, a text property, and then the default value object.
See here: https://msdn.microsoft.com/en-us/library/system.web.mvc.selectlist.selectlist(v=vs.118).aspx#M:System.Web.Mvc.SelectList.
#Html.DropDownListFor(x => x.ExistingTeams[c].Captain,
new SelectList(Model.MemberSelectList, "Value", "Text", Model.Captain)
)

Formatting a Drop Down List in ASP.NET MVC

I'm building an app with ASP.NET MVC 4. I'm binding my model to a view. In my view, I need a drop down list. That drop down list needs to show quarters. The quarters should be displayed as "Q1", "Q2", "Q3", and "Q4". My model, only has quarter numbers. They are defined like this:
public List<short> Quarters = new List<short>() { get; set; }
public short? SelectedQuarter = null;
public void Initialize() {
Quarters.Add(1);
Quarters.Add(2);
Quarters.Add(3);
Quarters.Add(4);
}
Somehow, I need to prepend "Q" to each value. However, I'm not sure how to do this in ASP.NET MVC. How does someone do this?
Thanks!
Create a SelectList to be used by DropdownListFor() so that you bind the selected option to property SelectedQuarter, but display the 'friendly' name.
View model
public class MyViewModel
{
[Display(Name = "Quarter")]
[Required]
public short? SelectedQuarter { get; set; } // must be a property, not a field!
IEnumerable<SelectListItem> QuarterList { get; set; }
}
Controller
public ActionResult Edit()
{
MyViewModel model = new MyViewModel();
ConfigureViewModel(model);
return View(model);
}
public ActionResult Edit(MyViewModel model)
{
if(!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model);
}
// model.SelectedQuarter contains the selected value
}
private void ConfigureViewModel(model)
{
model.SelectedQuarter = new List<SelectListItem>()
{
new SelectListItem() { Value = "1", Text = "Q1" },
new SelectListItem() { Value = "2", Text = "Q2" },
new SelectListItem() { Value = "3", Text = "Q3" },
new SelectListItem() { Value = "4", Text = "Q4" },
}
}
View
#model MyViewModel
#using(Html.BeginForm())
{
#Html.LabelFor(m => m.SelectedQuarter)
#Html.DropDownListFor(m => m.SelectedQuarter, Model.QuarterList, "-Please select-")
#Html.ValidationMessageFor(m => m.SelectedQuarter)
<input type="submit" />
}
Assuming you have this property:
public List<short> Quarters { get; set; }
Then in your view or any other consuming code you can generate a list of strings with something like:
model.Quarters.Select(q => "Q" + q)
or:
model.Quarters.Select(q => string.Format("Q{0}", q))
However, semantically it really feels like this belongs on a view model and not in consuming code. Ideally the view should only ever need to bind directly to properties on the view model, not transform those properties. Something like this:
public IEnumerable<string> QuartersDisplay
{
get { return Quarters.Select(q => string.Format("Q{0}", q)); }
}
Then consuming code can just bind to that property:
model.QuartersDisplay
(If the model is a domain model then I'd recommend introducing a view model between the domain and the view, since this wouldn't belong on a domain model.)
Thinking about this a little more... Do you want one property with both the displays and the backing values for the drop down list? That would likely be a IDictionary<short, string>, I imagine? Something like this:
public IDictionary<short, string> QuartersOptions
{
get { return Quarters.ToDictionary(q => q, q => string.Format("Q{0}", q)); }
}
In which case you'd bind to that property:
model.QuartersOptions
Keep in mind that a drop down list often binds to two things. The property which holds the list of possible values (which is what we've built here) and the property which holds the selected value (which remains your SelectedQuarter property).

MVC4 annotation conditional validation depending on input of another field

Here is my model:
Primary
{
public Boolean Yes { get; set; }
public Boolean NoHome { get; set; }
public int mailzip
public string mailcity
public string mailstate
}
i have 2 fields based on which required field validation via annotation must be done on a textbox
one of them is a checkbox (condition for required field to activate -> this must be checked)
#Html.CheckBoxFor(model => model.nohome, new { name = "NoHome", id = "NoHome" })
OR
The other is a #Html.RadioButtonFor pair - the below must be clicked as yes for the required field to be validated
#Html.RadioButtonFor(model => model.primary.yes, "true", new { name = "DifferentAddress", id = "DifferentAddressYes" })
#Html.RadioButtonFor(model => model.primary.no, "true", new { name = "DifferentAddress", id = "DifferentAddressYes" })
Either of the above two fields should be able to fire the required field attribute on the below 3 fields
mailzip
mailcity
mailstate

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