Grouping radio buttons in c# mvc

2020-07-24 06:56发布

问题:

I Have a form in which I display a menu. Each menu has a section and choices as below:

Starters

Prawn Cocktail 
Soup

Mains

Beef
Lamb

I am looping through the menu sections and menu choices for that section, for each menu option I want a radio button and to group them together per section so that only one menu option can be selected per section. By default the top selection will be selected. This is what I have so far

In the model

public List<MenuCourses> courses {get; set;}
public List<MenuOptions> options {get;set;}

and in the view

@for ( int i = 0; i < Model.MenuCourses.Count(); i++ ){

      @Html.DisplayFor(m=> m.MenuCourses[i].CourseTitle )

      // loop options
      for ( int k = 0; k < Model.MenuOptions.Count(); k++ ){

          if(Model.MenuOptions[k].MenuCoursesID == Model.MenuCourses[i].MenuCoursesID){

             @Html.DisplayFor(m=> m.MenuOptions[k].Title)
             //NEED RADIO BUTTON HERE BUT HOW DO I BIND TO THE MODEL?

           }
       }

I need each menu option to have a radio button grouped to that section, and when the user hits save I need to pick up which menu options has been selected.

Any help would be greatly appreciated

Thanks in advance

回答1:

You can do this with EditorTemplates.

Let's create 3 view models for our scenario.

public class Course
{
    public int ID { set; get; }
    public string Name{ set; get; }
    public List<Option> Options{ set; get; }
    public int SelectedAnswer { set; get; }
    public Course()
    {
        Options= new List<Option>();
    }
}
public class Option
{
    public int ID { set; get; }
    public string Title { set; get; }
}
public class OrderViewModel 
{
    public List<Course> Courses{ set; get; }
    public OrderViewModel()
    {
        Courses= new List<Course>();
    }
}

In our GET action method for the view, we will create an object of our OrderViewModel class and set the Course collection and it’s Options properties and then send that to the view by passing it to the View method.

public ActionResult Index()
{
    var vm= new OrderViewModel();

    //the below is hard coded for DEMO. you may get the data from some  
    //other place and set the course and options

    var q1 = new Course { ID = 1, Name= "Starters" };
    q1.Options.Add(new Option{ ID = 12, Title = "Prawn Cocktail " });
    q1.Options.Add(new Option{ ID = 13, Title = "Soup" });
    vm.Courses.Add(q1);     

    var q2 = new Course { ID = 1, Name= "Mains" };
    q2.Options.Add(new Option{ ID = 42, Title = "Beef" });
    q2.Options.Add(new Option{ ID = 43, Title = "Lamp" });
    vm.Courses.Add(q2);

   return View(vm);           
}

Now go to the ~/Views/YourControllerName folder and create a folder called EditorTemplates. Create a new view there with the name Course.cshtml. Add the below code to that file

@model Course
<div>
    @Html.HiddenFor(x=>x.ID)
    <h3> @Model.Name</h3>
    @foreach (var a in Model.Options)
    {
       <p>
          @Html.RadioButtonFor(b=>b.SelectedAnswer,a.ID)  @a.Title
       </p>
    }
</div>

Now go to the main view and use EditorFor html helper method to bring the editortemplate

@model OrderViewModel 
<h2>Your Order</h2>
@using (Html.BeginForm())
{
    @Html.EditorFor(x=>x.Courses)
    <input type="submit" />
}

To get the selected items on form submit, you can do this

[HttpPost]
public ActionResult Index(OrderViewModel model)
{
    if (ModelState.IsValid)
    {
        foreach (var q in model.Courses)
        {
            var qId = q.ID;
            var selectedAnswer = q.SelectedAnswer;
            // Save the data 
        }
        return RedirectToAction("ThankYou"); //PRG Pattern
    }
    //to do : reload courses and options on model.
    return View(model);
}

This is clearly explained in this blog post with a working sample which you can download and run yourself and see how it works.