in

dotNet Umbria

Il primo User Group in Umbria sul mondo .Net

Paolo Possanzini

November 2007 - Posts

  • WCF CompactFramework with PowerToys: Serialization Tips

    Oggi Andrea ha creato una applicazione WCF per CompactFramework, per collegare una applicazione per PPC ad un servizio WCF esposto su un webservice.
    Tutto sembra funzionare correttamente, tranne che per l'invio di alcuni dati da parte del PPC al server.

    Abbiamo scoperto che ogni volta che il palmare incontra un valore nullable, il valore non viene serializzato di default e quindi non viene riportato sul server.
    La classe proxy del servizio generata per l'applicazione PPC,contiene infatti una proprietà aggiuntiva per ogni proprietà Nullable.
    La proprietà (di tipo boleano) si chiama esattamente con lo stesso nome della proprietà base con in più il suffisso "Specified".

    Ogni volta che intendo inviare al servizio un valore nullabile è necessario impostare il valore di tale proprietà a TRUE.
    Altrimenti il client non serializzerà il valore corrispondente all'interno del messaggio e sul server otterrò sempre un valore nullo.

    Dopo ogni assegnazione è quindi necessario inserire una if e se abbiamo effettivamente valorizzato la proprietà dobbiamo inserire un true sulla rispettiva proprietà Specified.

    [code language="C#"]

    if(myentity.myproperty != null)
        myentity.mypropertySpeficied=true;
    else
        myentity.mypropertySpecified=false;

    [/code]

    Il problema probabilmente è un errore di serializzazione della classe proxy, infatti si potrebbe far inserire questa if all'interno del metodo set di ogni proprietà.

  • Operazioni Cross-Thread con WPF

    In una applicazione Windows Forms classica, per evitare il lock dell'applicazione, è buona regola invocare alcune operazioni su Thread paralleli e poi aggiornare l'interfaccia utente durante l'esecuzione del thread con operazioni cross-thread.
    In WPF questa necessità si sente di meno poichè alcune operazioni cross-thread su controlli vengono gestite direttamente dal framework.

    Tuttavia può capitare di dover fare una operazione cross-thread con controlli WPF, per aggiornare un controllo esplicitamente oppure per invocare un metodo di un controllo che è un in thread diverso.
    Mi sono trovato in questa situazione proprio oggi, e non ho trovato il metodo Invoke nella Windows che dovevo aggiornare.

    La mancanza di Invoke si spiega facilmente; WPF infatti non eredita da nessuno dei normali controlli di Windows Forms e quindi manca il metodo Invoke che nella gerarchia degli oggetti è dichiarato dentro System.Windows.Forms.Control
    Tuttavia il controllo o la finestra che stiamo visualizzando si trova in un'altro thread e quindi dovremmo poter effettuare l'invoke.

    La risposta arriva molto presto, in ogni controllo troviamo la proprietà Dispatcher che ci mette a disposizione l'oggetto Dispatcher del thread con cui ogni oggetto è associato.
    Dal Dispatcher possiamo chiamare il metodo Invoke.

  • Ancora databinding su WPF

    Continuiamo a parlare di DataBinding in WPF ed andiamo per gradi.
    Abbiamo visto che è possibile bindare due controlli tra di loro utilizzando la proprietà ElementName della struttura di Binding. Iniziamo a vedere come è possibile bindare una lista di elementi in una listview.

    Creiamo la listview

    [code language="xml"]
    <ListView ItemsSource="{StaticResource mySource}">
    </ListView>
    [/code]

    Utilizzando “ItemsSource” informiamo la nostra ListView che deve utilizzare come sorgente dati, la risorsa statica mySource.

    Per dichiarare la risorsa statica è sufficiente includere questo tag nel tag Window.Resources
    [code language="xml"]
        <Window.Resources>

            <!-- Dichiarazione di una reference ad una classe scritta in c# -->
            <local:mySource x:Key="mySource"/>

        </Window.Resources>
    [/code]

    Attraverso questa definizione, la classe locale mySource verrà instanziata e resa disponibile a tutti gli oggetti all’interno della finestra che stiamo progettando come risorsa statica.
    Dobbiamo dichiarare anche “local”. Local è un riferimento ad uno spazio dei nomi per WPF.
    Includiamo quindi la definizione di local nel tag Window:

    [code language="xml"]
     xmlns:local="clr-namespace:miniSample1" 
    [/code]

    Definiamo la classe mySource, creando una semplice classe C# in questo modo:

    [code language="C#"]
      public class mySource : ObservableCollection<string>
      {
        public mySource()
        {
          this.Add("Customer1");
          this.Add("Customer1");
          this.Add("Customer1");
          this.Add("Customer1");
          this.Add("Customer1");

        }
      }
      [/code]

    La nostra sorgente dati eredita da ObservableCollection, una classe base che ci mette a disposizione una serie di funzioni di ordinamento e raggruppamento per i nostri dati. Il dato sarà composto da una semplice stringa.

    Abbiamo ottenuto una  lista di stringhe all’interno di una listview e fin qui nulla di nuovo a parte la sintassi di WPF. Possiamo tuttavia modificare a piacimento il look dei nostri controlli e quindi possiamo rendere gradevole e leggermente più complessa la nostra lista.

    Per cominciare aggiungiamo un po’ di dati, modificando la nostra sorgente dati, in modo da avere qualcosa in più da bindare.


    [code language="C#"]
      public class mySourceItem
      {
        private string _title = string.Empty;
        private string _description = string.Empty;

        public string Title
        {
          get
          { return _title; }
          set
          { _title = value; }
        }

        public string Description
        {
          get
          { return _description; }
          set
          { _description = value; }
        }

        public mySourceItem(string title, string description)
        {
          _title = title;
          _description = description;

        }
      }

      public class mySource : ObservableCollection<mySourceItem>
      {
        public mySource()
        {
          this.Add(new mySourceItem("Customer1", "Customer1 Description"));
          this.Add(new mySourceItem("Customer2", "Customer2 Description"));
          this.Add(new mySourceItem("Customer3", "Customer3 Description"));
          this.Add(new mySourceItem("Customer4", "Customer4 Description"));
          this.Add(new mySourceItem("Customer5", "Customer5 Description"));
        }
      }
      [/code]

    Abbiamo creato una DataEntity che contiene due proprietà. La sorgente dati sarà una collection di DataEntity. Se colleghiamo questa collection alla nostra listview otterremo soltanto un elenco di questo tipo: “minisample1.mySourceItem”. Questo accade perché listview non sa come estrarre i dati dalla nostra collection e quindi invoca in metodo ToString() di ogni singolo elemento. Dobbiamo quindi istruire la listview su come visualizzare il nostro elemento.

    [code language="xml"]
    <ListView ItemsSource="{StaticResource mySource}">
    <!-- DataTemplate : Definiamo l'aspetto dei nostri dati -->
    <ListView.ItemTemplate>
        <DataTemplate>
            <!-- Binding : Visualizziamo come contenuto l'intero oggetto {Binding} (La sorgente dati è una collection di stringhe ) -->
            <TextBlock FontSize="24" FontFamily="Calibri" Text="{Binding Path=Title}" />
            <TextBlock FontSize="24" FontFamily="Calibri" Text="{Binding Path=Description}" />

        </DataTemplate>
    </ListView.ItemTemplate>
    </ListView>
    [/code]

    All’interno del tag DataTemplate definiamo come ogni singolo elemento deve essere visualizzato.
    Definiamo il look dei nostri elementi con i normali tag WPF, in questo caso TextBlock, e definiamo dove ogni proprietà deve essere utilizzata attraverso la struttura  {Binding Path=<proprietà>}.

  • E' uscito Visual Studio 2008

    E' uscita la versione RTM (Release to Market) di Visual Studio 2008. Ed è disponibile in download ai possessori di un abbonamento msdn.

  • wpf databinding parte 1

    WPF è il nuovo standard per la realizzazione della interfaccia grafica delle nostre applicazioni. E’ nato per molteplici motivi, uno dei quali è la necessità di dividere lo strato di presentazione dei dati dallo sviluppo dell’applicazione stessa. Un parte molto interessante è il Binding dei dati all’interno delle applicazioni WPF, e insieme al binding non possiamo non menzionare i DataTemplate.  Il Binding è una operazione solitamente svolta dai programmatori ma che adesso deve essere accessibile anche in parte al grafico che sta lavorando al look della mia applicazione. Andiamo a vedere come funziona facendo qualche confronto con il mondo Windows Form tradizionale che ormai ci accompagna da un ventennio.

    Iniziamo subito con alcuni esempi, e associamo una sorgente dati alla proprietà Text di una TextBox.
    Se utilizziamo Visual Studio 2005, probabilmente faremo questa operazione dal PropertyGrid che ci genererà il seguente codice:

    [code language="C#"] this.textBox1.DataBindings.Add(new Binding("Text", myDataSource, "Value")); [/code]

    dove “Text” è la proprietà della textbox che vogliamo associare alla sorgente dati “myDataSource” e “Value”  è il dato da associare. Ovviamente possiamo scrivere direttamente noi il codice per il binding.

    In WPF possiamo fare tutto da xaml in questo modo:

    [code language="ASPX"] <TextBox Text="{Binding Source=myDataSource,Path=Value}" /> [/code]


    Il vantaggio immediato è la possibilità per il grafico di poter implementare direttamente tutta l’interfaccia utente senza andare a scrivere codice, ma utilizzando una sintassi che probabilmente già conosce. Infatti xaml è basato su xml ed eredita inoltre molti concetti del mondo Web.

    Torniamo al Binding. Nell’esempio abbiamo inserito all’interno della proprietà Text una struttura compresa tra due graffe (detta MarkupExtension). Siamo andati direttamente ad indicare la sorgente dati e il valore da associare. A runtime questa struttura verrà tradotta nella struttura vera e propria di binding.

    La MarkupExtension è ci permette di scrivere in modo molto compatto qualcosa che altrimenti sarebbe articolato e scomodo da scrivere. Il Parser di WPF traduce il primo elemento della MarkupExtension in una classe  e i successivi elementi in proprietà della classe stessa. Nel nostro caso la struttura

    [code language="ASPX"] {Binding Source=myDataSource,Path=Value} [/code]

    verrà tradotta dal parser nel codice per instanziare la classe Binding ed assegnare le proprietà Source e Path dell’oggetto creato. Questo ci lascia intuire che possiamo continuare a popolare le proprietà della classe Binding direttamente da xaml. Iniziamo a chiederci che cosa possiamo utilizzare come sorgente dati; la risposta è TUTTO, o quasi; in generale possiamo utilizzare ogni oggetto che implementa INotifyChanges o le cui proprietà sono delle DependencyProperties (la stragrande maggioranza di oggetti in WPF implementano le proprietà come DependencyProperty).

    Quindi possiamo utilizzare oltre a collections, classi custom, DataSet, DataEntity, WebService ed altro, anche oggetti della interfaccia utente come sorgente dati.

    [code language="ASPX"] <Slider Height="26" Name="MySlider" Width="193" />
    <TextBox Text="{Binding ElementName=MySlider,Path=Value}" Height="30" Width="100"/> [/code]

    In questo codice è stato utilizzato un elemento della UI come Sorgente dati di un altro elemento. In questo caso specifico WPF ci viene in aiuto e ci permette di indicare un elemento della interfaccia grafica che fa da sorgente dati attraverso il suo nome con la proprietà “ElementName”. In questo esempio, che ormai è diventato un classico, uno slider visualizza il suo valore attuale nella TextBox. Ad ogni modifica dello slider, vedremo il valore cambiare nella TextBox.

     

  • Errata Corrige in MSDN

     

    Nella pagina di MSDN che parla della configurazione dei servizi di WCF.
    http://msdn2.microsoft.com/en-us/library/ms789018.aspx

    E' presente un piccolo errore di battitura, infatti la configurazione dei baseAddresses del servizio non va fatta utilizzando l'elemento baseAddress come indicato nella documentazione ma utilizzando l'elemento Add.

    Codice Errato:

    <host>

          <baseAddresses>

                <baseAddress baseAddress="string" />

          </baseAddresses>

    </host>

     


    Codice Esatto:

    <host>

          <baseAddresses>

                <add baseAddress="string" />

          </baseAddresses>

    </host>

    Spero di avervi evitato un po' di grattacapi.

    Paolo

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