How do I render a group of checkboxes using MVC 4 and View Models (strongly typed)

后端 未结 3 1105
谎友^
谎友^ 2021-02-01 06:35

I\'m rather new to the ASP.net MVC world and I\'m trying to figure out how to render a group of checkboxes that are strongly typed to a view model. In webforms I would just use

相关标签:
3条回答
  • 2021-02-01 07:14

    For me this works too, and I think this is the simplest (reading the previous answers).

    The viewmodel has a string[] for the check boxes.

        public string[] Set { get; set; }
    

    The view has this code, and you can repeat the input as many times you need. name, id of the input control has to match the name of the property of the viewmodel.

    <div class="col-md-3">
      <div class="panel panel-default panel-srcbox">
        <div class="panel-heading">
          <h3 class="panel-title">Set</h3>
        </div>
        <div class="panel-body">
          <div class="form-group-sm">
            <label class="control-label col-xs-3">1</label>
            <div class="col-sm-8">
              <input type="checkbox" id="Set" name="Set" value="1" />
            </div>
            <label class="control-label col-xs-3">2</label>
            <div class="col-sm-8">
              <input type="checkbox" id="Set" name="Set" value="2" />
            </div>
          </div>
        </div>
      </div>
    </div>
    

    On the post method the Set variable is an array, having the checked value(s).

    0 讨论(0)
  • 2021-02-01 07:17

    Use a string array in your view model. You can then use the helper I hacked together. if you don't want to use the helper and the enum then see the actual Html at the bottom. The binder will return a string array with only the selected string values in it. if none are selected it returns a null value for your array. You must account for that, you have been warned :)

    View Model:

    [Display(Name = "Which Credit Cards are Accepted:")]
            public string[] CreditCards { get; set; }
    

    Helper:

    public static HtmlString CheckboxGroup<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> propertySelector, Type EnumType)
            {
                var groupName = GetPropertyName(propertySelector);
                var modelValues = ModelMetadata.FromLambdaExpression(propertySelector, htmlHelper.ViewData).Model;//propertySelector.Compile().Invoke(htmlHelper.ViewData.Model);
            StringBuilder literal = new StringBuilder();  
    
            foreach (var value in Enum.GetValues(EnumType))
            {
                var svalue = value.ToString();
                var builder = new TagBuilder("input");
                builder.GenerateId(groupName);
                builder.Attributes.Add("type", "checkbox");
                builder.Attributes.Add("name", groupName);
                builder.Attributes.Add("value", svalue);
                var contextValues = HttpContext.Current.Request.Form.GetValues(groupName);
                if ((contextValues != null && contextValues.Contains(svalue)) || (modelValues != null && modelValues.ToString().Contains(svalue)))
                {
                    builder.Attributes.Add("checked", null);
                }
    
                literal.Append(String.Format("</br>{1}&nbsp;<span>{0}</span>", svalue.Replace('_', ' '),builder.ToString(TagRenderMode.Normal)));
            }
    
            return (HtmlString)htmlHelper.Raw(literal.ToString()); 
        }
    
        private static string GetPropertyName<T, TProperty>(Expression<Func<T, TProperty>> propertySelector)
        {
            var body = propertySelector.Body.ToString();
            var firstIndex = body.IndexOf('.') + 1;
            return body.Substring(firstIndex);
        }
    

    HTML:

    @Html.CheckboxGroup(m => m.CreditCards, typeof(VendorCertification.Enums.CreditCardTypes))
    

    Use this if helper extensions scare you:

                <input id="CreditCards" name="CreditCards" type="checkbox" value="Visa" 
                @(Model.CreditCards != null && Model.CreditCards.Contains("Visa") ? "checked=true" : string.Empty)/>
                &nbsp;<span>Visa</span><br />
    
                <input id="CreditCards" name="CreditCards" type="checkbox" value="MasterCard" 
                @(Model.CreditCards != null && Model.CreditCards.Contains("MasterCard") ? "checked=true" : string.Empty)/>
                &nbsp;<span>MasterCard</span><br />
    
    0 讨论(0)
  • 2021-02-01 07:31

    You could enrich your view model:

    public class VendorAssistanceViewModel
    {
        public string Name { get; set; }
        public bool Checked { get; set; }
    }
    
    public class ContactViewModel
    {
        public ContactViewModel()
        {
            VendorAssistances = new[]
            {
                new VendorAssistanceViewModel { Name = "DJ/BAND" },
                new VendorAssistanceViewModel { Name = "Officiant" },
                new VendorAssistanceViewModel { Name = "Florist" },
                new VendorAssistanceViewModel { Name = "Photographer" },
                new VendorAssistanceViewModel { Name = "Videographer" },
                new VendorAssistanceViewModel { Name = "Transportation" },
            }.ToList();
        }
    
        [Required]
        public string Name { get; set; }
    
        [Required]
        public string Phone { get; set; }
    
        [Required]
        [DataType(DataType.EmailAddress)]
        public string Email { get; set; }
    
        [Required]
        public string Subject { get; set; }
        public IEnumerable<SelectListItem> SubjectValues
        {
            get
            {
                return new[]
                {
                    new SelectListItem { Value = "General Inquiry", Text = "General Inquiry" },
                    new SelectListItem { Value = "Full Wedding Package", Text = "Full Wedding Package" },
                    new SelectListItem { Value = "Day of Wedding", Text = "Day of Wedding" },
                    new SelectListItem { Value = "Hourly Consultation", Text = "Hourly Consultation" }  
                };
            }
        }
    
        public IList<VendorAssistanceViewModel> VendorAssistances { get; set; }
    }
    

    Controller:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View(new ContactViewModel());
        }
    
        [HttpPost]
        public ActionResult Index(ContactViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }
    
            //Send email logic
            return RedirectToAction("ContactConfirm");
        }
    }
    

    View:

    @using (Html.BeginForm())
    {
        <div id="ContactContainer">
            <div><span class="RequiredField">*&nbsp;</span>Your Name:</div>
            <div>
                @Html.TextBoxFor(model => model.Name)
            </div>
            <div><span class="RequiredField">*&nbsp;</span>Your Phone:</div>
            <div>
                @Html.TextBoxFor(model => model.Phone)
            </div>
            <div><span class="RequiredField">*&nbsp;</span>Your Email:</div>
            <div>
                @Html.TextBoxFor(model => model.Email)
            </div>
            <div>Subject:</div>
            <div> 
                @Html.DropDownListFor(model => model.Subject, Model.SubjectValues)
            </div>
            <div>Vendor Assistance:</div>
            <div>
                @for (int i = 0; i < Model.VendorAssistances.Count; i++)
                {
                    <div>
                        @Html.HiddenFor(x => x.VendorAssistances[i].Name)
                        @Html.CheckBoxFor(x => x.VendorAssistances[i].Checked)
                        @Html.LabelFor(x => x.VendorAssistances[i].Checked, Model.VendorAssistances[i].Name)
                    </div>
                }
            </div>
            <div>
                <input id="btnSubmit" type="submit" value="Submit" />
            </div>
        </div>
    }
    
    0 讨论(0)
提交回复
热议问题