Having returned to this problem after a few months I\'ve added my current best answer below.
In the original question I was still looking for a simple way to achieve a g
There is a way to create a generic DropDown which I've mangled together from a few pointers on StackOverflow and this article on CodeProject. Comments on whether this follows best practice would be appreciated.
I use both an AddList and an EditList to allow for a selected item on the EditList and some jQuery based on html class attributes. The generic EditList is created as follows:
I have a viewmodel for any DropDown that fits with the generic pattern and then a ViewModel for the entity I'm returning. Annotations are held in a validation file.
public class DropDownViewModel
{
public IEnumerable Items { get; set; }
}
public partial class OrganisationEditViewModel
{
public int entityID { get; set; }
public string entityName { get; set; }
public DropDownViewModel entityTypeID { get; set; }
public string notes { get; set; }
}
[MetadataTypeAttribute(typeof(OrganisationEditViewModelMetaData))]
public partial class OrganisationEditViewModel
{
}
public class OrganisationEditViewModelMetaData
{
[Key]
[ScaffoldColumn(false)]
[HiddenInput(DisplayValue = false)]
public int entityID { get; set; }
[Required]
[Display(Name = "Organisation")]
public string entityName { get; set; }
[Required]
[Display(Name = "Entity Type")]
[UIHint("_dropDownEdit")]
public DropDownViewModel entityTypeID { get; set; }
[Display(Name = "Notes")]
public string notes { get; set; }
}
The UIHint annotation on the ViewModel points to an Editor Template. I'm using chosen.js on my lookups, hence the html attributes.
@model WhatWorks.ViewModels.DropDownViewModel
@Html.DropDownList("", Model.Items, new { @class = "chosen chosenLookup" })
The controller queries the current entity to get the selected string for the EditList. The DropDown is called from the GetEditList
function in the repository. The ViewModel is then mapped via Automapper (GetUpdate(id)
).
public ActionResult Edit(int id = 0)
{
var query = _repo.GetByID(id);
string selected = query.tEntityType.entityTypeID.ToString();
DropDownViewModel entityType = new DropDownViewModel
{
Items = _repo.GetEditList("entityType", "entityTypeID", selected)
};
OrganisationEditViewModel a = GetUpdate(id);
a.entityTypeID = entityType;
if (a == null)
{
return HttpNotFound();
}
return View(a);
}
The generic DropDown repository method gets an IEnumerable
set of data from the calling type
(tEntityType
in this case). The return
method converts everything into strings and checks for the selected item.
//generic Edit dropdown
public IEnumerable GetEditList(string text, string value, string selected)
where O : class
{
IEnumerable result = context.Set();
var query = from e in result
select new
{
Value = e.GetType().GetProperty(value).GetValue(e, null),
Text = e.GetType().GetProperty(text).GetValue(e, null)
};
return query.AsEnumerable()
.Select(s => new SelectListItem
{
Value = s.Value.ToString(),
Text = s.Text.ToString(),
Selected = (selected == s.Value.ToString() ? true : false)
});
}
Finally, the view renders the DropDown via a standard Html.Editor
which picks up the Editor Template from the UIHint
annotation on the validation file.