MVC4 CheckboxFor HtmlAttributes issue - asp.net-mvc-3

I have a checkbox like this with defined value and text.
#Html.CheckBoxFor(model => model.UserGroup.administration, new[] { new SelectListItem { Text = "True", Value = "1" }, new SelectListItem { Text = "False", Value = "0" } })
I would like to add another html attributes which is "id=1", but it gave me an error if I attempt to do so in new[] {...}
I get the following errors : “No best type found for implicitly-typed array”
Any idea?

If you want to manually set the control ID to MyClass you can do it like this:
#Html.CheckBoxFor(model => model.UserGroup.administration, new { id = "MyClass" })
The other attributes should be mapped automatically if your model.UserGroup.administration is a boolean...

Related

Drop-down not working in ToSelectList extension method

I've got a nullable enum that, unlike others on the same page, doesn't work. I have an enum, Title whereby using the extension method will help to populate a drop-down list on the page. Here's what the ViewBag declaration looks like:
ViewBag.TitleList = EnumExtensions.ToSelectList<Title>("[select]");
Now, perhaps someone could explain it to me, but this is where the black magic happens when it comes to binding in MVC. If the page is invalid when calling if(ModelState.IsValid) then upon re-rendering the screen, the above statement is called again. However this time, the correct drop-down item will be selected (dependent on which one you had selected at the time).
Digging deeper, this is the method declarations:
public static SelectList ToSelectList<TEnum>(string nullEntry = null) where TEnum : struct
{
return ToSelectList<TEnum>(nullEntry, null);
}
public static SelectList ToSelectList<TEnum>(string nullEntry = null, string selectedValue = null) where TEnum : struct
{
var enumType = typeof(TEnum);
var values = Enum.GetValues(enumType).OfType<TEnum>();
List<SelectListItem> items = ToSelectList<TEnum>(values, nullEntry, selectedValue);
SelectList sl = new SelectList(items, "Value", "Text", selectedValue);
return sl;
}
public static List<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, string nullEntry, string selectedValue = null)
{
List<SelectListItem> items;
if ((typeof(T).IsEnum))
{
items = enumerable.Select(f => new SelectListItem()
{
Text = f.GetDescription(),
Value = f.ToString(),
Selected = f.ToString() == selectedValue
}).ToList();
}
else
{
items = enumerable.Select(f => new SelectListItem()
{
Text = f.ToString(),
Value = f.ToString()
}).ToList();
}
if (!string.IsNullOrEmpty(nullEntry))
{
items.Insert(0, new SelectListItem() { Text = nullEntry, Value = "" });
}
return items;
}
There's just some overloads to handle random cases, although presumably some of these won't be needed.
As I say, the correct item will be selected for other enumerations, but for this particular one, Title, it will not. Here's the enum declaration:
public enum Title
{
Mr,
Miss,
Mrs,
Ms
}
And finally, the declaration using DropDownListFor on the page itself;
#Html.DropDownListFor(x => x.Title, (SelectList)ViewBag.TitleList)
The problem is that when I first visit the page, the selected item is always "[select]" (when the provided enum value is null in the model). However, the model property Title definitely has a value set, and the SelectedItem property is set for the drop-down list too, but on screen, it defaults to "[select]" which is unexpected.
Any ideas?
Could it be because of the name Title? Try changing it to another name just to see.
Maybe you should try adding String.Empty so it the drop down list will default to a blank
#Html.DropDownListFor(x => x.Title, (SelectList)ViewBag.TitleList, String.Empty)

MVC3 DropDownListFor not populating selectedValue

I feel like I'm taking crazy pills. I have a dropdownlist for a view that reads from our database all of the wine producers we have. I want to set the selectedValue to a particular ID driven by the referring page. I can see it picks up the selectedValue in debug, I see the selected value populated (906 for this example), but it doesn't set the dropdownlist to the correct value when the page is rendered, it always defaults to 1 for the default value. I've tried creating the selectList in razor as opposed to my controller, but nothing works. Any help on this would be appreciated, I'm guessing it is something small.
Controller:
if (User.IsInRole("admin"))
{
if (ID != 0)
{
ViewBag.ProducerSelect = new SelectList(db.Producers.OrderBy(p => p.Name), "ProducerID", "Name", ID);
}
else
{
ViewBag.ProducerSelect = new SelectList(db.Producers.OrderBy(p => p.Name), "ProducerID", "Name");
}
}
View:
if (User.IsInRole("producereditor"))
{
<h3>#ViewBag.ProducerName</h3>
}
else
{
<div class="editor-label">
#Html.LabelFor(m => m.Wine.ProducerID, "Producer")
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.Wine.ProducerID, ViewBag.ProducerSelect as SelectList)
</div>
}
Tried the below but no success:
ViewBag.ProducerSelect = new SelectList(from p in db.Producers
orderby p.Name
select new { p.ProducerID, p.Name }
, "ProducerID", "Name", ID);
If you want to preselect an item, You set that value to your ProducerId property.
var yourViewModelObj=new YourViewModel;
yourViewModelObj.Wine.ProducerId=906; //or whatever value you want
return View(yourViewModelObj);
Suggestion : For better code readablity/Maintenance, Try to avoid ViewBag / ViewData and use a ViewModel to pass the data.
I would add a Property to my ViewModel to hold the Collection of Producers
public class WineViewModel
{
//Other Existing properties also
public IEnumerable<SelectListItem> Producers{ get; set; }
public string SelectedProducer { get; set; }
}
Then in yout GetAction method, you can set the value like this, If you want to set one select option as the default selected one.
public ActionResult CreateWine()
{
var vm=new WineViewModel();
//The below code is hardcoded for demo. you mat replace with DB data.
vm.Producers= new[]
{
new SelectListItem { Value = "1", Text = "Prodcer A" },
new SelectListItem { Value = "2", Text = "Prodcer B" },
new SelectListItem { Value = "3", Text = "Prodcer C" }
};
//Now let's set the default one's value
vm.SelectedProducer = "2";
return View(vm);
}
And in your Strongly typed View,
#Html.DropDownListFor(x => x.SelectedProducer,
new SelectList(Model.Producers, "Value", "Text"), "Select Producer")
The HTML Markup generated by above code will have the HTML select with the option with value 2 as selected one.
I figured this out. I had ViewModel.wine.ProducerID elsewhere on the page in a hidden field, and that defaults to 1, so I just assigned that to passed in value, and it worked great. I knew it was something like that. Thanks!
User a ViewModel ex WineViewModel
public class WineViewModel
{
public Wine Wine { get; set; }
public SelectList PProducerList { get; set; }
public WineViewModel() { }
public WineViewModel(Wine wine)
{
this.Wine = wine;
}
}
Try the following in your controller
var model = new WineViewModel( selectwine);
model.ProjectTypeList = new SelectList( from p in db.Producers
orderby p.Name
select new { p.ID, p.Name }, "ID", "Name")
notice how I am exclusively declaring which is the ID and which is the Value in my SelectList
Then in your view do
#Html.DropDownListFor(model => model.Wine.ProducerID, Model.ProjectTypeList)

How to display bool values in a view and save the value to DB

I have a table that has bit values (true/false)
Table Definition:
CharacterID int
isActive bit
UserId uniqueidentifier
I have 2 problems:
How to display the existing selected option in the edit view in a Dropdown
I need to save the value (yes/No) as true and false in the database.
Here is what I have attempted so far:
<div class="editor-label">
#Html.LabelFor(model => model.IsActive)
</div>
<div class="editor-field">
#Html.DropDownList("", new SelectListItem[] { new SelectListItem() { Text = "Yes", Value = "true", Selected = Model.IsActive }, new SelectListItem() { Text = "No", Value = "false", Selected = !Model.IsActive }})
</div>
Assuming that model.IsActive is declared as bool:
Wouldn't using a CheckBox be a bit more intuitive to the user and require less clicks?
In that case you could just use:
#Html.EditorFor(model => model.IsActive)
If you really want dropdowns, then this SO might provide a working implementation: https://stackoverflow.com/a/4036922/1373170
Applied to your context, I believe it would be:
#Html.DropDownListFor(model => model.IsActive, new SelectList(new SelectListItem[] { new SelectListItem() { Text = "Yes", Value = "True" }, new SelectListItem() { Text = "No", Value = "False"}}, model.IsActive.ToString())
Now, for saving it to the database I'd have to know if you are using EF, L2S, etc.
But I imagine you already have an action in your controller set up for saving. In that case it is probably already receiving an instance of your model as parameter. Using DropDownListFor instead of DropDownList, your model should be bound automatically by MVC's default ModelBinder, and you should be able to map that to your database entity and store it.
There are couple things you need to setup for drop-down and viewmodel property to make this work.
1) Your view model:
public class MyModel
{
public MyModel()
{
BoolSelectList = new List<SelectListItem>();
}
public int CharacterID { get; set; }
public bool isActive { get; set; }
public Guid UserId { get; set; }
public IList<SelectListItem> BoolSelectList { get; set; }
}
2) In controller you need to assign value to bool Value and List
public MyModel viewmodel = new MyModel();
// Set other properties of viewmodel
// ....
// Set Drop-down List values
viewModel.BoolSelectList = new SelectList(new SelectListItem[] { new SelectListItem() { Text = "Yes", Value = "True" }, new SelectListItem() { Text = "No", Value = "False"}};
3) In your view :
#Html.LabelFor(model => model.isActive, "Is Active ")
#Html.DropDownListFor(model => model.isActive, Model.BoolSelectList, model.IsActive.ToString())
On your Post action, the value of IsActive should be True/False depending on your selection.

ASP.net MVC validation issue

I have the following set for drop down in asp.net mvc
#Html.DropDownListFor(model => model.DataId, ((IEnumerable<ProgrammeModel>)ViewBag.Data).Select(option => new SelectListItem
{
Text = (option == null ? "None" : option.Name),
Value = option.DataId.ToString(),
Selected = (Model != null) && (option.DataId== Model.DataId)
}), "Choose...", new { Class = "input", id = "DataId"
})
And in model:
[Required(ErrorMessage="The Data field is required.")]
public int DataId { get; set; }
But when the validation happens on form submit I am getting the error message for this field as
The Int32 field is required.
where I was expecting the result as
The Data field is required
#Html.DropDownListFor(model => model.DataId,
new SelectList(ViewBag.Data as System.Collections.IEnumerable,
"DataId", "Name"), "Choose")
I had the same problem, It seems that in the controller you have ViewBag.DataId and it is causing confusion to the validation.
Please try removing it and let me know if it is ok now.
Thanks,
Dimitar

How do you properly create a MultiSelect <select> using the DropdownList helper?

(sorry, there are several item here but none seems to allow me to get this working.)
I want to create a DropDownList which allows multiple selection. I am able to populate the list but I can't get the currently selected values to seem to work.
I have the following in my controller:
ViewBag.PropertyGroups = from g in db.eFinGroups
where g.GroupType.Contents == "P"
select new
{
Key = g.Key,
Value = g.Description,
Selected = true
};
ViewBag.SelectedPropertyGroups = from g in company.Entities
.First().Properties.First().PropertyGroups
select new {
g.eFinGroup.Key,
Value = g.eFinGroup.Description };
In the view I have:
#Html.DropDownListFor(model => model.PropertyGroupsX,
new MultiSelectList(ViewBag.PropertyGroups
, "Key", "Value"
, ViewBag.SelectedPropertyGroups),
new { #class = "chzn-select", data_placeholder = "Choose a Property Group", multiple = "multiple", style = "width:350px;" })
PropertyGroupX is a string[] in the model.
I have tried all types of iterations with the selected properties... passing just the value, just the key, both, etc.
Also, what type is PropertyGroupX supposed to be? Is string array correct? Or should it be a dictionary that contains the current propertygroups? I really am having a hard time finding doc on this.
Someone suggested I should be using ListBoxFor. I have changed to that and still have the same issue. The selected values are not being set as selected when the option tags are rendered. Here is what I have tried:
#Html.ListBoxFor(model => model.PropertyGroups, new MultiSelectList(ViewBag.PropertyGroups, "Key", "Value"))
I have tried the model.PropertyGroups as a collection of string matching the Values, as a collection of Guid matching this IDs and as an anonymous type with both a Key and Value to match the items in the ViewBag. Nothing seems to work.
You don't use DropDownListFor if you want to create a multiselect list. You use the ListBoxFor helper.
View model:
public class MyViewModel
{
public string[] SelectedIds { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
}
Controller:
public ActionResult Index()
{
var model = new MyViewModel
{
// preselect the first and the third item given their ids
SelectedIds = new[] { "1", "3" },
// fetch the items from some data source
Items = Enumerable.Range(1, 5).Select(x => new SelectListItem
{
Value = x.ToString(),
Text = "item " + x
})
};
return View(model);
}
View:
#model MyViewModel
#Html.ListBoxFor(x => x.SelectedIds, Model.Items)

Resources