<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Silverlight</title>
        <link>http://blogs.ugidotnet.org/dsantarelli/category/Silverlight.aspx</link>
        <description>Silverlight</description>
        <language>it-IT</language>
        <copyright>Dario Santarelli</copyright>
        <generator>Subtext Version 2.6.0.0</generator>
        <item>
            <title>[Silverlight 5] ICustomTypeProvider</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2011/05/17/silverlight-5-icustomtypeprovider-again.aspx</link>
            <description>La beta di Silverlight 5 ha introdotto una nuova interfaccia ICustomTypeProvider che permette di effettuare il binding tra elementi della UI ed oggetti la cui struttura non è nota a compile-time. Nello specifico, l’esigenza che questa interfaccia soddisfa è evidente quando si lavora con dati provenienti da fonti eterogenee (database, istanze XML, oggetti JSON, dati binari, csv etc.) che si desiderano presentare senza ricompilare ogni volta che viene aggiunto/rimosso un attributo, una colonna o un campo dalla sorgente dati. In questi contesti si può valutare di rendere flessibile il meccanismo di binding permettendo di aggiungere/rimuovere proprietà a runtime lasciando al motore di databinding il compito di determinarne il tipo senza obbligare lo sviluppatore a ri-compilare/ri-deployare l’applicazione ogni volta che si necessita di una modifica al model. 
Continua &amp;gt;&amp;gt; &lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/100042.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2011/05/17/silverlight-5-icustomtypeprovider-again.aspx</guid>
            <pubDate>Tue, 17 May 2011 01:25:34 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2011/05/17/silverlight-5-icustomtypeprovider-again.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/100042.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/100042.aspx</trackback:ping>
        </item>
        <item>
            <title>[Silverlight 5] ICustomTypeProvider</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2011/05/17/silverlight-5-icustomtypeprovider.aspx</link>
            <description>La beta di Silverlight 5 ha introdotto una nuova interfaccia ICustomTypeProvider che permette di effettuare il binding tra elementi della UI ed oggetti la cui struttura non è nota a compile-time. Nello specifico, l’esigenza che questa interfaccia soddisfa è evidente quando si lavora con dati provenienti da fonti eterogenee (database, istanze XML, oggetti JSON, dati binari, csv etc.) che si desiderano presentare senza ricompilare ogni volta che viene aggiunto/rimosso un attributo, una colonna o un campo dalla sorgente dati. In questi contesti si può valutare di rendere flessibile il meccanismo di binding permettendo di aggiungere/rimuovere proprietà a runtime lasciando al motore di databinding il compito di determinarne il tipo senza obbligare lo sviluppatore a ri-compilare/ri-deployare l’applicazione ogni volta che si necessita di una modifica al model. L’interfaccia ICustomTypeProvider è così definita:     
         
public interface ICustomTypeProvider       
{       
    Type GetCustomType();       
}
Quando la si implementa, viene chiesto di ritornare un oggetto di tipo System.Type. Oggi l’engine di Silverlight 5 controlla in fase di binding se l’oggetto che stiamo passando implementa o meno l’interfaccia ICustomTypeProvider per capire se usare i metadati del nostro tipo custom piuttosto che del fallback System.Type.     
Bisogna dire che l’implementazione di questa interfaccia richiede un certo sforzo iniziale, poiché implica la creazione di un tipo custom in grado di gestire ad esempio un “repository” di proprietà (PropertyInfo) che possiamo aggiungere/rimuovere dinamicamente. Inoltre, non dobbiamo dimenticarci della solita INotifyPropertyChanged utile per il corretto funzionamento del binding e di INotifyDataErrorInfo per la validazione. I benefici che otteniamo sono tuttavia notevoli rispetto alle versioni precedenti di Silverlight, dove non è possibile derivare Type o PropertyInfo per questi scopi. 
Esempio di utilizzo      
A titolo di esempio, proviamo a definire una classe DictionaryObject che, come il nome fa intendere, espone a mo’ di dictionary l’elenco delle sue proprietà in modo tale che possono essere aggiunte e rimosse a runtime. L’obiettivo è rendere “binding-friendly” queste coppie chiave-valore!
public class DictionaryObject : ICustomTypeProvider, INotifyPropertyChanged       
{       
    private Dictionary&amp;lt;string, object&amp;gt; _properties = null;       

    public event PropertyChangedEventHandler PropertyChanged;       

    public object this[string propertyName]       
    {       
        get { return _properties.ContainsKey(propertyName) ? _properties[propertyName] : null; }       
        set       
        {       
            AddProperty(propertyName);       
            if (_properties[propertyName] != value)       
            {       
                _properties[propertyName] = value;       
                OnPropertyChanged(propertyName);       
            }       
        }       
    }       

    public DictionaryObject()       
    {  
        _properties = new Dictionary&amp;lt;string, object&amp;gt;();  
    }       

    public bool AddProperty(string name)  
    {  
        return AddProperty(name, null);  
    }       

    public bool AddProperty(string name, object value)       
    {       
        if (!_properties.ContainsKey(name))       
        {       
            _properties.Add(name, value);       
            return true;       
        }       
        else return false;       
    }       

    public bool RemoveProperty(string name)       
    {       
        if (_properties.ContainsKey(name))       
        {       
            _properties.Remove(name);       
            return true;       
        }       
        else return false;       
    }       

    public Type GetCustomType()  
    {  
        return new DictionaryObjectType(_properties);         
    }         
      
    protected void OnPropertyChanged(string key)       
    {       
        if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(key));       
    }       
}
Affinché il runtime di Silverlight tratti le coppie chiave-valore alla stregua di proprietà vere e proprie di un generico oggetto del CLR, il trucco sta nel definire un tipo custom in grado di fornire al volo tutti i metadati che servono in fase di binding. Riportiamo solo le righe di codice rilevanti…
public class DictionaryObjectType : Type       
{       
   private Type _proxyType = typeof(DictionaryObject);       
   private Dictionary&amp;lt;string, object&amp;gt; _propertiesDictionary = null;       
   …      
   
   public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)       
   {       
      PropertyInfo[] properties = _proxyType.GetProperties(bindingAttr);       

      if (BindingFlags.Instance == (bindingAttr &amp;amp; BindingFlags.Instance) &amp;amp;&amp;amp;       
          BindingFlags.Public == (bindingAttr &amp;amp; BindingFlags.Public))       
          {       
             return GetDynamicProperties().ToArray();       
          }       

      return properties;       
   }       
      
   private List&amp;lt;PropertyInfo&amp;gt; GetDynamicProperties()       
   {       
     List&amp;lt;PropertyInfo&amp;gt; properties = new List&amp;lt;PropertyInfo&amp;gt;();       

     foreach (string key in _propertiesDictionary.Keys)       
     {                 
        if (_propertiesDictionary[key] != null)  // null values will be ignored!      
        {       
            properties.Add(new DictionaryObjectPropertyInfo(_propertiesDictionary[key].GetType(), typeof(DictionaryObject), key));       
        }       
     }       

     return properties;       
   }       
}
Per gli oggetti che implementano l’interfaccia ICustomTypeProvider, abbiamo la possibilità di intercettare le richieste di informazioni di reflection che provengono dal motore di databinding e fornire metadati personalizzati. Nel nostro esempio, per comunicare al runtime come fare la get e la set sulle proprietà di un DictionaryObject, abbiamo bisogno di ereditare anche PropertyInfo.
public class DictionaryObjectPropertyInfo : PropertyInfo       
{       
    private Type _propertyType;       
    private Type _declaringType;       
    private string _name;       

    public DictionaryObjectPropertyInfo(Type propertyType, Type declaringType, string propertyName)       
    {       
        _propertyType = propertyType;       
        _declaringType = declaringType;       
        _name = propertyName;       
    }       
  
    ...       
    
    public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, System.Globalization.CultureInfo culture)       
    {       
        DictionaryObject dictionaryObject = (DictionaryObject)obj;             
        return dictionaryObject[Name];       
    }       
       
    public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, System.Globalization.CultureInfo culture)       
    {       
        DictionaryObject dictionaryObject = (DictionaryObject)obj;       
        dictionaryObject[Name] = value;       
    }       
}
OK non abbiamo bisogno di altro! Proviamo a utilizzare concretamente la classe DictionaryObject. Creiamo una view con una DataGrid le cui colonne vengono autogenerate. L’obiettivo è di rendere il databinding bidirezionale e consistente rispetto al tipo CLR di ciascuna proprietà esposta.
&amp;lt;UserControl x:Class="ICustomTypeProviderSample.MainPage"       
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"       
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"     
   xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"&amp;gt;       
    &amp;lt;StackPanel x:Name="LayoutRoot" HorizontalAlignment="Center" Margin="20"&amp;gt;       
        &amp;lt;sdk:DataGrid AutoGenerateColumns="True" ItemsSource="{Binding Items}" /&amp;gt;              
    &amp;lt;/StackPanel&amp;gt;       
&amp;lt;/UserControl&amp;gt;
Nel viewmodel definiamo le proprietà degli items come coppie chiave-valore.
public class MainPageViewModel : INotifyPropertyChanged       
{       
    ...       
     
    public ObservableCollection&amp;lt;DictionaryObject&amp;gt; Items { get; private set; }         

    public MainPageViewModel()       
    {             
        Items = new ObservableCollection&amp;lt;DictionaryObject&amp;gt;();       
             
        DictionaryObject newItem = new DictionaryObject();         
        newItem["ID"] = 1;       
        newItem["Name"] = "Item 1";       
        newItem["UnitPrice"] = 5.3;       
        newItem["Created"] = DateTime.Now;     
     
        Items.Add(newItem);       

        ...       
   }       
}   
La view risultante è coerente rispetto ai tipi delle proprietà. L’oggetto DictionaryObject implementa l’interfaccia INotifyPropertyChanged (e preferibilmente INotifyDataErrorInfo) quindi la nostra interazione con le celle della DataGrid si riflette direttamente sul valore delle proprietà coinvolte nel databinding.
  

L’esempio mostrato è molto banale ma fa intendere quanti miglioramenti possono essere concepiti. Il codice completo di questo esempio è scaricabile al seguente link.
Ma non esisteva qualcosa del genere anche in WPF?  
A chi possiede familiarità con l’interfaccia ICustomTypeDescriptor di WPF (la quale risolve lo stesso problema di ICustomTypeProvider di Silverlight 5… i nomi addirittura sono più o meno gli stessi!) verrà subito in mente la domanda “Perché non hanno aggiunto direttamente l’interfaccia ICustomTypeDescriptor”?     
Leggendo la documentazione MSDN non sono riuscito ad estrarre una risposta chiara. Sembrerebbe che il motivo (per ora almeno) sia dovuto al fatto che ICustomTypeDescriptor richiede una sua gerarchia di classi  (TypeDescriptor, EventDescriptor, etc.) che di fatto duplica la gerarchia di reflection, il che incrementerebbe la dimensione del pacchetto Silverlight da installare client-side. 
E il DLR?      
Questa feature in realtà non ha nulla a che vedere con il DLR. Oggetti del DLR come ExpandoObject o DynamicObject (o qualunque implementazione dell’interfaccia IDynamicMetaObjectProvider) non apportano alcun tipo di informazione sulle loro proprietà. Il motore del databinding ha invece bisogno di queste informazioni per effettuare correttamente conversioni di tipo per tutto ciò che non sia una semplice stringa. Ad esempio, se abbiamo una TextBox in binding con una proprietà DateTime di un oggetto, quando inseriamo un nuovo valore nella TextBox l’engine valuta il tipo della proprietà e converte il testo contenuto nella TextBox da stringa a DateTime e viceversa. Se invece si effettua il binding su una proprietà di un ExpandoObject, il valore della proprietà sarà convertito semplicemente a stringa e non possono essere fatte valutazioni di binding. Insomma, in WPF è possibile associare elementi del DLR agli elementi della UI, ma non avviene nessuna conversione di tipo… tutto ciò su cui possiamo lavorare sono solo stringhe.     
In definitiva, mentre il DLR è conveniente quando si interagisce con altri linguaggi o altre piattaforme, non è consigliabile per il databinding e l’interazione con la UI.
Riferimenti      
Segnalo i due interessanti articoli da cui ho preso spunto:

    Using ICustomTypeProvider in Silverlight 5 
    Binding to Dynamic Properties with ICustomTypeProvider (Silverlight 5 Beta) 
&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/100041.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2011/05/17/silverlight-5-icustomtypeprovider.aspx</guid>
            <pubDate>Tue, 17 May 2011 00:51:56 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2011/05/17/silverlight-5-icustomtypeprovider.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/100041.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/100041.aspx</trackback:ping>
        </item>
        <item>
            <title>nRoute e "Reverse Commands"</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2010/01/08/nroute-e-reverse-commands.aspx</link>
            <description>nRoute è uno dei framework a supporto di applicazioni Silverlight sviluppate secondo il pattern M-V-VM. In merito, segnalo questo interessante articolo in cui si parla dell' introduzione di Reverse Commands. 
Da un punto di vista pratico viene introdotta una nuova interfaccia IReverseCommand che estende la solita ICommand. Tale specializzazione permette di definire un trigger "di ritorno" dal View-Model verso la View una volta che un command è stato eseguito. L'aspetto interessante si trova quindi nel fatto che il target dell' IReverseCommand è la View e non il ViewModel. 
Secondo i principi del pattern M-V-VM in Silverlight, esistono due meccanismi primari di comunicazione tra View e ViewModel:

    Cambiamenti di stato relativi a databinding tra oggetti della View e proprietà del ViewModel
    Invocazioni di azioni ( ICommand appunto ) dalla View verso il ViewModel

Se in questi scenari architetturali gli ICommand sono concepiti per essere scatenati dalla View (e gestiti nel ViewModel), l'introduzione di ReverseCommands avviene per esplicitare il meccanismo inverso sempre in un'ottica strongly-typed.&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/97820.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2010/01/08/nroute-e-reverse-commands.aspx</guid>
            <pubDate>Fri, 08 Jan 2010 16:32:51 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2010/01/08/nroute-e-reverse-commands.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/97820.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/97820.aspx</trackback:ping>
        </item>
        <item>
            <title>Database client-side per Silverlight</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2010/01/06/database-client-side-per-silverlight.aspx</link>
            <description>Con il potenziamento delle funzionalità out-of-browser, Silverlight 3+ è ormai una tecnologia matura per supportare scenari off-line. Nell’ Isolated Storage client-side, infatti, oggi possiamo gestire ad esempio un vero e proprio database engine.   Ultimamente la mia attenzione è rivolta in particolare a due interessanti progetti (in beta):     Silverlight Database     siaqodb (object database per .NET, Mono and Silverlight)   Technorati Tag: Silverlight,Isolated Storage&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/97811.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2010/01/06/database-client-side-per-silverlight.aspx</guid>
            <pubDate>Wed, 06 Jan 2010 13:24:08 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2010/01/06/database-client-side-per-silverlight.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/97811.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/97811.aspx</trackback:ping>
        </item>
        <item>
            <title>[Silverlight/WPF] Resource file e Access Modifier</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2009/03/20/silverlightwpf-resource-file-e-access-modifier.aspx</link>
            <description>Più volte nello sviluppo Silverlight/WPF mi sono imbattuto nella necessità di utilizzare i file di risorsa (.resx) e devo dire che le prime volte mi sono trovato un po’ in difficoltà dal momento che non riuscivo a capire per quale arcano i miei binding dichiarativi nel codice XAML verso le mie risorse non funzionassero affatto. Andiamo per ordine: supponendo di definire un file di risorsa in questo modo ...              ... in fase di design Visual Studio notifica uno “strano” errore,      indipendentemente dal fatto che si utilizzi Public o Internal come access modifier (più precisamente se si selezionasse Internal l’errore diverrebbe AG_E_PARSER_BAD_TYPE). Mantenendo l’access modifier come “Public” ed andando a vedere il codice autogenerato da Visual Studio ci si imbatte in questa piccola “finezza”:            Classe public e costruttore internal!!!   Personalmente ho sempre ovviato al problema nel modo più semplice, impostando il costruttore come public per ogni file di risorsa. Oggi invece mi imbatto in questo post che propone invece una soluzione più elegante a cui non avevo proprio pensato, ovvero realizzare semplicemente una classe pubblica con una singola proprietà che espone la classe associata al file di risorsa. SEMPLICE MA GENIALE!!!     Technorati Tag: Silverlight 2,WPF&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/95753.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2009/03/20/silverlightwpf-resource-file-e-access-modifier.aspx</guid>
            <pubDate>Fri, 20 Mar 2009 00:02:41 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2009/03/20/silverlightwpf-resource-file-e-access-modifier.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/95753.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/95753.aspx</trackback:ping>
        </item>
        <item>
            <title>[Silverlight 2] Visibility e VisualStateManager</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2009/03/16/silverlight-2-visibility-e-visualstatemanager.aspx</link>
            <description>Una caratteristica di un controllo visuale che spesso e volentieri risulta gradevole è la possibilità di mostrare/nascondere il contenuto del controllo stesso tramite un effetto FadeIn/FadeOut. In genere, questo effetto è realizzato tramite una semplice animazione che lavora sull’Opacity del controllo (portandola da 1 a 0 e viceversa) e che magari imposta a Visible/Collapsed la proprietà Visibility subito dopo l’animazione in modo da riempire/liberare istantaneamente un’area specifica dello schermo.  In molti casi risulta dunque utile legare l’ effetto FadeIn/FadeOut proprio alla proprietà Visibility del controllo, in modo da ottenere automaticamente le animazioni desiderate al momento della valorizzazione della proprietà (che altrimenti non effettuerebbe ovviamente alcun effetto visuale di transizione). Un modo che ritengo molto interessante per ottenere questo tipo di scenario sfrutta il VisualStateManager : nel seguente esempio vediamo come sia possibile effettuare l’override della proprietà Visibility di un UserControl per agganciare gli effetti di FadeIn/FadeOut agli stati Visible/Collapsed definiti tramite VisualStateManager. 

MyControl.xaml
&amp;lt;UserControl xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows" ...&amp;gt; 
    &amp;lt;Grid x:Name="LayoutRoot"&amp;gt; 
      
     &amp;lt;vsm:VisualStateManager.VisualStateGroups&amp;gt; 
         &amp;lt;vsm:VisualStateGroup x:Name="CommonStates"&amp;gt; 
           &amp;lt;vsm:VisualState x:Name="Visible"&amp;gt; 
             &amp;lt;Storyboard&amp;gt; 
               &amp;lt;DoubleAnimation Duration="0:0:.5" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Opacity" 
                                From="0" To="1" AutoReverse="False" Completed="VisibleCompleted" /&amp;gt; 
             &amp;lt;/Storyboard&amp;gt; 
           &amp;lt;/vsm:VisualState&amp;gt; 
           &amp;lt;vsm:VisualState x:Name="Collapsed"&amp;gt; 
             &amp;lt;Storyboard&amp;gt; 
               &amp;lt;DoubleAnimation Duration="0:0:.5" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Opacity" 
                                From="1" To="0" AutoReverse="False" Completed="CollapsedCompleted" /&amp;gt; 
             &amp;lt;/Storyboard&amp;gt; 
           &amp;lt;/vsm:VisualState&amp;gt; 
         &amp;lt;/vsm:VisualStateGroup&amp;gt; 
      &amp;lt;/vsm:VisualStateManager.VisualStateGroups&amp;gt; 

      ...  

    &amp;lt;/Grid&amp;gt; 
&amp;lt;/UserControl&amp;gt; 

MyControl.xaml.cs
public partial class MyControl : UserControl 
{ 
  private Visibility _visibility;        

  public event EventHandler VisibilityChanged;         
  
  public MyControl() { InitializeComponent(); } 

  public new Visibility Visibility 
  { 
     get { return _visibility; } 
     set 
     { 
       if (_visibility != value) 
       { 
         _visibility = value; 
         OnVisibilityChanged(); 
       } 
      } 
  } 

  protected virtual void OnVisibilityChanged() 
  { 
     if (this.Visibility == Visibility.Visible) 
     { 
       base.Visibility = this.Visibility; 
       VisualStateManager.GoToState(this, "Visible", true); 
     } 
     else VisualStateManager.GoToState(this, "Collapsed", true);             
  } 

  private void CollapsedCompleted(object sender, EventArgs e) 
  { 
     base.Visibility = this.Visibility; 
     FireVisibilityChanged(); 
  }        

  private void VisibleCompleted(object sender, EventArgs e) { FireVisibilityChanged(); } 

  private void FireVisibilityChanged() 
  { 
     if (VisibilityChanged != null) VisibilityChanged(this, new EventArgs());   
  } 
}

Come si può notare, nell’esempio si è voluto implementare anche un evento VisibilityChanged che viene scatenato ogni volta che l’animazione FadeIn/FadeOut ha terminato la propria esecuzione. Infatti, la transizione visuale da uno stato Visible ad uno stato Collapsed può essere relativamente lunga e di conseguenza potrebbe essere utile sapere esattamente quando il nostro controllo è completamente visibile/nascosto.
 
Technorati Tag: Silverlight 2&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/95722.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2009/03/16/silverlight-2-visibility-e-visualstatemanager.aspx</guid>
            <pubDate>Mon, 16 Mar 2009 23:04:58 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2009/03/16/silverlight-2-visibility-e-visualstatemanager.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/95722.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/95722.aspx</trackback:ping>
        </item>
        <item>
            <title>Interazione tra Javascript e Silverlight: un password checker</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2009/01/28/interazione-tra-javascript-e-silverlight-un-password-checker.aspx</link>
            <description>La comunicazione tra Javascript and Silverlight è una tecnica che spesso rende molto semplice e potente l’introduzione di miglioramenti grafici nonché funzionali in applicazioni web preesistenti. In questo post viene mostrato nello specifico come integrare un password checker realizzato in Silverlight all’interno di un form ASP.NET di partenza, sfruttando javascript come “collante”. 
Supponiamo by design che il password checker stabilisca 6 livelli di complessità raggruppabili in tre categorie: “Weak”,”Normal” e “Strong”: 

  

1. Page.xaml 
Partiamo dalla definizione del password checker in Silverlight. Gli elementi della UI di tale controllo, come mostrato nella figura sopra riportata, sono costituiti da 6 Rectangle ed un TextBlock disposti orizzontalmente all’interno di uno StackPanel. 

&amp;lt;UserControl x:Class="SilverlightAppPasswordStrength.Page" 
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&amp;gt;     
   ... 
   
  &amp;lt;Grid x:Name="LayoutRoot"&amp;gt;                       
    &amp;lt;StackPanel x:Name="mainPanel" Orientation="Horizontal"&amp;gt;            
      &amp;lt;Rectangle ...&amp;gt;&amp;lt;/Rectangle&amp;gt; 
      &amp;lt;Rectangle ... Margin="2,0,0,0"&amp;gt;&amp;lt;/Rectangle&amp;gt; 
      &amp;lt;Rectangle ... Margin="2,0,0,0"&amp;gt;&amp;lt;/Rectangle&amp;gt; 
      &amp;lt;Rectangle ... Margin="2,0,0,0"&amp;gt;&amp;lt;/Rectangle&amp;gt; 
      &amp;lt;Rectangle ... Margin="2,0,0,0"&amp;gt;&amp;lt;/Rectangle&amp;gt; 
      &amp;lt;Rectangle ... Margin="2,0,0,0"&amp;gt;&amp;lt;/Rectangle&amp;gt; 
      &amp;lt;TextBlock x:Name="txtPwdStrength" ... Margin="5,2,0,0"&amp;gt;&amp;lt;/TextBlock&amp;gt;            
    &amp;lt;/StackPanel&amp;gt;        
  &amp;lt;/Grid&amp;gt; 
&amp;lt;/UserControl&amp;gt; 

2. Page.xaml.cs 
Nell’implementazione, il comportamento della UI è in mano ad un metodo NotifyStrengthLevel che sostanzialmente si prende carico di gestire il layout degli elementi in base al livello di complessità (da 0 a 5) restituito da un metodo GetPasswordStrengthLevel che implementa l’algoritmo di password cecking. Due note:

    Tramite il metodo HtmlPage.RegisterScriptableObject possiamo “registrare” il nostro oggetto Page di Silverlight all’interno di una pagina (X)Html in modo da abilitare l’accesso da parte di javascript 
    Per essere invocabile via javascript, il metodo NotifyStrengthLevel dell’oggetto Page deve essere decorato con l’attributo ScriptableMember.  
    

public partial class Page : UserControl 
{        
  public Page() 
  { 
    InitializeComponent(); 
    HtmlPage.RegisterScriptableObject("PwdStrengthControl", this);             
  } 

  [ScriptableMember] 
  public void NotifyStrengthLevel(string pwd) 
  { 
    SolidColorBrush color = null; 
    string text = null; 

    int level = GetPasswordStrengthLevel(pwd);           
    
    if (level &amp;lt;= 1) 
    { 
      color = new SolidColorBrush(Colors.Red); 
      text = "Weak"; 
    } 
    else if (level &amp;gt; 1 &amp;amp;&amp;amp; level &amp;lt;= 3) 
    { 
      color = new SolidColorBrush(Colors.Orange); 
      text = "Normal"; 
    } 
    else if (level &amp;gt; 3 &amp;amp;&amp;amp; level &amp;lt;= 5) 
    { 
      color = new SolidColorBrush(Colors.Green); 
      text = "Strong"; 
    } 
    else throw new ArgumentException(string.Format("Invalid Strength level: {0}",level)); 

    txtPwdStrength.Text = text; 
    txtPwdStrength.Foreground = color; 

    IEnumerable&amp;lt;Rectangle&amp;gt; rects = mainPanel.Children.OfType&amp;lt;Rectangle&amp;gt;(); 
    foreach (Rectangle rect in rects) rect.Fill = new SolidColorBrush(Colors.LightGray); 
    for (int i = 0; i &amp;lt;= level; i++) rects.ElementAt(i).Fill = color;                        
  } 

  private int GetPasswordStrengthLevel(string pwd) 
  {   
   int level = 0; 

   // Algoritmo per determinare il livello di sicurezza della password 

   return level; 
  } 
}

3. Test.aspx 
A questo punto, il nostro password checker in Silverlight è pronto per essere acceduto via javascript analizzando il DOM del form ASP.NET host. Nel seguente codice viene mostrata una possibile implementazione: ogni volta che si scatena l’evento client-side onkeyup sulla TextBox per l’inserimento della password, viene invocata una funzione javascript CheckPwdStrength che si occupa di gestire l’interazione con l’oggetto Silverlight. Da notare in particolare la sintassi: 

document.getElementById("&amp;lt;silverlightControl&amp;gt;").Content.&amp;lt;ScriptableObject&amp;gt;.&amp;lt;ScriptableMember&amp;gt;(...); 

utilizzata per invocare il metodo di interesse NotifyStrengthLevel (ScriptableMember) definito all’interno dell’oggetto Silverlight registrato. 

&amp;lt;script type="text/javascript"&amp;gt; 
  function CheckPwdStrength(pwd) 
  { 
    var control = document.getElementById("xamlPwdStrength");       
    if (pwd.length == 0) control.style.visibility = 'hidden'; 
    else 
    { 
      control.style.visibility = 'visible'; 
      control.Content.PwdStrengthControl.NotifyStrengthLevel(pwd);                
    } 
   }         
&amp;lt;/script&amp;gt;
. . .

&amp;lt;asp:TextBox ID="txtPassword" runat="server" TextMode="Password" onkeyup="CheckPwdStrength(this.value)" /&amp;gt; 

&amp;lt;asp:Silverlight ID="xamlPwdStrength" runat="server" Source="~/ClientBin/SilverlightAppPasswordStrength.xap" MinimumVersion="2.0.31005.0" Height="15px" /&amp;gt; 
. . . 


Technorati Tag: Silverlight,Javascript&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/95318.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2009/01/28/interazione-tra-javascript-e-silverlight-un-password-checker.aspx</guid>
            <pubDate>Wed, 28 Jan 2009 00:20:08 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2009/01/28/interazione-tra-javascript-e-silverlight-un-password-checker.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/95318.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/95318.aspx</trackback:ping>
        </item>
        <item>
            <title>[Silverlight 2] Simulare una MasterPage</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2009/01/22/silverlight-2-simulare-una-masterpage.aspx</link>
            <description>Allo stato attuale, Silverlight 2 non possiede un modello di programmazione built-in per gestire il concetto di MasterPage così come avviene in ASP.NET a partire dalla versione 2.0. Ad ogni modo, per ovviare a tale mancanza, l'implementazione di una semplice soluzione custom che simula l'interazione tra una pagina "Master" e più pagine "Content" in Silverlight 2 non è poi così difficile. 
L'obiettivo è fondamentalmente quello di definire un PlaceHolder all'interno di una pagina Master (che funge da RootVisual) in cui caricare e visualizzare varie pagine di contenuto. Per ottenere questo risultato vengono dunque definiti due UserControl: MasterPage e ContentPage.

- MasterPage
Supponiamo di definire la master page come un semplice UserControl, avente ad esempio il seguente classico layout:


&amp;lt;Grid x:Name="LayoutRoot"&amp;gt;
  &amp;lt;Grid.RowDefinitions&amp;gt;
    &amp;lt;RowDefinition Height="100" /&amp;gt;
    &amp;lt;RowDefinition/&amp;gt;
  &amp;lt;/Grid.RowDefinitions&amp;gt;
 
  &amp;lt;!-- Header --&amp;gt;
  &amp;lt;StackPanel Grid.Row="0" ... &amp;gt;&amp;lt;/StackPanel&amp;gt;
        
  &amp;lt;Grid Grid.Row="1"&amp;gt;
     &amp;lt;Grid.ColumnDefinitions&amp;gt;
        &amp;lt;ColumnDefinition Width="150" /&amp;gt;
        &amp;lt;ColumnDefinition /&amp;gt;
     &amp;lt;/Grid.ColumnDefinitions&amp;gt;
 
    &amp;lt;!-- Left Column --&amp;gt;
    &amp;lt;StackPanel Grid.Column="0" ...&amp;gt;
      ...
    &amp;lt;/StackPanel&amp;gt;
            
    &amp;lt;!-- Center Column --&amp;gt;
    &amp;lt;StackPanel x:Name="ContentPagePlaceHolder" Grid.Column="1" ... /&amp;gt;            
  &amp;lt;/Grid&amp;gt;
&amp;lt;/Grid&amp;gt;

Come si può notare, abbiamo un header (StackPanel) e due colonne di una Grid (una a sinistra per il menu ed una centrale per il contenuto). La colonna centrale contiene uno StackPanel nominato ContentPagePlaceHolder che funge appunto da PlaceHolder per le nostre pagine di contenuto.
Ecco una sintesi dell'implementazione della MasterPage:
public partial class MasterPage : UserControl
{
  public MasterPage()
  {
    InitializeComponent();
    LoadContentPages("contentPages.xml");
  }
 
  private void LoadContentPages(string contentPagesFile)
  {
     XDocument xDoc = XDocument.Load(contentPagesFile);
     foreach (XElement node in xDoc.Element("ContentPages").Descendants("Page"))
     {
       ContentPage page = Activator.CreateInstance(Type.GetType(node.Attribute("type").Value)) as ContentPage;
       page.PageName = node.Attribute("name").Value;     
       page.Visibility = Visibility.Collapsed;
       ContentPagePlaceHolder.Children.Add(page);
     }
   }
 
   public ContentPage GetContentPage(string pageName)
   {
     return ContentPagePlaceHolder.Children.OfType&amp;lt;ContentPage&amp;gt;().Single(p =&amp;gt; p.PageName == pageName);
   }
 
   public void ViewContentPage(string pageName)
   {
      ViewContentPage(GetContentPage(pageName));
   }
 
   public void ViewContentPage(ContentPage page)
   {
     IEnumerable&amp;lt;ContentPage&amp;gt; contentPages = ContentPagePlaceHolder.Children.OfType&amp;lt;ContentPage&amp;gt;();
     foreach (ContentPage contentPage in contentPages)
     {
       if (!contentPage.Equals(page)) contentPage.Visibility = Visibility.Collapsed;
       else contentPage.Visibility = Visibility.Visible;
     }          
   } 
}

Tramite il metodo LoadContentPages(...) popoliamo semplicemente il ContentPagePlaceHolder con le content pages del nostro progetto che in questo caso specifichiamo in un file XML contentPages.xml:
&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;ContentPages&amp;gt;
  &amp;lt;Page name="Page1" type="MasterPageSilverlight.Page1"&amp;gt;&amp;lt;/Page&amp;gt;
  &amp;lt;Page name="Page2" type="MasterPageSilverlight.Page2"&amp;gt;&amp;lt;/Page&amp;gt;
  &amp;lt;Page name="Page3" type="MasterPageSilverlight.Page3"&amp;gt;&amp;lt;/Page&amp;gt;
  ...
&amp;lt;/ContentPages&amp;gt;

Poi, tramite il metodo ViewContentPage(...)  implementiamo il meccanismo di visualizzazione di una specifica ContentPage, che in questo caso è realizzato sfruttando la proprietà Visibility di ciascuna content page pre-caricata nel ContentPagePlaceHolder.
- ContentPage
La classe ContentPage rappresenta una pagina di contenuto visualizzabile all'interno del ContentPagePlaceHolder definito nella MasterPage. Per questa classe potremmo definire le seguenti proprietà:

    Master: la MasterPage che contiene la ContentPage 
    PageName: il nome delle ContentPage che la identifica univocamente all'interno di un ContentPagePlaceHolder  
    PageData: un dictionary utilizzabile per passare dati tra ContentPage  

public class ContentPage : UserControl
{
  public MasterPage Master
  {
    get { return Application.Current.RootVisual as MasterPage; }
  }
        
  public string PageName { get; set; }
 
  public Dictionary&amp;lt;string, object&amp;gt; PageData { get; set; }
 
  public ContentPage()
  {
    this.PageData = new Dictionary&amp;lt;string, object&amp;gt;();                
  }
}

Esempio di utilizzo
A questo punto abbiamo un semplice programming model per "switchare" content page sia a partire dalla MasterPage contenitore che a partire da una ContentPage contenuta nel ContentPagePlaceHolder della Master. 
In particolare, 
- all'interno della MasterPage possiamo selezionare la ContentPage da visualizzare nel  ContentPagePlaceHolder nel modo seguente:

ContentPage contentPage = GetContentPage("Page2");
page.PageData["Info"] = "MyData..."; // Eventuale passaggio di dati alla pagina 
ViewContentPage(contentPage);

- all'interno di una ContentPage, invece, possiamo utilizzare la reference alla MasterPage che la contiene per comunicare con un'altra ContentPage sorella:


ContentPage page = Master.GetContentPage("Page2");
page.PageData["Info"] = "MyData..."; // Eventuale passaggio di dati alla pagina
Master.ViewContentPage(page);

Technorati Tag: Silverlight,MasterPage&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/95273.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2009/01/22/silverlight-2-simulare-una-masterpage.aspx</guid>
            <pubDate>Thu, 22 Jan 2009 15:58:32 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2009/01/22/silverlight-2-simulare-una-masterpage.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/95273.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/95273.aspx</trackback:ping>
        </item>
        <item>
            <title>Silverlight 2 e ICommand</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2008/12/13/94921.aspx</link>
            <description>Premessa: l'altro ieri ho partecipato all' 8° Workshop DotNetMarche dedicato a Silverlight. Un Alessandro in grande forma ha tenuto banco per più di 3 ore illustrando una gran quantità di contenuti interessantissimi: dalla presentazione di soluzioni/problematiche architetturali che interessano le RIAs alla realizzazione di controlli custom (finestre di navigazione e menu per Silverlight) , dalla creazione di un' infrastruttura multitargeting per il porting in WPF all' IoC. Insomma, un evento per veri buongustai!!! ( ...considerando soprattutto la seguente cena in compagnia di Alessandro, Gian Maria, Stefano, Andrea, Stefano, Alfredo e la buonissima bistecca alla fiorentina :D .  )     
Tornando all'oggetto di questo post, un aspetto che sta attirando la mia attenzione in questi giorni è l'assenza in Silverlight 2 del supporto built-in per l'interfaccia ICommand. Ovvero, l'interfaccia è presente (come in WPF), ma per utilizzarla ad esempio in un M-V-VM sottoforma di binding dichiarativo abbiamo bisogno di implementare a mano i nostri ICommand come "attached properties" e quindi associarli agli eventi dei controlli.... O_o  
Speriamo vivamente che il supporto ai command source sia presto introdotto anche in Silverlight.  

Ad ogni modo, segnalo questo post di Josh Smith in cui viene riportato un semplice esempio di realizzazione di due attached properties (nello specifico Command e CommandParameter) per i controlli che derivano da ButtonBase. 

Technorati Tag: Silverlight 2&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/94921.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2008/12/13/94921.aspx</guid>
            <pubDate>Sat, 13 Dec 2008 10:47:42 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2008/12/13/94921.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/94921.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/94921.aspx</trackback:ping>
        </item>
        <item>
            <title>[Silverlight 2] Navigazione tra pagine</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2008/12/09/silverlight-2-navigazione-tra-pagine.aspx</link>
            <description>Da un punto di vista dell'usabilità, è estremamente importante strutturare un' applicazione che gestisce molti contenuti in modo tale che l'utente possa navigare facilmente ed intuitivamente tra le varie pagine. Da un punto di vista dello sviluppo, invece, implementare un'infrastruttura di navigazione flessibile e testabile non è la cosa più semplice del mondo, ma può caratterizzare un aspetto critico.    Purtroppo, a differenza del suo fratellone WPF, Silverlight 2 non include alcun supporto alla navigazione tra pagine!    Questo significa che a meno di applicazioni piccole, ci troveremmo veramente nei pasticci se implementassimo la navigazione basandoci solo sul mostrare/nascondere "manualmente" i controlli della UI contenuti nella nostra Root Page... insomma, attualmente  la navigazione avanti/indietro in Silverlight ce la dobbiamo implementare in casa!!! E' evidente che in un progetto di una certa complessità questa mancanza può essere pesante.  Per chi vuole approfondire la questione, nel blog di David Hill sono presenti dei post dedicati allo sviluppo di un prototipo di framework dedicato alla navigazione (codename "Helix") in Silverlight 2. Essa si basa su tre semplici entità: Frame, Page e NavigationLink.              Buona Navigazione :D      Technorati Tag: Silverlight 2&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/94889.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2008/12/09/silverlight-2-navigazione-tra-pagine.aspx</guid>
            <pubDate>Tue, 09 Dec 2008 20:54:03 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2008/12/09/silverlight-2-navigazione-tra-pagine.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/94889.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/94889.aspx</trackback:ping>
        </item>
    </channel>
</rss>