LA.NET [EN]

Jan 30

Today we’ll keep looking at the helpers and see how we can add dropdowns and listboxes to our views. As you might expect, there are some helper methods that render the corresponding SELECT HTML element. They’re adequately named DropDownList and ListBox and,as you might expect, you’ll find several overloads of each. The main difference between then is that with the ListBox you’ll be able to select several items simultaneously. Here’s some demo code that shows how to create and fill the lists which will be shown on the page:

<%= Html.DropDownList(
                    "optionsDrop",
                     new []
                         {
                                 new SelectListItem
                                     {
                                             Text = "Option 1",
                                             Value = "opt1"
                                     },
                                  new SelectListItem
                                     {
                                             Text = "Option 2",
                                             Value = "opt2"
                                     },
                                  new SelectListItem
                                     {
                                             Text = "Option 3",
                                             Value = "opt3"
                                     }
                },
               "Choose an option"  
             ) %>
<br />
<%= Html.ListBox(
                    "optionsList",
                     new []
                         {
                                 new SelectListItem
                                     {
                                             Text = "Option 1",
                                             Value = "opt1"
                                     },
                                  new SelectListItem
                                     {
                                             Text = "Option 2",
                                             Value = "opt2"
                      &#16 0;              },
                                  new SelectListItem
                                     {
                                             Text = "Option 3",
                                             Value = "opt3"
                                     }
                },
               "Choose an option"  
             ) %>

Since this is demo code and my main objective is to show you how you can render a dropdown, I’ve just created some dumb SelectListItems to fill the list of items displayed by the HTML SELECT element generated by the helpers. In the “real world” you’d probably have a collection of items that you’d want to show in a dropdow or in a listbox. In those cases, you’d be encouraged to perform the transformation from the custom items in that collection into the SelectListItems in the  controller.

Going back to the example, I’d like to mention that the SelectListItem class is a simple class which exposed three properties:

  • Text: used for setting the text of the OPTION element contained in the dropdown or listbox;
  • Value: used for  defining the value of the OPTION element used for representing a rendered entry;
  • Selected: boolean property that indicates if an item is selected.

Btw, in the previous snippet, we’re using one of the overloads which receives an optional string label. This label is added to the items on the list without a specified value (ie, the string you passed for the label parameter is converted into a SelectListItem with an empty string Value and with the Selected property set to false – oh, and yes, with its Text property set to the text you’ve passed through the label parameter). As you’ve seen in some of the previous posts, you also have overloads that let you specify the html attributes you want to set up on the generated HTML element.

More interestingly, you can make the dropdown or listbox render automatically the items passed from the controller through the ViewData property (which is really what you want when you have a custom collection which the controller converts into SelectListItems as I’ve suggested above). You have 2 options:

  • if you use the dictionary approach without a “strongly typed” view, you’ll need to have an entry on the ViewData dictionary with the same name as the one that is passed to the name parameter of the DropDownList or ListBox  methods you’re calling;
  • if you’re using a “strongly typed” view, then you need to guarantee that the object that is passed to the view has one property with the same name as the name you’ve passed to the DropDownList (or ListBox) method you’re invoking.

So, if you’re using approach 1, you need to have something like this in your action method:

ViewData["optionsDrop"] = new[] {
                new SelectListItem
                    {
                            Text = "Option 1",
                            Value = "opt1"
                    },
                new SelectListItem
                    {
                            Text = "Option 2",
                            Value = "opt2"
                    },
                new SelectListItem
                    {
                            Text = "Option 3",
                            Value = "opt3"
                    }
        };
//the code is similar for the ListBox method

Notice that I’m passing the same name as the one that is passed to the DropDownList/ListBox method in the previous example! In scenario 2, you’d start by having a class. Here’s the quickest one I could build:

public class Dto    {
      public IEnumerable<SelectListItem> optionsDrop {
          get {
              return new[] {
                                                new SelectListItem
                                                     {
                                                            Text = "Option 1",
                                                            Value = "opt1"
                                                    },
                                                new SelectListItem
                                                    {
                                                            Text = "Option 2",
                                                            Value = "opt2"
                                                    },
                                                new SelectListItem
                                                    {
                                                            Text = "Option 3",
                                                            Value = "opt3"
                                                    }
                                        };
          }
      }

      public IEnumerable<SelectListItem> optionsList {
          get {
             //similar to the other property…
          }
      }
}

And then you could reduce the method call in your pages to this:

<%= Html.DropDownList(
                    "optionsDrop",
                     "Choose an option"  
             ) %>
<br />
<%= Html.ListBox(
                    "optionsList" 
             ) %>

And that’s it! The dropdown and listbox controls will automatically get the correct SelectListItem from the ViewState initialized by the controller. Interestingly, there’s not an overload for the ListBox method that lets you pass a name and a value for the label (I don’t know what’s the rationale behind that decision, but if you need that additional entry and you want to pass the SelectListItems from your controller, then you’ll need to add that default entry to the list that is passed from the controller). Do keep in mind that you’ll only get this automatic hookup if you don’t pass a valid collection of SelectListItem elements to the helper methods!

If you’re curious, then you’d probably like to know that the assembly of the HTML returned by each of the methods is done by a private method called SelectInternal. There’s also another important helper called GetSelectData which is called when you don’t pass a collection of SelectListItems explicitly to these methods (ie, this method tries to get the SelectListItem collection from the ViewState passed from the controller). The code for these private methods is really simple, so I’ll leave it to you to explore it.

And that’s all for today. Keep tuned because there’s more to come about MVC.

3 comments so far

  1. DW
    9:44 pm - 7-13-2009

    First example is great second one I get this error

    “There is no ViewData item with the key ”optionsDrop” of type ”IEnumerable””

    probably a stupid error but it doesn”t seem to be covered in the tutorial.

  2. luisabreu
    9:48 pm - 7-13-2009

    Hello. Are you using a strongly typed view?

  3. DW
    9:51 pm - 7-13-2009

    Scenario #2 as written throws an error, is something missing

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>