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?

2
  • google search gave me this; not sure if it's exactly what you need, but should give you an idea of what you need to do Commented Jun 23, 2016 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 Commented Jun 23, 2016 at 12:01

2 Answers 2

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
Sign up to request clarification or add additional context in comments.

Comments

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

1 Comment

Or use @Html.CheckBoxFor with view model yes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.