By using the the simple SelectorAttribute and EditorTemplate described in this post, you will get rich support the following very common scenarios (and flip between the various modes with ease):
Say youâre inserting a new Product and need to set the CategoryId property. You make a simple input Model wanting to use EditorFor, but CategoryId gets rendered as a useless textbox. The challenge is:
public class Product
{
[Required]
public string Name { get; set; }
[Required]
[Display(Name = "Category")]
public int? CategoryId { get; set; }
}
The only change from the model above is the new [CategorySelector] attribute on the property.
Since the [CategorySelector] was placed on an int? property, the selector will render in Single-select mode (only one int can be stored into the property). If however, it were a List<int?> property, the selector would render in Multi-select mode, allowing the user to choose more than one int value. I personally find this automatic behavior pretty cool and very helpful!
The screenshot you saw easier is rendered simply by using following Model and EditorFor. The magic lies in the [CategorySelector] and [DisplayModeSelector] attributes.
public class DisplayModeOptions
{
public DisplayModeOptions()
{
ReadOnly = new List<DisplayMode> { DisplayMode.HomePage, DisplayMode.BrowseOnly};
}
[Required]
[Display(Name = "Category")]
[CategorySelector]
public int? CategoryId { get; set; }
[Required]
[DisplayModeSelector(BulkSelectionThreshold = 0)]
public DisplayMode? DropDown { get; set; }
[Required]
[DisplayModeSelector]
public DisplayMode? RadioButtons { get; set; }
[Required]
[DisplayModeSelector(BulkSelectionThreshold = 0)]
public List<DisplayMode> ListBox { get; set; }
[Required]
[DisplayModeSelector]
public List<DisplayMode> CheckBoxes { get; set; }
[ReadOnly(true)]
[DisplayModeSelector]
public List<DisplayMode> ReadOnly { get; set; }
}
<form action="" method="post">
<div class="two-column">
<div class="field-group">
<h4>Single Selection</h4>
@Html.FullFieldEditor(m => m.RadioButtons)
@Html.FullFieldEditor(m => m.DropDown)
@Html.FullFieldEditor(m => m.CategoryId)
</div>
<div class="field-group">
<h4>Multiple Selection</h4>
@Html.FullFieldEditor(m => m.CheckBoxes)
@Html.FullFieldEditor(m => m.ListBox)
</div>
</div>
<input type="submit" value="Save"/>
</form>
Youâll need to create your own SelectorAttributes in order to specify the list of choices that should be displayed to the user.
The DisplayModeSelector displays all possible choices within an enum.
public class DisplayModeSelectorAttribute : SelectorAttribute
{
public override IEnumerable<SelectListItem> GetItems()
{
return Selector.GetItemsFromEnum<DisplayMode>();
}
}
The CategorySelector demonstrates how you might access a database to get a list of items dynamically.
public class CategorySelectorAttribute : SelectorAttribute
{
public CategorySelectorAttribute()
{
// The Category selector should always be rendered as a drop down
BulkSelectionThreshold = 0;
}
public override IEnumerable<SelectListItem> GetItems()
{
// You could of course get these values from a database, similar to:
// var dataContext = DependencyResolver.Current.GetService<IDataContext>();
var categories = new List<Category>
{
new Category {Id = 1, Name = "Beverages"},
new Category {Id = 2, Name = "Tools"},
new Category {Id = 3, Name = "Soup"},
};
return Selector.GetItems(categories, m => m.Id, m => m.Name);
}
}
Rather than pasting the full source here, I will be publishing it along with a sample project at https://mvcgrabbag.codeplex.com
Using TortoiseHg simply clone the URL: https://hg01.codeplex.com/mvcgrabbag
Browse the Selector code, MvcGrabBag.Web/Selectors folder
Â
Leave a Comment