I have found couple questions about my problem but none of them actually addresses the problem and gives alternative solutions to problem, thats why I am asking this again.
I am using strongly typed HTML Helpers and no ViewData and ViewBag for only page titles.
Here is my problem.
I have following viewmodel.
public class RegisterViewModel
{
public string Mail { get; set; }
public string Name { get; set; }
public ThreePartDatePickerViewModel ThreePartDateSelection { get; set; }
public RegisterViewModel()
{
ThreePartDateSelection = new ThreePartDatePickerViewModel();
}
}
Above viewmodel uses below viewmodel which basically holds data for 3 dropdownlist which are Day, Month and Year.
public class ThreePartDatePickerViewModel
{
public string Day { get; set; }
public string Year { get; set; }
public string Month { get; set; }
public IList<SelectListItem> Years { get; set; }
public IList<SelectListItem> Months { get; set; }
public IList<SelectListItem> Days { get; set; }
public ThreePartDatePickerViewModel()
{
var now = DateTime.Now;
Years = new List<SelectListItem>();
Months = new List<SelectListItem>();
Days = new List<SelectListItem>();
var empty = new SelectListItem { Text = "" };
Years.Add(empty);
Months.Add(empty);
Days.Add(empty);
foreach(var item in Enumerable.Range(0, 100).Select(x => new SelectListItem { Value = (now.Year - x).ToString(), Text = (now.Year - x).ToString() }))
Years.Add(item);
foreach(var item in Enumerable.Range(1, 12).Select(x => new SelectListItem { Value = x.ToString(), Text = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(x) }))
Months.Add(item);
foreach(var item in Enumerable.Range(1, 31).Select(x => new SelectListItem { Value = x.ToString(), Text = x.ToString() }))
Days.Add(item);
}
}
In the action method which returns RegisterViewModel
to view, I am setting the Day,Month and Year properties of ThreePartDatePickerViewModel
.
I have checked these values on runtime while views are generated and they are correct.
In my main view,
@model Bla.Bla.RegisterViewModel
<!-- Helpers for other properties -->
@Html.EditorFor(m => m.ThreePartDateSelection)
And my ThreePartDatePickerViewModel Editor Template is
@model Bla.Bla.ThreePartDatePickerViewModel
<div class="threePartDatePicker">
@Html.DropDownListFor(m => m.Day, Model.Days)
@Html.DropDownListFor(m => m.Month, Model.Months)
@Html.DropDownListFor(m => m.Year, Model.Years)
</div>
In my final rendered html, I have all the controls as expected. Dropdowns are rendered fine except the values I have set in action method are not selected.
If I switch from EditorTemplates to Partial Views, It starts working. Or If directly render dropdownlists inside my main view, instead of passing model to EditorFor, It again works.
It seems an old bug, not solved yet. it is reported here.
http://connect.microsoft.com/VisualStudio/feedback/details/654543/asp-net-mvc-possible-mvc-bug-when-working-with-editortemplates-and-drop-down-lists#details
I have to edit the editor template to set selected value as,
@{
//capture the selected list wherever it is. Here it passed in additionalViewData
SelectList tmpList, list = null;
ViewContext.ViewData.TryGetValue("list", out tmpList);
if (tmpList != null && tmpList.Count() > 0 && tmpList.SelectedValue == null)
{
list = new SelectList(tmpList, "Value", "Text", Model);
}
else
{
list = tmpList;
}
}
<div class="form-group">
@Html.DropDownListFor(m => m, list, attributes)
</div>
so I can work with select list in Editor Template as default behavior it should be.
I'm experiencing the same issue using a dropdownlist in an editor template. The selected value is not set even though I can see the correct value in the model. This is my workaround. It could be extended to work with other DropdownListFor
methods.
public static class HtmlHelperExtensions
{
public static IHtmlString EditorDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string optionLabel)
{
var dropDown = SelectExtensions.DropDownListFor(htmlHelper, expression, selectList, optionLabel);
var model = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).Model;
if (model == null)
{
return dropDown;
}
var dropDownWithSelect = dropDown.ToString().Replace("value=\"" + model.ToString() + "\"", "value=\"" + model.ToString() + "\" selected");
return new MvcHtmlString(dropDownWithSelect);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With