Credo abbiate intuito che Microsoft sta spingendo molto sul presentare Silverlight3 come la piattaforma per lo sviluppo di RIA applications puntando molto sulle LOB (Line Of Business) Applications, i nuovi .NET RIA Services sono solo un esempio in questa direzione.
Oltre alla mia feature preferita (ChildWindow) in Silverlight3 sono stati aggiunti una serie di controlli nati con lo scopo di alleggerire la parte più noiosa delle LOB, ovvero la presentazione dei dati e relativa interazione con l’utente, tra questi il controllo DataForm.

Supponiamo di avere una classe Person con le classiche proprietà FirstName, LastName etc… e di volerne editare le proprietà.
In Silverlight2, sebbene banale, c’è un pò di lavoro da fare via XAML/VS2010/Blend, in Silverlight3 dopo avere impostato un riferimento a: System.Windows.Controls.Data, System.ComponentModel e System.Data.Annotations e avere trascinato il controllo DataForm nella pagina Silverlight non dobbiamo fare altro che scrivere:

   1: public partial class MainPage : UserControl
   2: {
   3:     public MainPage()
   4:     {
   5:         InitializeComponent();
   6:         DataForm1.CurrentItem = this.CreatePerson();
   7:     }
   8:  
   9:     private Person CreatePerson()
  10:     {
  11:         return new Person() {    FirstName = "Gianfranco", 
  12:                                         LastName = "Rossi", 
  13:                                         Role=Role.Tester,
  14:                                         BirthDate = DateTime.Parse("08/06/1981"), 
  15:                                         EMail = "gr@stupidsoft.it" 
  16:                                     };
  17:     }

per ottenere questo risultato:

image

 

 

Ovviamente quello che vedete è la rappresentazione di default, decorando person con una serie di attributi (la lista è immensa) è possibile personalizzare all’inverosimile le funzionalità del DataForm.

 

 

Andiamo a decorare la classe Person con gli attributi che vedete di seguito:

 

   1: [CustomValidation(typeof(PersonValidator), "ValidatePerson")]
   2: public class Person :IEditableObject
   3: {
   4:    
   5:     ...Fields...
   6:  
   7:     [Display(Name = "Nome", Order = 0, Description = "Nome utente")]
   8:     [Required(ErrorMessage = "Name is mandatory")]
   9:     [StringLength(10)]
  10:     public string FirstName
  11:     {
  12:         get { return firstName; }
  13:         set
  14:         {
  15:             if (!string.IsNullOrEmpty(value) && Char.IsNumber(value.ToCharArray()[0]))
  16:                 throw new ArgumentException("Name can't start with a number");
  17:             firstName = value;
  18:         }
  19:     }
  20:  
  21:     [Display(Name = "Cognome", Order = 1, Description = "Cognome utente")]
  22:     [Required(ErrorMessage = "Last Name is mandatory")]
  23:     public string LastName
  24:     {
  25:         get { return lastName; }
  26:         set { lastName = value; }
  27:     }
  28:  
  29:     [Display(Name = "Nato il", Order = 2, GroupName = "GeneralInfo")]
  30:     [Range(typeof(DateTime), "01/01/1970", "01/01/1990", ErrorMessage = "Date is out of range")]        
  31:     public DateTime BirthDate
  32:     {
  33:         get { return birthDate; }
  34:         set { birthDate = value; }
  35:     }
  36:  
  37:     [Bindable(true, BindingDirection.TwoWay)]
  38:     [Display(Name = "Email", Order = 3, GroupName = "GeneralInfo")]
  39:     [RegularExpression(@"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$", ErrorMessage = "Invalid Email")]
  40:     public string EMail
  41:     {
  42:         get { return eMail; }
  43:         set { eMail = value; }
  44:     }
  45:  
  46:     [Bindable(true)]
  47:     [Display(Name = "Ruolo", Order = 4, GroupName = "GeneralInfo")]
  48:     [CustomValidation(typeof(PersonValidator), "ValidateRole")]
  49:     public Role Role
  50:     {
  51:         get { return role; }
  52:         set { role = value; }
  53:     }
  54:  
  55:     #region IEditableObject Members
  56:     ...
  57:     #endregion
  58: }
 
quello che otterremo e questo risultato:

image Uno sguardo veloce agli attributi più comuni:

  • Bindable: Indica se il campo deve apparire oppure no, cosi come se deve essere Read-Only
    Display: Determina la posizione del campo nella  UI e il relativo nome (localizzabile)
    Required: Indica che il campo è obbligatorio (il nome del campo viene visualizzato in grassetto)
    StringLength: Massima lunghezza ammessa.
    Range: Valida il range ammesso.
    RegularExpression: Valida il campo usando una regular expression.
    CustomValidator: Permette di validare un campo o l’intera istanza usando il nostro codice.

Notate come il controllo visualizzi sia l’elenco dei campi non validati che eventuali eccezioni generate durante la valorizzazione del campo, e come se, come nel nostro caso, il tipo implementa IEditableObject, un pulsante Cancel per annullare l’editing che si attiva premendo il pulsante in alto a dx oppure, se la proprietà AutoEdit del controllo è True cliccando semplicemente su un campo.

Ok: Ma se ho un insieme di elementi, ad esempio una collezione di oggetti Persons?
No problem, basta associare la collezione alla proprietà ItemSource (via databinding oppure via codice) per ottenere questo risultato:

image

 

 

 

Notate come è possibile scorrere, editare, cancellare o inserire elementi usando i pulsanti in alto.

 

 

 

 

Ovviamente se quello che potete ottenere con gli attributi non vi basta, potete creare dei DataTemplate custom e associarli alle properietà HeaderTemplate, EditTemplate e DisplayTemplate personalizzando a proprio piacimento la user interface senza modificarne il comportamento.

imageDisplay Mode image  Edit Mode (notate come i nomi dei pulsanti sono personalizzabili)

Vi assicuro che quelle elencate sono solo alcune delle opzioni messe a disposizione dal controllo DataForm, le possibilità di personalizzazione sono veramente infinite.