0

I have created a class for that is used to create a reusable dropdown on create/edit views:

  public class TimeDropDowns
    {
        public static int SelectedHour{ get; set; }
        public static List<SelectListItem> hours = new List<SelectListItem>()
                {
                    new SelectListItem() {Text="9", Value="09"},
                    new SelectListItem() {Text="10", Value="10"},
                    new SelectListItem() {Text="11", Value="11"},
                    new SelectListItem() {Text="12", Value="12"}
                };

    }

I am able to display the dropdown 2 ways:

1) in a view @Html.DropDownList("hour", TimeDropDowns.hours, htmlAttributes: new { @class = "form-control" })

2) setting using viewbag in controller ViewBag.hours = TimeDropDowns.hours; and then referencing in view @Html.DropDownList("hours", null, htmlAttributes: new { @class = "form-control" })

But I haven't been able to set the selected value using either approach, suggestions?

Joe Riggs
  • 1,312
  • 4
  • 23
  • 48

3 Answers3

1

The class SelectListItem has a property called Selected. It's type is bool. When this property for an item is true, then it's value is selected.

That being said you need something like this:

public class TimeDropDowns
{
    public static List<SelectListItem> GetHoursDropDown(int? selectedHour = null)
    {
        var items = new List<SelectListItem>();
        for(var hour=9; hour<=12; hour++)
        {
            var hourStr = hour.ToString();
            var item = new SelectListItem 
            {
                Text = hourStr, 
                Value = hour < 9 ? "0"+hourStr : hourStr, 
                Selected = selectedHour.HasValue && selectedHour == 9
            }
            items.Add(item);
        }
        return items;
    }
}

Then you could use this as below:

ViewBag.hours = TimeDropDowns.GetHoursDropDown(11);

If you want the selected hour to be the 11th or like:

ViewBag.hours = TimeDropDowns.GetHoursDropDown();

if you want none of them to be selected.

The place of 11, when you post your form, would be taken by the value you post, hour. Apparently this value should be parsed first and the you will pass it to the GetHoursDropDown method.

I strongly encourage you, as already Win have mentioned correctly in his post, to avoid the use of ViewBag and create a strongly type view model.

Christos
  • 53,228
  • 8
  • 76
  • 108
1

You need to set DropDownList as SelectedHour instead of hours, so that ModelBinder can bind the selected value to SelectedHour when form is posted back to server.

@Html.DropDownList("SelectedHour", ...)

I personally like to use Strongly Typed Model. You can read more here.

Community
  • 1
  • 1
Win
  • 61,100
  • 13
  • 102
  • 181
  • I already have a model, should I add a 2nd just for this? I am using several dropdowns to create a datetime value in the model – Joe Riggs Mar 10 '17 at 14:07
  • I am using it for the date, but I also need hours and minutes, which is what I am creating these dropdowns for – Joe Riggs Mar 10 '17 at 14:26
  • For date time, you can use Kendo UI's [DateTime Picker](http://demos.telerik.com/kendo-ui/datetimepicker/index). You just add one line of jQuery code `$("#datetimepicker").kendoDateTimePicker();`, and you are done. Beside, kendo DateTime Picker is part of [Open Source and Free HTML5 Framework](http://www.telerik.com/kendo-ui/open-source-core). – Win Mar 13 '17 at 16:39
0

Thanks to the feedback of the 2 responders I have decided that creating a strongly typed model was the best approach. Since my model was generated from the db I needed to create a partial class so that I would not lose changes if db model refreshed. I created the partial class which is a type of my model class

namespace TouchScreenEvents
{
    [MetadataType(typeof(TouchScreenEventMetadata))]
    public partial class TouchScreenEvent
    {
        public string selectedHour { get; set; }
        public  List<SelectListItem> hours = new List<SelectListItem>()
            {
                new SelectListItem() {Text="9a", Value="09"},
                new SelectListItem() {Text="10a", Value="10"},
                new SelectListItem() {Text="11a", Value="11"},
                new SelectListItem() {Text="12p", Value="12"},
                new SelectListItem() {Text="1p", Value="13"},
                new SelectListItem() {Text="2p", Value="14"},
                new SelectListItem() {Text="3p", Value="15"},
                new SelectListItem() {Text="4p", Value="16"},
                new SelectListItem() {Text="5p", Value="17"},
                new SelectListItem() {Text="6p", Value="18"},
                new SelectListItem() {Text="7p", Value="19"},
                new SelectListItem() {Text="8p", Value="20"}
            };

        public string selectedMinute { get; set; }
        public List<SelectListItem> minutes = new List<SelectListItem>()
            {
                new SelectListItem() {Text="00", Value="00"},
                new SelectListItem() {Text="30", Value="30"}
            };
    }
}

To set the selected index in the controller I have this code (unnecessary parts removed)

//get edit touchscreen event
TouchScreenEvent touchScreenEvent = await db.TouchScreenEvents.FindAsync(id);
var d = touchScreenEvent.date;
touchScreenEvent.selectedMinute= d.ToString("mm");
touchScreenEvent.selectedHour = d.ToString("HH");

And the view code, with previously selected value set. This will also work without the selected index being set - in the create view for instance

 @Html.DropDownListFor(model => model.selectedHour, Model.hours, htmlAttributes: new { @class = "form-control" })
 @Html.DropDownListFor(model => model.selectedMinute, Model.minutes, htmlAttributes: new { @class = "form-control" })

When posted back to the controller I can access the values like this

touchScreenEvent.selectedHour, touchScreenEvent.selectedMinute
Joe Riggs
  • 1,312
  • 4
  • 23
  • 48
  • It looks great. My only suggestion will be to use ***PascalCasing*** for ***Public Properties***. You can read more at [.Net Naming Guidelines](https://msdn.microsoft.com/en-us/library/ms229012(v=vs.110).aspx#Anchor_1). – Win Mar 14 '17 at 21:55