2

Forgive my ignorance. Not done a lot of MVC work, and I'm sure there must be a better way to do this but I can't seem to find it. I have a Flags enum like this:

[Flags]
public enum Services
{
    Foo = 1,
    Bar = 2,
    Meh = 4
}

And a SelectedServices property on my Model which has a value of this type. In the View, I have a checkbox for each possible service. I have implemented the binding logic like so:

<div><label><input type="checkbox" name="services" value="@((int)Services.Foo)" 
@if(Model.SelectedServices.HasFlag(Services.Foo))
{
    <text>checked</text>
}
 />Foo</label></div>

<div><label><input type="checkbox" name="services" value="@((int)Services.Bar)" 
@if(Model.SelectedServices.HasFlag(Services.Bar))
{
    <text>checked</text>
}
 />Bar</label></div>

And so on. Which works, but is really horribly messy.

There must, surely be a better way to encapsulate this - but I have no idea what the relevant concept is in MVC?

Bob Tway
  • 9,301
  • 17
  • 80
  • 162
  • google search gave me [this](http://stackoverflow.com/questions/388483/how-do-you-create-a-dropdownlist-from-an-enum-in-asp-net-mvc); not sure if it's exactly what you need, but should give you an idea of what you need to do – The Bearded Llama Jun 23 '16 at 11:55
  • Create a view model with `bool IsFoo` and `bool IsBar` and `bool IsMeh` then you can use the strongly typed `Html.CheckBoxFor()` method to generate the checkboxes –  Jun 23 '16 at 12:01

2 Answers2

4

You current code would not bind to your enum when you submit the form since it will only be received as an array of values. As always, use a view model to represent what you want to display/edit in a view.

public class MyViewModel
{
    [Display(Name = "Foo")]
    public bool IsFoo { get; set; }
    [Display(Name = "Bar")]
    public bool IsBar { get; set; } 
    [Display(Name = "Meh")]
    public bool IsMeh { get; set; } 
    .... // other properties of your view model
}

and to map the enum value to the view model

model.IsFoo= yourEnumProperty.HasFlag(Type.Foo); // etc

and in the view

@model MyViewModel
....
@Html.CheckBoxFor(m => m.IsFoo)
@Html.LabelFor(m => m.IsFoo)
@Html.CheckBoxFor(m => m.IsBar)
@Html.LabelFor(m => m.IsBar)
....

and finally in the POST method

[HttpPost]
public ActionResult Edit(MyViewModel model)
{
    bool isTypeValid = model.IsFoo || model.IsBar || model.IsMeh;
    if (!isTypeValid)
    {
        // add a ModelState error and return the view
    }
    Services myEnumValue = model.IsFoo ? Services.Foo : 0;
    myEnumValue |= model.IsBar ? Services.Bar : 0;
    myEnumValue  |= model.IsMeh ? Services.Meh : 0;
    // map the view model to an instance of the data model, save and redirect
2

Create razor helper :

@helper DisplayFlagHelper(Services flag)
{
   <div><label><input type="checkbox" name="services" value="@((int)flag)" 
   if(Model.SelectedServices.HasFlag(flag))
   {
       <text>checked</text>
   }
    />@flag</label></div>
}

@DisplayFlagHelper(Services.Foo)

or shared view

borgez
  • 36
  • 1
  • 3