Pubblicato da andrea in MVC il 05 maggio 2010 alle 9.00
Intro
Nelle mie applicazioni faccio largo uso di enums (e chi non lo fa?), mi sono quindi creato una serie di helpers / providers per la gestione della UI bindata con gli enum.
In WebForms utilizzo:
Visto che MVC2 è estendibile ho provato a riportare le funzionalità di base su questa piattaforma.
Questo è il model
public class Movie
{
[Required]
public string Title { get; set; }
public Rating Rating { get; set; }
}
e questo l’enum
public enum Rating
{
None,
Horrible,
Bad,
Poor,
BelowAverage,
Average,
AboveAverage,
Good,
VeryGood,
Superb,
Excellent
}
Sfruttando il nuovo motore di template possiamo scrivere la form di inserimento dati come
<% using (Html.BeginForm()){%>
<%= Html.EditorForModel() %>
<input type="submit" value="Create" />
<%}%>
Il risultato è il seguente:
Decisamente poco user friendly.
Step 1 – gestire le descrizioni tramite attributo
MVC2 utilizza DataAnnotations e l’attributo DisplayNameAttribute per poter impostare una label custom sui controlli. Purtroppo l’attributo DisplayNameAttribute non è utilizzabile direttamente sul singolo valore dell’enum. Bypassiamo il problema creando la nostra versione e cambiando l’AttributeUsage
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field)]
public class EnumDisplayNameAttribute : DisplayNameAttribute
{
public EnumDisplayNameAttribute(string displayName)
:base(displayName)
{
}
}
In questo modo è possibile decorare l’enum
[EnumDisplayName("** Rating")]
public enum Rating
{
None,
Horrible,
Bad,
Poor,
[EnumDisplayName("Below Average")]
BelowAverage,
Average,
[EnumDisplayName("Above Average")]
AboveAverage,
Good,
[EnumDisplayName("Very Good")]
VeryGood,
Superb,
[EnumDisplayName("Just... WOW!")]
Excellent
}
Step 2 – estendere l’enum
Abbiamo bisogno di leggere il valore degli enum e di poter creare una lista di valori da passare al controllo DropDown. Implementiamo entrambe le funzionalità come Extension Methods
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace EnumTemplates.Helpers
{
public static class EnumExtensions
{
public static string GetDisplayName(this Enum enumItem)
{
var mi = enumItem.GetType().GetMember(enumItem.ToString()).FirstOrDefault();
if(mi != null)
{
var dn = (EnumDisplayNameAttribute)(mi.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false)).FirstOrDefault();
if (dn != null)
return dn.DisplayName;
}
return enumItem.ToString();
}
public static IEnumerable<SelectListItem> ToSelectList(this Enum enumItem)
{
var enumType = enumItem.GetType();
return (from object value in Enum.GetValues(enumType)
select new SelectListItem
{
Selected = value.ToString() == enumItem.ToString(),
Text = ((Enum)value).GetDisplayName(),
Value = ((int)value).ToString()
}).ToList();
}
}
}
Step 3 – Creare un template di default per gli Enum
Nella cartella Views\Shared\EditorTemplates creiamo un nuovo usercontrol Enum.ascx
il cui sorgente è il seguente
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Enum>" %> <%@ Import Namespace="EnumTemplates.Helpers" %> <%= Html.DropDownListFor(x => x,Model.ToSelectList()) %>
Step 4 – Abilitare il template per il nostro Enum
Piuttosto che decorare con l’attributo UIHint ogni property del nostro ViewModel (che è un approccio decisamente poco DRY) proviamo a decorare direttamente l’enum Ratings.
Anche in questo caso ci sono limitazioni sull’utilizzo dell’attributo, la soluzione la conosciamo già ;D
using System;
using System.ComponentModel.DataAnnotations;
namespace EnumTemplates.Helpers
{
[AttributeUsage(AttributeTargets.Enum)]
public class EnumUIHintAttribute : UIHintAttribute
{
public EnumUIHintAttribute(string uiHint)
: base(uiHint)
{
}
}
}
a questo punto possiamo definire il nostro enumerativo come
using EnumTemplates.Helpers;
namespace EnumTemplates.Models
{
[EnumDisplayName("** Rating")]
[EnumUIHint("Enum")]
public enum Rating
{
None,
Horrible,
Bad,
Poor,
[EnumDisplayName("Below Average")]
BelowAverage,
Average,
[EnumDisplayName("Above Average")]
AboveAverage,
Good,
[EnumDisplayName("Very Good")]
VeryGood,
Superb,
[EnumDisplayName("Just... WOW!")]
Excellent
}
}
Step 5 – Up & Running
Step fondamentale…. F5 e test nel browser..
e se diamo un’occhiata al sorgente HTML troviamo
decisamente meglio.
Pubblicato da andrea in MVC il 05 maggio 2010 alle 9.00