1

From reading many tutorials on how to set up drop down menus on various sites I've managed to piece a few things together but am still stuck.

I've been told that my code below should be contained in a View Model, currently it is at the top of my View:

var genderItems = new List<ListItem> 
    { 
          new ListItem { Text = "Unisex", Value = "0" }, 
          new ListItem { Text = "Female", Value = "1" },
          new ListItem { Text = "Male", Value = "2" } 
    };

var statusItems = new List<ListItem> 
    { 
          new ListItem { Text = "Inactive", Value = "0" }, 
          new ListItem { Text = "Active", Value = "1" }
    };

In the same View I have been using this code to generate a drop down box:

@Html.DropDownList("RoomGender", new SelectList(genderItems, "Value", "Text", Model.RoomGender))

Could somebody please explain how I am supposed to abstract this and then pass it to the view without removing the already attached Room model which I have, as that is the Model which models the data for the database.

This is probably quite simple and I have tried researching it, but I really am struggling to piece it all together.

Jamie Street
  • 1,527
  • 3
  • 14
  • 32
  • 1
    You could have used Enum for showing Gender – Aritra B Nov 25 '13 at 16:24
  • I tried using Enums a few days ago for drop downs, had everything storing to the server fine but struggled with the selected values for drop down elements. – Jamie Street Nov 25 '13 at 16:33
  • For your confusion regarding Model and viewModel you can check out this one http://stackoverflow.com/questions/4061440/asp-net-mvc-model-vs-viewmodel and for using enum part I will add some code! – Aritra B Nov 25 '13 at 16:36
  • 1
    http://coding-in.net/asp-net-mvc-3-method-extension/ should help with enum binding – levelnis Nov 25 '13 at 16:37

3 Answers3

3

This is one is for binding Enum Gender to your view. Suppose Student is the Model that I am binding to the View,

namespace MyApp.Models
{
    public class Student 
    {
            public int Id { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public Gender Gender { get; set; }
    }

    public enum Gender 
    { Male = 0, Female = 1 }
}

and then in your View

@Html.DropDownListFor(model => model.Gender, new SelectList(Enum.GetValues(typeof(MyApp.Models.Gender))))

I hope you get it now!

Aritra B
  • 1,726
  • 6
  • 29
  • 45
  • Thank you for your explanation, would it be correct to use this same `Student` class to attach a `DbContext` `DbSet` to? – Jamie Street Nov 25 '13 at 16:58
  • Yes you can have this in your DbContext class. – Aritra B Nov 25 '13 at 17:14
  • As these enums will be used in multiple places should I really be creating separate enum class files for them? Will this effect the way they are accessed with the drop down in the view? Also does this pick out the default selected gender? – Jamie Street Nov 25 '13 at 17:33
  • If you can see from above, I have created an enum called Gender which can be accessed from multiple places and yes the default value for an enum is always zero. In this case it has been set to Male, you can change it to set Female as default by assigning it 0. – Aritra B Nov 25 '13 at 17:44
  • Sorry I meant if I receive a Student back from the database where its stored as 1 (Female) would my view automatically pick up that the drop down box needs to select Female when generating the html? – Jamie Street Nov 25 '13 at 17:57
  • I dont know how to answer this one..it depends on the way you are coding. If you are using scaffold template MVC controller with read/write actions then VS will take care of it and yes, the saved object will be returned along with the selected gender value at the time of creating that particular object. You can test it out yourself. – Aritra B Nov 26 '13 at 06:20
1

Isn't this Room model already your view model? A view model is simply a class that contains the data that your view requires. Convention has it that they tend to be called view models to separate them from domain models. In your case, you could either add a couple of properties to Room for StatusItems and GenderItems. Alternatively, create a RoomViewModel with a property Room and the 2 list properties and pass that to the View instead.

Ideally you would create a RoomViewModel and create properties for all of the data that you need to display within your view. This doesn't need to match the structure of your domain objects. In you MVC layer, you would take the domain objects that you retrieve the data from for your view, and map those properties across during view model creation. You can either do this manually or using a tool like Automapper.

levelnis
  • 7,665
  • 6
  • 37
  • 61
  • So say for example I'm using `Room` and `Bunk` classes (which I've migrated to the database), are those my domain models? When generating the controller I set the `Room` class as my model, should I have created another class to act as a type of wrapper around my domain model? – Jamie Street Nov 25 '13 at 16:23
  • Updated my answer with a bit more detail. Does that help? – levelnis Nov 25 '13 at 16:25
  • That does help! Although I am a little confused how an automatically generated controller using EF5 (creating index, create, detail, edit, delete) will be able to store things to the database if I have a `RoomViewModel` sat in the middle? – Jamie Street Nov 25 '13 at 16:37
  • @JamieShanikwaStreet: you "map" the `RoomViewModel` back to the `Room` and vice-versa. You can do this manually, simply by setting each property to the respective property on the other model or use something like AutoMapper (http://automapper.org/) – Chris Pratt Nov 25 '13 at 16:41
  • Is there any chance I could show either of you what code I have in my project and the full architecture I've constructed. I think I've got myself into a bit of a mess :( – Jamie Street Nov 25 '13 at 16:50
  • By all means post some more of the code that you're having problems with. Try to ensure that you just post the relevant parts – levelnis Nov 25 '13 at 22:21
0

In order to get the dropdown list data to the view, I would suggest adding the data to the ViewBag.

You can see an example of this here: http://jnye.co/Posts/12/creating-cascading-dropdownlists-using-mvc-4-and-jquery

First add the values to your ViewBag. Typically i put this in it's own method as it needs to be called each time the page is loaded (including, when being displayed on a failed form subission):

//You can keep your current list setup, I have simply shortened it for brevity
var genderItems = new List<string> {"Unisex", "Female", "Male"};
ViewBag.Genders = new SelectList(genderItems);

Then in your view:

@Html.DropDownList("gender", ViewBag.Genders as SelectList)

Or if you want to bind the result to a property on your view model:

@Html.DropDownListFor(m => m.Property, ViewBag.Genders as SelectList)
NinjaNye
  • 7,046
  • 1
  • 32
  • 46
  • Why use ViewBag when the OP is already using a view model? How are you proposing to unit test that? – levelnis Nov 25 '13 at 17:55
  • Given the OP is talking about drop down lists I think we can assume the view model is used to define data going to and from the server. The options within a dropdownlist are additional data that the view requires to render, and should not be sent back to the server with every form submission, nor should the viewmodel be altered to accommodate this view data, this is the point of `ViewData` (which `ViewBag` wraps). The `ViewBag` is there to be used in conjuction with the a viewmodel so the fact the OP is already using a view model is not an issue, but in fact, expected, in my opinion. – NinjaNye Nov 25 '13 at 18:11
  • I don't want this to turn into a `ViewBag` vs `ViewModel` debate as that's been done to death, but the dropdownlist options don't get posted back to the server each time. Only the selected value gets posted back. Encapsulating all the data that a view requires within a `ViewModel` specific to that view makes it very clear which data is required. In order to highlight the data required for display rather than postback, I favour a `ViewModel` for display and an equivalent `Command` for posting back to the server. The `Command` doesn't require the options Lists, merely the selected value. – levelnis Nov 25 '13 at 22:18