I would like to pass the item list for a drop-down list into a strongly-typed partial view. The parent view uses a ViewModel class that contains the properties both for the value I want to set and the list of options the associated drop-down list should contain.
My ViewModel looks like:
public class EntityFormViewModel
{
private MyDBEntity Entity { get; set; }
// *** The list of options. ***
public SelectList DataTypeSelectList { get; private set; }
public int EntityId { get; set; }
public byte FormatId { get; set; }
// *** The property the options relate to. ***
[UIHint("DataTypesDropDownST")]
public string DataType { get; set; }
// Other properties snipped...
public EntityFormViewModel(EntityModel db, int Id)
{
Entity = db.MyDBEntity.First(e => e.EntityId == Id);
DataTypeSelectList = new SelectList(db.SDDS_DataType.ToList(), "DataType", "Description", this);
EntityId = Entity.EntityId;
FormatId = Entity.FormatId;
DataType = Entity.DataType;
// Etc ...
}
public void Update(EntityModel db)
{
Entity.EntityId = EntityId;
Entity.FormatId = FormatId;
Entity.DataType = DataType;
// Etc ...
db.SaveChanges();
}
};
My partial view in EditorTemplates/DataTypesDropDown.ascx looks like
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcApp.Controllers.EntityFormViewModel>" %>
<!-- Doesn't work. -->
<%= Html.DropDownListFor(m => Model, Model.DataTypeSelectList) %>
<!-- Doesn't work either. -->
<!-- <% Html.DropDownListFor(m => Model, Model.DataTypeSelectList); %> -->
And my parent view looks like
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApp.Controllers.EntityFormViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Edit
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Edit</h2>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<%: Html.EditorFor(m => m) %>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
I can get it to work fine without strong typing by passing the list of items in the ViewData dictionary, thus:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%: Html.DropDownList("", new SelectList(ViewData["DataTypes"] as IEnumerable, "DataType", "Description", Model)) %>
but I get the following error with strong typing:
The model item passed into the dictionary is of type 'System.String', but this dictionary requires a model item of type 'MvcApp.Controllers.EntityFormViewModel'.
It looks like the wrong type (a string) is being passed into the partial view, but what can I do to change the type I pass? Or is my approach completely wrong? If so, how should it be done? I imagine this is a very common scenario.
I know I should use a "repository" class for database access, but I want to get this working before building too much other stuff around it. Note my ViewModel is in the controllers namspace. I guess I should move it to the Model namespace, but I doubt that's the cause of my problem.
=================================================================================
UPDATE
I still have a problem, but at least I solved the compiler error. I changed the view model as follows
// Make this private
private string DataType { get; set; }
// Add this which supplies all the list information.
[UIHint("DataTypesDropDownST")]
public DataTypeOptsAndVal DataTypeAndOpts
{
get { return new DataTypeOptsAndVal(DataType, DataTypeSelectList); }
set { DataType = value.DataType; }
}
The idea being derived from the fact the return value of the property controls the type passed into the partial view; the whole model is not passed, which was my earlier mistake. Therefore, I return a type that contains everything the partial view needs. The new partial view is
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcApp.Controllers.DataTypeOptsAndVal>" %>
<%: Html.DropDownListFor(m => m.DataType, Model.DataTypeSelectList) %>
However, the form now renders with this field completely absent. I tried including static text in the partial view, but even this was not rendered.
Any help appreciated. Surely it isn't that hard to strongly type a list of options?