in

dotNet Umbria [DNU]

Il primo User Group in Umbria sul mondo .Net

Articoli

Articoli vari degli iscritti a DotNetUmbria

February 2008 - Posts

  • ObjectDataProvider e databinding su WPF

    Tramite WPF è possibile istanziare in diversi modi un oggetto da utilizzare come sorgente dati per il databinding.
    Nel precedente post "Ancora databinding su WPF" si è visto come (attraverso le risorse della classe Window - Window.Resources) è possibile  dichiarare un oggetto come risorsa statica, e, grazie al tag x:key, qualsiasi controllo è in grado di referenziarlo come sorgente dati, permettendo all'engine di WPF di istanziare l'oggetto richiamando il suo costruttore base.

    In alcuni scenari, nei quali non si vuole perdere l'approccio dichiarativo messo a disposizione da XAML, ma che richiedono comportamenti particolari, come il richiamo di costruttori specializzati o metodi con parametri dell'oggetto, WPF fornice la classe ObjectDataProvider.Questa Classe non fa altro che incapsulare la risorsa statica e fornire gli strumenti per interoperare con essa.

    Riprendiamo la configurazione precedente della risorsa statica mySource che referenziava la classe mySource scritta in c#

    <Window.Resources>

           <local:mySource x:Key="mySource"/>

    </Window.Resources>

    Per incapsulare la risorsa basta aggiungere

    <Window.Resources>

             <local:mySource x:Key="mySource"/>
             <ObjectDataProvider x:Key="dataProvider"  ObjectType="{x:Type local:mySource}"/>

    </Window.Resources>

    Dal codice precedente si vede subito che anche l'ObjectDataProvaider è stato definito come risorsa statica, e che può essere referenziato grazie alla sua chiave dataProvider, definita attraverso il tag x:Key.
    A questo punto  si può effettuare il binding attraverso l'ObjectDataProvider, che si occuperà di istanziare la risorsa mySource che sta incapsulando.
    L'esempio del precedente post diventa così

    <ListView ItemsSource="{Binding Source={StaticResource dataProvider}}">

    Da notare che l'applicazione continua a funzionare come in precedenza.
    Fino ad ora non abbiamo visto nulla di interessante, infatti per vedere le potenzialità di questo oggetto dobbiamo fare qualche modifica alla nostra classe sorgente dati, aggiungendo un secondo costruttore che accetta un parametro di tipo int e un metodo che accetta anche'esso un parametro di tipo int.

    public class mySource : ObservableCollection<mySourceItem>
    {
        public mySource()
       {
        }

        //Nuovo costruttore che accetta un parametro int, rappresentante il numero di item da construire
        public mySource(int param)
       {
           for (int i = 0; i <= param; i++)
          {
              this.Add(new mySourceItem("Customer"+i.ToString(), "Customer"+i.ToString()+" Description"));
           }   
        }
      
      //Metodo che inizializza una nuova classe mySource con un numero di item definito dal paramtro param
        public mySource GetItems(int param)
        {

           mySource _mySourse = new mySource();
           for (int i = 0; i <= param; i++)
           {

              _mySourse.Add(new mySourceItem("Customer" + i.ToString(),
               "Customer" + i.ToString() + " Description"));
           }
           return _mySourse;
        }

    }

    Benché non ha molto senso creare un metodo che realizzi una nuova istanza della stessa classe, è stato aggiunto solo per facilitare questo esempio.

    Utilizzando la proprietà CostructorParameters dell' ObjectDataProvider  che accetta una collezione di oggetti, possiamo stabilire quale costruttore prendere attraverso la firma dei suo parametri.

    L'esempio diventa:

    <Window.Resources>
            <ObjectDataProvider x:Key="dataProvider" ObjectType="{x:Type local:mySource}">
                <ObjectDataProvider.ConstructorParameters>
                    <sys:Int32>4</sys:Int32>
                </ObjectDataProvider.ConstructorParameters>
            </ObjectDataProvider>
    </Window.Resources>

    Ogni parametro è referenziato con il suo tipo, in questo caso Int32, perciò sul nodo root di Window bisogna aggiungere il namespace dei tipi base del Framework; nota che la chiave sys è puramente arbitraria e può essere cambiata a proprio piacimento.

    xmlns:sys="clr-namespace:System;assembly=mscorlib"

    Se mandiamo in esecuzione il programma si noterà che il nostro ListView è costituito da quattro Item, proprio perché ha utilizzato il costruttore custom, seguendo la sequenza dei parametri, passandogli il numero 4.

    Analogamente l'ObjectDataProvider ci fornisce la possibilità di chiamare un metodo della classe che incapsula al suo interno , utilizzando la proprietà MethodName e passandogli  i propri parametri grazie alla proprietà MethodParameters  che accetta una collezione di oggetti.
    L'esempio precedente diventa

    <Window.Resources>
            <ObjectDataProvider x:Key="dataProvider" ObjectType="{x:Type local:mySource}" MethodName="GetItems">
              <ObjectDataProvider.MethodParameters>
                  <sys:Int32>4</sys:Int32>
               </ObjectDataProvider.MethodParameters>
           </ObjectDataProvider>
    </Window.Resources>

    Potete scaricare la soluzione d'esempio realizzata con Visual Studio 2008 :
    ODPDemo.zip

     

dotNet Umbria 2007-2008
Powered by Community Server (Commercial Edition), by Telligent Systems