WPF, LINQ e DataBinding

WPF, LINQ e Binding
Con questo articolo voglio giocare con un paio di nuone tecnologie offerte da Microsoft.
Seguendo l’esempio offerto da Beatriz Costa al TechEd 2008, ho sviluppato qualcosa di analogo.
Librerie e Libri
L’esempio in se non è nulla di complicato ma è bello poter vedere in azione queste nuove tecnologie.
Il progetto che andremo a realizzare con VS2008 sarà un WPF Browser Application.
La nostra pagina principale sarà Page1.xaml e aggiungeremo solamente 3 files in più al progetto:
 
XMLFile1.xml
Questo sarà il nostro file d’appoggio, il quale conterrà le informazioni che vogliamo presentare all’utente.
Parte del contenuto di questo file si presenta così:
<ListBooks>
<BookObjectTitle="Extreme Programming Explained: Embrace Change">
<
ImageFileName>Images\xp_guide_small.jpg</ImageFileName>
<
Author>Kent Beck</Author>
<
Published>25 Nov 2004</Published>
</BookObject>
Notate, avrete bisogno di una directory Images dove dovrete andare a inserire l’immagine da caricare relativa al libro.
BookObject
Questa è una semplicissima classe contenitore che useremo per definire un libro all’interno della nostra libreria.
    public class BookObject
    {
        public string Title { get; set; }
        public string ImageFileName { get; set; }
        public string Author { get; set; }
        public string Published { get; set; }
 
        public override string ToString()
        {
            return Title + " " + Author;
        }
    }
 
Library
Finalmente un pò di codice.
    public class Library
    {
        public Library()
        {
            Uri res = new Uri(@"pack://application:,,,/XMLFile1.xml", UriKind.Absolute);
 
            // The Application object wraps a set of XAML files and creates a shared data environment between the
            // pages. The Application object loads with the initial load and provides shared variables at that time.
            StreamResourceInfo sri = App.GetResourceStream(res);
            StreamReader reader = new StreamReader(sri.Stream);
            XDocument booksXml = XDocument.Load(reader);
 
            _libraryObjects = new List<BookObject>();
 
            var book = from books in booksXml.Descendants("BookObject")
                       select new BookObject
                       {
                           Title = books.Attribute("Title").Value,
                           ImageFileName = books.Element("ImageFileName").Value,
                           Author = books.Element("Author").Value,
                           Published = books.Element("Published").Value
                       };
 
            foreach (var bd in book)
                _libraryObjects.Add(bd);
        }
 
        private List<BookObject> _libraryObjects;
        public List<BookObject> LibraryObjects
        {
           get { return _libraryObjects; }
        }
    }
 
Analizziamo nel dettaglio il lavoro di questa classe.
Per prima cosa dovrà aprire il nostro file XMLFile1.xml e leggerne il contenuto.

Per motivi di sicurezza i progetti di questo tipo, Browser Application, non hanno diritti di lettura e scrittura sul nostro file system se non nelle directory utilizzate da IsolatedStorageFile.
Per questo motivo dovremo specificare nelle proprietà del XMLFile1.xml:
·         Build Action: Resource
In questa maniera il file verrà inserito all’interno del nostro eseguibile e sarà disponibile per la lettura.

Per poter leggere il file, WPF, mette a disposizione le
URI (uniform resource identifiers).
Quindi specificheremo un nuovo URI, puntando sul file all’interno della nostra applicazione.
Avendo adesso il riferimento al nostro file, dobbiamo farlo leggere a LINQ che non è a conoscenza di come sono organizzate le nostre risorse.
Quindi andremo a prendere la risorsa tramite la classe Application.
La classe Application è un’interfaccia tra il nostro sistema e l’applicazione. È l’entry point delle nostre applicazioni WPF.
Nel nostro caso specifico, troveremo questa nel file App.xaml.cs
Per ulteriori informazioni
quì.
Acquisito il riferimento al nostro file e creati gli Streams opportuni, lasceremo a LINQ l’arduo compito di leggere i dati all’interno del file.
Questo procedimento è alquanto semplice, almeno nel nostro caso.
Creando una query come quella all’interno del nostro codice, LINQ si occuperà di tirar fuori tutti i dati relativi ai libri presenti nel file XML e inserirà questi dati all’interno della variabile book.
Adesso che abbiamo a disposizione tutti i dati che sono all’interno del nostro file xml, ne inseriremo i riferimenti all’interno della nostra collection:
List<BookObject> _libraryObjects;
 
Page1.xaml
A questo punto la nostra applicazione è pronta all’80%.
Ci rimane solamente da bindare i dati all’interno della nostra pagine XAML e definire come vogliamo visualizzarli.
Per quanto concerne il concetto di bindare i dati all’interno di un’applicazione WPF vi consiglio di vedere il video di Beatriz Costa, il quale vi potrà chiarire le idee.
Sappiate solamente che il binding è una relazione che creiamo tra la nostra UI e la nostra sorgente di dati.

Quello che vedremo in questo tutorial è come bindare dei dati presenti in memoria che vengono modificati durante l’esistenza dell’applicazione.
    <StackPanel x:Name="LayoutRoot" HorizontalAlignment="Center" VerticalAlignment="Top">
        <ListBox ItemsSource="{Binding Source={StaticResource myLibrary}, Path=LibraryObjects}"
            ScrollViewer.VerticalScrollBarVisibility="Auto" Height="480" Width="500" />
        <!--<ComboBox ItemsSource="{Binding Source={StaticResource myLibrary}, Path=LibraryObjects}" SelectedIndex="0"/>-->
    </StackPanel>
Con queste poche righe di XAML noi stiamo già bindando i nostri dati e potrebbero essere già disponibili.
Se non ci credere, provate a completare in questa maniera:
·         Inserite il seguente codice sopra lo StackPanel poc’anzi definito:
    <Page.Resources>
        <local:Library x:Key="myLibrary" />
Ecco adesso la vostra ListBox con i dati bindati.
Già così abbiamo ottenuto ciò che volevamo ma, per concludere, diamo un’aspetto migliore ai nostri dati.
Per far ciò dobbiamo solamente dire a WPF come vogliamo, appunto, visualizzarli.
Per farlo bisogna utilizzare un
DataTemplate.
Il nostro DataTemplate è stato definito nella seguente maniera:
        <DataTemplate DataType="{x:Type local:BookObject}">
            <StackPanel Orientation="Horizontal" Margin="3" TextBlock.FontSize="12" TextBlock.FontFamily="Tahoma">
                <Image Source="{Binding Path=ImageFileName}" Margin="0,0,3,0" />
                <StackPanel Width="500">
                    <TextBlock FontWeight="Bold" Text="{Binding Title}" />
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Author}" />
                        <TextBlock Text="{Binding Published}" />
                    </StackPanel>
                </StackPanel>
            </StackPanel>
        </DataTemplate>
    </Page.Resources>
In pratica stiamo definendo i StackPanel che conterranno i nostri dati, cosa dovranno contenere e come visualizzarli.
Esempio, il primo StackPanel definisce come il testo verrà visualizzato e al suo interno ha un Controllo di tipo Image che viene bindato all’oggetto ImageFileName presente all’interno della classe BookObject.
 
Nel codice ho lasciato commentato un Control di tipo ComboBox.
Provate a decommentare la ComboBox e a commentare la ListBox, e potrete capire come le WPF vi aiuteranno a relazionarvi e come sono strettamente relazionate a pattern quali MVP.
Il progetto completo lo trovate quì.
 
Tags:

posted @ domenica 23 dicembre 2007 12:31

Print

Comments on this entry:

# re: WPF, LINQ e DataBinding

Left by Salvatore at 13/05/2008 19:42
Gravatar
Salve!
Ho trovato molto interessante e ben spiegato il suo esempio. Ho qualche domanda che può aiutarmi a comprendere meglio quanto succede:

1) Il file xml è una risorsa del progetto. Ho provato a creare una seconda versione del suo progetto in cui nella classe Library veniva inserito il path del file xml senza aggiungerlo come risorsa del progetto. Non ha assolutamente funzionato.
2) Se la classe Library avesse ad esempio una proprietà col path del file come si può nel codice xaml creare un'istanza della classe Library specificando tale proprietà

Grazie della sua attenzione

Salvatore
Comments have been closed on this topic.