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

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.

Related

DropdownList Data Annotation does not fire when the Textboxes and other controls are firing

I have a form that has several controls in it. I added data annotation to display an error message to the user when the required field are left empty. The TextBoxes and other controls display the message, which is an "*" before the label name, but the dropdownlist does not not. Once the user get rid of all the error messages and click on submit again, then, the message for the dropdown box is display. How do I force the dropdown box to display the message at the same time with the textbox?
Additional information:
Here is a sample of my data annotation:
[MetadataType(typeof(UserMetaData))]
public partial class UserMeta
{
}
public class UserMetaData
{
[Required(ErrorMessage = "*")]
public int GenderID { get; set; }
//The gender ID is displayed in a dropdown
list with "Select" as the default option. Then, it has all the other genders
showing in the dropdown once it is clicked on.
[Required(ErrorMessage = "*")]
public DateTime DataOfBirth{ get; set; }
}
In my view, I am using
#Html.ValidationMessageFor(model => model.DataOfBirth) //This is working fine.
#Html.ValidationMessageFor(model => model.GenderID)
//Here is the dropdown
#Html.DropDownList("GenderID", null, "Select", new { style = "width:200px;", onchange = "ValidateDropdown()" })
//This is the one that is not working as expected. I could get it to work using javascript, but I am trying not to it if I there is a way to get it to work properly using data annotation.
Thank in advance for your help.
I could not get it to work properly on the server side. As a result, I had to write a JQuery function that does the validation for the dropdown on the client side. Then, I do the post only if there is a selection on the dropdown.

SelectList doesn't show the selected item

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))
};

Telerik MVC custom AJAX editor template

I am using the MVC version of the Telerik controls with ASP.NET MVC and the razor view engine. I have an AJAX grid. When I click edit I want it to display the data in form style. But the issue is that I want to rearrange the in form controls they way that I want them to display. How would I do something like that? Currently the controls are all beneath each other. I want to create my own layout for editing.
I have a whole lot of other controls on the view, one of them being this grid. My view model object has a list of Children objects and I want to use my grid to populate this list.
The view model for my view:
public class EditGrantApplicationViewModel
{
public string EmployeeNumber { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// Other properties
// I want this to be populated from the grid
public IEnumerable<Children> Children { get; set; }
}
My grid's code for the Children list:
#(Html.Telerik().Grid(Model.Children)
.Name("grdChildren")
.Columns(column =>
{
column.Bound(x => x.Id);
column.Bound(x => x.FullName);
}
)
.DataKeys(keys =>
{
keys.Add(x => x.Id);
}
)
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
.Select("_SelectAjaxEditing", "Grid")
.Insert("_InsertAjaxEditing", "Grid")
.Update("_SaveAjaxEditing", "Grid")
.Delete("_DeleteAjaxEditing", "Grid");
}
)
.ToolBar(commands => commands.Insert().ButtonType(GridButtonType.Text))
.Editable(editing => editing.Mode(GridEditMode.InForm))
)
I'm not sure how my editor template must look like? What must it extend? And I can't get it to show in the inline form. I worked through the sample from Brad Wilson but I am not getting it. Can someone please explain what is happening?
Just another questions.. On my other page I have a grid with other HTML controls on the page. If I am busy editing data in the grid, and click insert, how would I prevent the other controls on the page not to be validated?
You can define a custom editor template for your model and arrange the fields as you wish. This code library project shows how.

Using ASP.NET MVC 3 with Razor, what's the most effective way to add an ICollection to a Create view?

I'm using Entity Framework Code First to generated my database, so I have an object defined like the following:
public class Band
{
public int Id { get; set; }
[Required(ErrorMessage = "You must enter a name of this band.")]
public string Name { get; set; }
// ...
public virtual ICollection<Genre> Genres { get; set; }
}
Now I'm looking at a create view for this and the default scaffolding isn't adding Genres to my form, which from past experience is about what I expect.
Looking online I've found Using ASP.NET MVC v2 EditorFor and DisplayFor with IEnumerable<T> Generic types which seems to come closest to what I want, but doesn't seem to make sense with Razor and possibly MVC 3, per ASP.NET MVC 3 Custom Display Template With UIHint - For Loop Required?.
At present I've added the listing of genres to the ViewBag and then loop through that listing in my create view:
#{
List<Genre> genreList = ViewBag.Genres as List<Genre>;
}
// ...
<ul>
#for (int i = 0; i < genreList.Count; i++)
{
<li><input type="checkbox" name="Genres" id="Genre#(i.ToString())" value="#genreList[i].Name" /> #Html.Label("Genre" + i.ToString(), genreList[i].Name)</li>
}
</ul>
Outside of not yet handling cases where the user has JavaScript disabled and the checkboxes need to be re-checked, and actually updating the database with this information, it does output the genres as I'd like.
But this doesn't feel right, based on how good MVC 3 has become.
So what's the most effective way to handle this in MVC 3?
I don't send lists into my View via the ViewBag, instead I use my viewmodel to do this. For instance, I did something like this:
I have an EditorTemplate like this:
#model IceCream.ViewModels.Toppings.ToppingsViewModel
<div>
#Html.HiddenFor(x => x.Id)
#Html.TextBoxFor(x =x> x.Name, new { #readonly="readonly"})
#Html.CheckBoxFor(x => x.IsChecked)
</div>
which I put in my Views\IceCream\EditorTemplates folder. I use this to display some html for allowing the user to "check" any particular topping.
Then in my View I've got something like this:
#HtmlEditorFor(model => model.Toppings)
and that will use that result in my EditorTemplate being used for each of the toppings in the Toppings property of my viewmodel.
And then I've got a viewmodel which, among other things, includes the Toppings collection:
public IEnumerable<ToppingsViewModel> Toppings { get; set; }
Over in my controller, among other things, I retrieve the toppings (however I do that in my case) and set my viewmodel's property to that collection of toppings. In the case of an Edit, where toppings may have been selected previously, I set the IsChecked member of the TopingsViewModel and it'll set the corresponding checkboxes to checked.
Doing it this way provided the correct model binding so that when the user checked a few toppings, the underlying items in the collection reflected those selections. Worked well for me, hope it's helpful for you.

Strongly Typed RadioButtonlist

I want to get some options (say payment method cash, credit card etc.) and bind these to radio buttons. I believe there is no RadioButtonList in MVC 3.
Also, once radios are bound I want to show the previously selected option to the user while editing the answer.
As always you start with a model:
public enum PaiementMethod
{
Cash,
CreditCard,
}
public class MyViewModel
{
public PaiementMethod PaiementMethod { get; set; }
}
then a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel();
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return View(model);
}
}
and finally a view:
#model MyViewModel
#using (Html.BeginForm())
{
<label for="paiement_cash">Cash</label>
#Html.RadioButtonFor(x => x.PaiementMethod, "Cash", new { id = "paiement_cash" })
<label for="paiement_cc">Credit card</label>
#Html.RadioButtonFor(x => x.PaiementMethod, "CreditCard", new { id = "paiement_cc" })
<input type="submit" value="OK" />
}
And if you want some more generic solution which encapsulates this in a helper you may find the following answer helpful.
This is how I like to bind RadioButtonLists. The view model has a collection of my strongly typed objects. For example, maybe PaymentOptions is a code table. Along with the collection is a SelectedPaymentOptionKey (or Selected*Id if you prefix your primary keys with Id). Initially this key will just be default 0, but on postback, it will hold the value of the selected item.
public class PaymentSelectionVM
{
public ICollection<PaymentOption> PaymentOptions { get; set; }
public int SelectedPaymentOptionKey { get; set; }
}
public ViewResult PaymentSelection()
{
var paymentOptions = db.PaymentOptions.ToList();
return View(
new PaymentSelectionVM {
PaymentOptions = paymentOptions,
//This is not required, but shows how to default the selected radiobutton
//Perhaps you have a relationship between a Customer and PaymentOption already,
//SelectedPaymentOptionKey = someCustomer.LastPaymentOptionUsed.PaymentOptionKey
// or maybe just grab the first one(note this would NullReferenceException on empty collection)
//SelectedPaymentOptionKey = paymentOptions.FirstOrDefault().PaymentOptionKey
});
}
Then in the View:
#foreach (var opt in Model.PaymentOptions)
{
#*Any other HTML here that you want for displaying labels or styling*#
#Html.RadioButtonFor(m => m.SelectedPaymentOptionKey, opt.PaymentOptionKey)
}
The m.SelectedPaymentOptionKey serves two purposes. First, it groups the Radio buttons together so that the selection is mutually exclusive(I would encourage you to use something like FireBug to inspect the generated html just for your own understanding. The wonderful thing about MVC is the generated HTML is fairly basic and standard so it shouldn't be hard for you to eventually be able to predict the behavior of your views. There is very little magic going on here.). Second, it will hold the value of the selected item on postback.
And finally in the post handler we have the SelectedPaymentOptionKey available:
[HttpPost]
public ActionResult PaymentSelection(PaymentSelectionVM vm)
{
currentOrder.PaymentOption = db.PaymentOptions.Find(vm.SelectedPaymentOptionKey);
....
}
The advantage of this over using SelectListItems is you have access to more of the object's properties in the case that you are displaying a grid/table and need to display many values of the object. I also like that there are no hard coded strings being passed in the Html helpers as some other approaches have.
The disadvantage is you get radio buttons which all have the same ID, which is not really a good practice. This is easily fixed by changing to this:
#Html.RadioButtonFor(m => m.SelectedPaymentOptionKey, opt.PaymentOptionKey, new { id = "PaymentOptions_" + opt.PaymentOptionKey})
Lastly, validation is a bit quirky with most all of the radio button techniques I've seen. If I really needed it, I would wire some jquery up to populate a hidden SelectedPaymentOptionsKey whenever the radio buttons are clicked, and place the [Required] or other validation on the hidden field.
Another workaround for the validation problem
ASP.NET MVC 3 unobtrusive validation and radio buttons
This looks promising but I haven't had a chance to test it:
http://memoriesdotnet.blogspot.com/2011/11/mvc-3-radiobuttonlist-including.html
You should bind your options to SelectList in ViewModel and set Selected attribute to true for previously selected option

Resources