Boy Pasmo
Boy Pasmo

Reputation: 8501

dropdownlistfor not selecting what's supposed to be selected upon page load

I have this helper. Now, this isn't mine. This is for displaying and populating the dropdown.

public static IEnumerable<SelectListItem> ToSelectList<T, TTextProperty, TValueProperty>(this IEnumerable<T> instance, Func<T, TTextProperty> text, Func<T, TValueProperty> value, Func<T, bool> selectedItem = null)
        {
            return instance.Select(t => new SelectListItem
            {
                Text = Convert.ToString(text(t)),
                Value = Convert.ToString(value(t)),
                Selected = selectedItem != null && selectedItem(t)
            });
        }

Then I have these classes:

public class FooVm {
  public FooVm() {
    Bars = new HashSet<BarVm>();
  }

  public int FooId { get; set; }
  public IEnumerable<BarVm> Bars { get; set; }
}

public class BarVm {
  public int BarId { get; set; }
  public int BarName { get; set; }
}

Then having this Linq Query:

var fooBar = _db.Foo
                .WithId(fooId)
                .Select(f => new FooVm {
                  FooId = f.Id,
                  Bars = f.Bars.Select(b => new BarVm {
                    BarId = b.Id,
                    BarName = b.Name
                  })
                })
                .ToList();

ViewBag.Bars = _db.Bars
                  .ToSelectList(s => s.Name, s => s.Id);

Then when I try to render these result for editing/updating.

@model ViewModels.Foo.FooVm

@Html.LabelFor(model => model.FooId)
@foreach(var item in Model.Bars) {
  @Html.DropDownListFor(model => item.BarId, ViewBag.Bars as IEnumerable<SelectListItem>, "Select bar")
}

The dropdown is rendering fine but it isn't selecting of what's supposed to be selected upon page load.

What am I missing? Any help would be much appreciated. Thanks

Upvotes: 1

Views: 774

Answers (1)

Judge Bread
Judge Bread

Reputation: 501

Your helper method takes up to 3 parameter but you are only supplying two. The third parameter allows you to set the selected Item by default this will be 'null'. See below for example.

ViewBag.Bars = Model.Bars.ToSelectList(s => s.BarName, s => s.BarId, s => s.BarId == 1);

EDIT

Try this, but since I don't understand your premise or what you are really trying to achieve this is just something to guide you.

public static MvcHtmlString DropDownListFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression,
                                               IEnumerable<SelectListItem> selectList, string selectedValue, string optionLabel, object htmlAttributes)
    {
        Func<TModel, TValue> method = expression.Compile();
        string value = method(helper.ViewData.Model) as string;

        if (string.IsNullOrEmpty(value) && selectList != null)
        {
            var selectListList = selectList.ToList();
            var selectedItem = selectListList.FirstOrDefault(s => s.Selected);
            if (selectedItem == null)
            {
                var itemToSelect = selectListList.FirstOrDefault(w => w.Value == selectedValue);
                if (itemToSelect != null)
                {
                    itemToSelect.Selected = true;
                }
            }
            return helper.DropDownListFor(expression, selectListList, optionLabel, htmlAttributes);
        }

        return helper.DropDownListFor(expression, selectList, optionLabel, htmlAttributes);
    }

Use like this.

@Html.DropDownListFor(model => item, ViewBag.Bars as IEnumerable<SelectListItem>, item.BarId.ToString(), "Select bar", new object())

Test this thoroughly as this is just a quick prototype to show you how you can create the helper on your own.

The selected value can be overridden if you use the first answer as the Selected property of the SelectListItem will be true.

Upvotes: 1

Related Questions