[1] Il ritorno dello HockeyPlayer (data-binding con WPF)

Vi ricordate la mia piccola serie di post su NHibernate che parlava di giocatori di hockey? In breve: si trattava di persistere una classe HockeyPlayer su database, usando NHibernate come DAL. E’ sufficiente googlare per raggiungere il primo post della serie. Voglio riprendere le stesse classi viste allora per introdurre i concetti base che ruotano attorno al meccanismo di data-binding di WPF e soprattutto per confermare (più a me stesso che a voi) che Corrado ha pienamente ragione quando dice che le proprietà di una classe non devono per forza essere dependency properties per fungere da sorgente per il binding.

Vediamo di sviscerare pian piano il mistero. Supponiamo di avere un domain model il cui SuperType (a type that acts as the supertype for all types in its layer) è rappresentato dalla classe AbstractEntity, che è implementata nel modo seguente:

public abstract class AbstractEntity : INotifyPropertyChanged { private int id; public int ID { get { return id; } set { id = value; NotifyPropertyChanged("ID"); } } // Definizione del public event // e del metodo NotifyPropertyChanged }

Questa è una classe astratta, dalla quale derivano le classi concrete che compongono il domain model della nostra applicazione. Per questo piccolo esempio, supponiamo di avere una sola semplice classe, HockeyPlayer appunto, che deriva da AbstractEntity e aggiunge qualche proprietà pubblica. Il codice è il seguente:

public class HockeyPlayer : AbstractEntity, INotifyPropertyChanged { private string name; private int height, weight, number; public string Name { get { return name; } set { name = value; NotifyPropertyChanged("Name"); } } public int Height { get { return height; } set { height = value; NotifyPropertyChanged("Height"); } } // Definizione delle altre proprietà (Weight e Number), }

Per brevità, ho omesso parte del codice. Per adesso, ci interessa sapere che HockeyPlayer espone quattro proprietà: Name, Height, Weight, Number (rispettivamente: nome, altezza, peso e numero di maglia). La cosa che voglio sottolineare è che queste proprietà sono proprietà normalissime, non hanno alcuna dipendenza con WPF. Se dovessimo sviluppare questa applicazione per console, per Windows Form, per ASP.Net, per un Windows Service, la implementeremmo nella stessa maniera. Altra cosa da sottolineare è che non è stato fatto l’override di ToString(). Per comodità ho implementato anche una classe HockeyPlayers (notare la ‘s’ finale), che non è nient’altro che una List<HockeyPlayer>: ci servirà con WPF più avanti.

Ok, passiamo ad aggiungere al progetto una Window molto molto semplice. Lo XAML è:

<Window x:Class="MyItemTemplate.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MyItemTemplate" Loaded="Window1_Loaded"> <StackPanel> <ListBox Name="lstPlayers" /> </StackPanel> </Window>

In pratica, è una Window che contiene uno StackPanel che a sua volta contiene una ListBox lstPlayers. Nel code-behind buttiamo giù due linee di codice per popolare la ListBox con un po’ di HockeyPlayer sparati a caso:

void Window1_Loaded(object sender, RoutedEventArgs e) { HockeyPlayer pl; for (int i = 0; i < 10; i++) { pl = new HockeyPlayer("Name " + i, 180 + i, 96 + i, 14 + i); lstPlayers.Items.Add(pl); } }

Sull’evento Loaded della Window faccia partire un ciclo for che crea 10 istanze di HockeyPlayer, con un po’ di valori a caso. Utilizzo il costruttore con quattro parametri per brevità di scrittura (l’ho fatto apposta!). Se eseguiamo il codice apparirà una Window fatta nel modo seguente:

Veramente brutta, vero? E poi, perchè appare quella schifezza invece di qualcosa di più sensato? Questo comportamento non è proprio di WPF, perciò non date la colpa a lui. La responsabilità è di .NET. Sta di fatto che avremmo ottenuto esattamente la stessa cosa se avessimo realizzato una tradizionale Windows Form. Il CLR non sa come convertire una nostra classe in stringa, perchè nessuno gli dice come fare: in preda al dubbio, .NET se la cava mostrando banalmente il nome completo della classe, inteso come namespace.classname. Io non ve l’ho detto, ma tutto il progetto si trova nel namespace MyItemTemplate, da cui il motivo dei 10 Items che appaiono qui sopra. Ci sono diversi modi per risolvere questo punto: il più breve (che non è quasi mai il più divertente) consiste nel fare l’override di ToString() all’interno della nostra classe HockeyPlayer. Se per esempio volessimo visualizzare il nome del giocatore, è sufficiente scrivere quanto segue:

public override string ToString() { return name; }

Se rilanciassimo l’applicazione, al posto di MyItemTemplate.HockeyPlayer, vedremmo il nome di ciascun giocatore, nel nostro caso 10 stringhe che vanno da “Name 0” a “Name 9”. Non è il massimo comunque, forse un pochino meglio, ma per adesso ci fermiamo qui.

Send to Kindle

XAML è un XML, non è solo di WPF e soprattutto non è lento…

Con questo piccolo post voglio sfatare diversi miti. Non mi sto inventando nulla, altre persone molto più illustri di me l’hanno già ribadito, ma voglio scrivermelo anche io per dirlo principalmente a chi legge il mio blog. Nel mio blog ho parlato nei giorni scorsi di WPF (Windows Presentation Foundation), perchè è una tecnologia che mi affascina e che ritengo estremamente potente. Parlando di WPF, non si può non parlare di XAML. Ma cos’è davvero XAML?

XAML è un dialetto XML. Come ogni XML, deve essere ben formattato, ogni tag aperto deve avere il suo tag di chiusura e roba del genere. XAML è un XML introdotto nel FX3.0 di Microsoft e non riguarda solo WPF. XAML serve anche a WPF, ma per esempio anche a WF: lo ha chiaramente indicato Raffaele durante il meeting di XeDotNet.

Ma siccome qui stiamo parlando di WPF, cos’è XAML nel contesto di WPF ?

XAML serve a descrivere una gerarchia di oggetti, ma non solo visuali. Perciò dire che XAML serve a descrivere l’interfaccia utente è solo parzialmente vero. XAML può essere utilizzato anche per esprimere altri contenuti, come risorse di ogni tipo (occhio: davvero di ogni tipo), comportamenti, triggers, stili, animazioni, pannelli custom, trasformazioni grafiche, data-binding, altre classi .NET che a run-time saranno – magari – invisibili e via dicendo. XAML serve a definire una Window, una Page od uno UserControl nella sua interezza, quindi, e non solo per quanto riguarda il suo aspetto grafico.

L’ultima cosa che voglio dire è che la lunghezza di un file XAML non ha alcuna correlazione con le dimensioni dell’assembly che verrà generato. Un file XAML può anche essere immenso, perchè l’XML è un po’ prolisso e XAML ha una sintassi che magari non aiuta in questo senso. Però francamente preferisco leggere XAML che almeno è chiaro e semplice. Magari è questione di abitudine. Voglio ricordare che ciascun file XAML viene compilato per ottenere il corrispondente file BAML (Binary Application Markup Language). Come dice Nathan…

BAML is a compressed declarative format that is faster to load and parse (and smaller in size) than plain XAML.

In altre parole, XAML è efficiente quando stiamo sviluppando, perchè è leggibile, chiaro e semplice. BAML è efficiente a run-time, perchè è compresso e più piccolo in termini di bytes (e forse questo è quello che ci interessa di più).

Che poi su determinati PC un’applicazione WPF sia lenta dipende da una miliardata di motivi, dalla scheda grafica (hardware) a cosa fa realmente l’applicazione mentre è aperta e sta girando (software)…

Send to Kindle

[Flickr.4] Usare la ListBox di WPF con binding ed ItemTemplate

Questa volta arrivo subito al sodo. Nell’ultimo post avevamo ottenuto l’elenco dei set fotografici associati ad un particolare utente. Lo scopo è quello di elencare questi set in qualche modo e di farli vedere in maniera gradevole all’utente che sta usando la nostra applicazione. La window principale si chiama MainWindow e questo è il suo XAML (non completo):

<Grid> <Grid.RowDefinitions> <RowDefinition Height="50" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Grid.Row="0" VerticalAlignment="Center"> <TextBox Name="UsernameTextBox" Text="IgorDamiani" Width="150" Margin="4" /> <b:FlickrButton x:Name="ListPhotoSets" Content=" List Photo Sets " Margin="4" Click="listPhotosets" /> <b:FlickrButton x:Name="WebToUserPhotos" Content=" See User's Photos " Margin="4" Click="webToUserPhotos" IsEnabled="False" /> <b:FlickrButton x:Name="WebToUserWorldMap" Content=" See User's World Map " Margin="4" Click="webToUserWorldMap" IsEnabled="False" /> </StackPanel> <ListBox Name="PhotoSetListBox" Grid.Row="1" MouseDoubleClick="PhotoSetListBox_MouseDoubleClick" ItemsSource="{Binding Source={StaticResource sets}, Path=FlickrBrowserPhotoset}" /> </Grid>

Lo XAML è concettualmente piuttosto semplice. In pratica, contiene una Grid con due sole righe. La prima ha un’altezza fissa e contiene uno StackPanel orizzontale che a sua volta contiene una TextBox e tre FlickrButton. La TextBox serve per ricercare un utente attraverso il suo username. Il primo FlickrButton è quello che ci interessa di più, perchè una volta cliccato ricerca i set fotografici dell’utente e li visualizza nella ListBox che si trova nella seconda riga della Grid. Gli altri due FlickrButton raggiungono due Url differenti: per adesso possiamo bellamente ignorarli.

Quello che ci interessa in questo momento sono tre cose: la TextBox UsernameTextBox, il FlickrButton ListPhotoSets e la ListBox PhotoSetListBox. Dall’interazione di questi tre controlli nasce l’applicazione vera e propria.

Se diamo un’occhiata al post precedente, vediamo come il popolamento della ListBox avviene attraverso l’impostazione della sua proprietà ItemsSource. Il valore assunto da questa proprietà è un oggetto di tipo FlickrBrowserPhotosetCollection, che è una classe che semplicemente è una List<FlickrBrowserPhotoset>. La classe FlickrBrowserPhotoSet espone una proprietà Title (titolo del set fotografico), NumberOfPhotos (Numero di foto nel set), PrimaryPhotoUrl (url della foto che fa da copertina al set), PhotosetSquareThumbnailUrl e Photos. Queste ultime due per adesso non sono utilizzate.

Questo per dire che possiamo lavorare sulla proprietà ItemTemplate della ListBox, specificando l’aspetto che ogni riga della ListBox deve assumere. Con aspetto intendo per esempio un pannello, che contiene altri pannelli, altri controlli e sui quali possiamo definire stili, triggers e tutto il resto. Diamo ancora una volta un’occhiata allo XAML sopra, nel punto in cui viene dichiarata la ListBox: viene specificato che la sorgente di ItemsSource è la risorsa statica sets, e viene specificato che ogni elemento aggiunto alla ListBox sarà di tipo FlickrBrowserPhotoset. Questo è importante, perchè dentro il template faremo un po’ di binding indicando la proprietà che ogni controllo deve visualizzare. Ultima nota: la risorsa sets viene popolato dal code-behind in C#, l’abbiamo visto l’altra volta. Un piccolo rimando è necessario per ricordarcelo:

FlickrBrowserPhotosetCollection setFoto = (FlickrBrowserPhotosetCollection) this.FindResource("sets"); // Popolo setFoto // ... // Assegno ItemsSource PhotoSetListBox.ItemsSource = setFoto;

Con i metodo FindResource ottengo l’istanza di FlickrBrowserPhotosetCollection. Poi popolo l’oggetto setFoto con tutti i set fotografici che mi servono e poi assegno ItemsSource. Ne abbiamo parlato l’altra volta, perciò chiudo qui.

L’ultima cosa che voglio far vedere è lo XAML che definisce il template che il runtime di WPF utilizza per disegnare ogni Item aggiunto alla ListBox:

<Style TargetType="{x:Type ListBox}"> <Setter Property="ItemTemplate"> <Setter.Value> <DataTemplate> <StackPanel Margin="4" Orientation="Horizontal"> <Image Margin="4"> <Image.Source> <Binding Path="PrimaryPhotoUrl" /> </Image.Source> </Image> <StackPanel Margin="4" Orientation="Vertical"> <TextBlock Margin="4" FontSize="14pt" Text="{Binding Path=Title}"/> <StackPanel Margin="4" Orientation="Horizontal"> <TextBlock Margin="4" FontSize="10pt" Text="Number of Photos :"/> <TextBlock Margin="4" FontSize="10pt" Text="{Binding Path=NumberOfPhotos}"/> </StackPanel> <StackPanel Margin="4" Orientation="Horizontal"> <TextBlock Margin="4" FontSize="10pt" Text="Thumbnail Url :"/> <TextBlock Margin="4" FontSize="10pt" Text="{Binding Path=PhotosetSquareThumbnailUrl}"/> </StackPanel> <TextBox Text="Drag here to upload new images" Background="LightCoral" Name="txtUpload" IsReadOnly="True" PreviewDragOver="ehDragOver" PreviewDrop="ehDrop" PreviewDragLeave="ehDragLeave" /> </StackPanel> </StackPanel> </DataTemplate> </Setter.Value> </Setter> </Style>

Lo XAML è lungo, ma vi posso assicurare che fare la stessa cosa con normale C# sarebbe un incubo. Ogni item viene disegnato con uno StackPanel che contiene un Image ed un altro StackPanel sulla sua destra. La morale è: visualizzo un certo numero di TextBox che vengono bindate alle diverse proprietà pubbliche esposte dalla classe FlickrBrowserPhotoset di cui parlavamo prima. Il risultato è inquietante…eccolo…

Farà anche schifo, ma una volta un impatto simile nelle applicazioni non riuscivo a darlo nemmeno se sudava quattro camicie. In realtà sto già lavorando ad altre features interessanti, come la possibilità di uploadare nuove foto e di inserirle dentro un set (nuovo o già esistente) tramite drag’n’drop, di ricercare foto le foto di un utente dato un particolare tag e roba del genere.

A presto, metterò disponibile il download di codice ed applicazione. Stay tuned!

Send to Kindle

[Flickr.3] Ricercare un utente ed ottenere i suoi set fotografici

Questo post è stato scritto durante il viaggio di andata all’evento di XeDotNet di questa sera. Giusto per cronaca. 🙂

Entriamo nel vivo
Ok, lasciamo da parte le sciocchezze sull’autenticazione di cui abbiamo parlato fino a ieri e vediamo qualcosa di più succulento. Dicevamo ieri che la finestra principale dell’applicazione è rappresentata dalla classe MainWindow. Quando l’applicazione è in esecuzione, possiamo inserire in una TextBox lo username di un utente su Flickr. Se l’utente esiste, possiamo vedere in una ListView i suoi sets di fotografie, oppure possiamo raggiungere la world map dell’utente stesso. Visivamente parlando, la windows si presenta in questo modo:

La cosa su cui voglio focalizzarmi è come riuscire a sfruttare la ListView in modo tale che ogni ListItem venga visualizzato in modo radicalemente diverso a quanto siamo abituati a vedere. Come tutte le ListView che si rispettino, anche quelle in WPF possono essere ovviamente popolate in due modi diversi:

  • aggiungendo a mano tanti ListItem attraverso il metodo Add esposto dalla proprietà Items. Per chi mi sta leggendo e non sa assolutamente nulla di WPF nè tantomeno di .NET: sappiate che potete aggiungere item di qualsiasi tipo, dal momento che il parametro in input al metodo Add è un generico object. Cosa viene visualizzato effettivamente in esecuzione dipende da molte cose: prima fra tutte, se è stato fatto o meno l’override del metodo ToString() della classe che stiamo aggiungendo alla ListView.
  • impostando la proprietà ItemsSource della ListView, che è tipo IEnumerable. Questo significa sfruttare il data-binding di WPF

Nell’esempio utilizzeremo il secondo metodo, che è quello più efficiente. Vediamo come fare.

Ottenere l’elenco dei set di fotografie associati ad un utente
Facciamo mente locale sull’immagine sopra. C’è una TextBox nella quale scrivere lo username dell’utente che ci interessa. Poi c’è un Button con una bella caption che dice: “List Photo Sets”. Vediamo come viene gestito il Click su questo Button che svela buona parte dell’arcano.

public void listPhotosets(object sender, RoutedEventArgs e) { if (conn == null) return; #region Trovo l'utente indicato nella TextBox try { currentUser = conn.PeopleFindByUsername(UsernameTextBox.Text); currentUserUri = conn.UrlsGetUserPhotos(currentUser.UserId); } catch (FlickrException ex) { MessageBox.Show("Username not found!", "Error...", MessageBoxButton.OK, MessageBoxImage.Error); return; } #endregion WebToUserPhotos.IsEnabled = (currentUserUri != null); WebToUserWorldMap.IsEnabled = (currentUserUri != null); // Leggo i sets di foto attualmente presenti Photosets sets = conn.PhotosetsGetList(currentUser.UserId); FlickrBrowserPhotosetCollection setFoto = (FlickrBrowserPhotosetCollection) this.FindResource("sets"); PhotoSetListBox.BeginInit(); PhotoSetListBox.ItemsSource = null; foreach (Photoset p in sets.PhotosetCollection) { FlickrBrowserPhotoset ps = new FlickrBrowserPhotoset(conn, p); setFoto.Add(ps); } PhotoSetListBox.ItemsSource = setFoto; PhotoSetListBox.EndInit(); }

Il codice è un po’ lungo, questa volta, ma piuttosto semplice da leggere. La prima cosa che dobbiamo fare è reperire un’istanza della classe FlickrUser, che ci dà un riferimento all’utente che è stato ricercato. Supponiamo di cercare l’utente “Igor Damiani”, come nell’esempio sopra. Salviamo in due field privati currentUser e currentUserUri l’utente corrente e l’url dell’utente su Flickr. Questo url ci servirà la prossima volta: ricordatevelo. 🙂

Se lo username specificato non esiste, le API di Flickr sollevano un’eccezione di tipo FlickrException che viene opportunamente trappata per poter dare all’utente un messaggio di errore che possa dire: “Che cavolo hai scritto????!”. 🙂 Nulla di che.

Terminata questa prima fase, posso richiedere a Flickr l’elenco dei sets di fotografie appartenenti all’utente. Lo facciamo con una sola semplice riga:

Photosets sets = conn.PhotosetsGetList(currentUser.UserId);

L’oggetto sets è ovviamente una collection di qualche tipo. Poi vado a prelevare dalle risorse della MainWindow un oggetto di tipo FlickrBrowserPhotosetCollection attraverso il metodo FindResource(). Indipendentemente da quello che andrò poi a fare sulla ListView, chiamo sempre i metodi BeginInit() all’inizio e EndInit() alla fine. Come si vede dal codice, vado a settare la proprietà ItemsSource dalla ListView sull’oggetto setFoto, che è una collection che viene popolato con un ciclo for…each per ciascun set di fotografie associato.

Un’altra parte dell’arcano sta in due parti: nello XAML (ovviamente) ed in un paio di classi che sono state create apposta per vivere all’interno del contesto di una Window di WPF. Queste classi derivano da DependencyObject e le loro proprietà pubbliche sono DependencyProperty: questo per permettere loro di essere utilizzate con l’engine di data-binding di WPF, appunto. Queste classi compaiono nel codice qui sopra e cominciano tutte e due per FlickrBrowser. La prima è FlickrBrowserPhotoset (che rappresenta un singolo set) e la seconda è FlickrBrowserPhotosetCollection che non è nient’altro che una List<FlickrBrowserPhotoset>.

Conclusione
Quello di cui vorrei parlare la prossima volta è chiaccherare un pochino sullo XAML della MainWindow. E’ lì che si nascondono (mica tanto) il data-binding, il template associato ad ogni ListItem ed altre cosucce interessanti. Alla prossima!

Send to Kindle

[Flickr.2] Startup dell’applicazione in WPF

Per questo primo esperimento, non ho grandi pretese. Voglio un’applicazione Windows che si connetta a Flickr e che permetta di sfogliare i sets di un certo utente, con tutte le sue foto. Il tutto in WPF, ovviamente. I concetti base li abbiamo visti ieri nel precedente post.

Il progetto che ho costruito fino ad adesso comprende due sole Window: MainWindow (la window principale dell’applicazione) e WaitingWindow (la window che appare all’avvio per autenticare l’applicazione). Il file app.xaml è definito nel modo seguente:

<Application x:Class="FlickrBrowser.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml"> </Application>

Non ci sono risorse a livello applicazione, ed inoltre si deduce che la window che parte è proprio la MainWindow.
Il costruttore di tale classe è molto semplice:

public MainWindow() { InitializeComponent(); authenticate(); }

Il metodo privato authenticate() apre una seconda Window, che esamineremo adesso. Lo scopo di questa window è quello di fare tutto quello che abbiamo detto la volta scorsa, ovvero: connettersi a Flickr, richiedere un frob, apre il browser per autenticare l’applicazione e dare il consenso. Roba già dette, insomma.

La window WaitingWindow
Questa window appare all’avvio e ci mostra due Button: il primo apre un browser ad un certo url, il secondo accede a Flickr con le credenziali che sono state autorizzate. Lo XAML che definisce la window è:

<Window x:Class="FlickrBrowser.WaitingWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:b="clr-namespace:FlickrBrowser" Title="Permission" Width="260" Height="138" WindowStartupLocation="CenterScreen" ResizeMode="NoResize"> <StackPanel Orientation="Vertical"> <b:FlickrButton Width="240" Margin="6" x:Name="openBrowserButton" Height="40"> <Button.Content> <TextBlock HorizontalAlignment="Center" Text="Open the browser!"> </TextBlock> </Button.Content> </b:FlickrButton> <b:FlickrButton Width="240" Margin="6" x:Name="closeWindowButton" Height="40" IsEnabled="False"> <Button.Content> <TextBlock HorizontalAlignment="Center" Text="Ok, I've authenticated this application!"> </TextBlock> </Button.Content> </b:FlickrButton> </StackPanel> </Window>

C’è uno StackPanel verticale e due Button. I Button non sono quelli classici di WPF, ma sono FlickrButton: una classe che eredita da Button ma ne specifica alcuni comportamenti. Non ci interessa in questo momento capire il perchè ed il percome: ci basti sapere che funzionano esattamente come due normalissimi Button. Per inserirli nello XAML, ho dovuto inserire un riferimento all’assembly FlickrBrowser, identificandolo con il prefisso b. Il costruttore della WaitingWindow è il seguente:

public WaitingWindow() { InitializeComponent(); conn = new Flickr(apiKey, secretKey); openBrowserButton.Click += new RoutedEventHandler(openBrowserButton_Click); closeWindowButton.Click += new RoutedEventHandler(closeWindowButton_Click); }

Ovvero: si connette a Flickr usando api key e secret key ed associa due event-handler ai due pulsanti (avrei potuto ovviamente farlo nello XAML – non so perchè mi è uscito così). Il primo event-handler è il seguente:

void openBrowserButton_Click(object sender, RoutedEventArgs e) { frob = conn.AuthGetFrob(); // Richiesta di autenticazione a flickr.com string loginLink = conn.AuthCalcUrl(frob, AuthLevel.Write); System.Diagnostics.Process.Start(loginLink); openBrowserButton.IsEnabled = false; closeWindowButton.IsEnabled = true; }

Ovvero: dalla connessione ottengo il frob, apro il browser e disabilito opportunamente il bottone, in modo tale che l’utente possa cliccare sull’altro. Il secondo event-handler è il seguente:

void closeWindowButton_Click(object sender, RoutedEventArgs e) { // Dopo aver autenticato l'applicazione Auth auth = conn.AuthGetToken(frob); token = auth.Token; // Mi loggo a flickr.com con l'account conn = new Flickr(apiKey, sharedKey, token); this.Close(); }

Ovvero: mi connetto a Flickr con il token che consente autorizzazioni più elevate rispetto a prima e poi, molto semplicemente, la window viene chiusa.

L’esecuzione continua sull’altra window, MainWindow: ne parleremo più nel dettaglio la prossima volta.

Send to Kindle

[Flickr.1] Creare una nostra applicazione per accedere a Flickr

Introduzione
In un mio post precedente ho accennato al fatto che possiamo scrivere codice .NET capace di sfruttare le API esposte da Flickr per fare tutto quello che possiamo attraverso il sito Web stesso. Vale a dire un sacco di cose: ricercare foto ed utenti secondo diversi criteri (tag, nome, data, etc.), uploadare nuove foto, creare nuovi set, geotaggare le foto già uploadate, ottenere la lista dei blog hostati da flickr.com, ottenere le informazioni EXIF di ciascuna foto e così via. Davvero tanta bella roba, che apre le porte a tutti gli sviluppatori che possono creare applicazioni alternative.

Questa pagina elenca le third party apps più diffuse. Quella che ho ritenuto obbligatoria è quella che permette l’upload delle foto in modo molto più efficace rispetto a quanto è possibile fare attraverso il sito Web. Con il sito infatti appare un modulo molto scarno, che permette di uploadare fino ad un massimo di 8 foto alla volta, taggandole ed assegnando un certo livello di protezione (privato o pubblico). Non potete creare nuovi set, dovete prima farlo a mano e poi assegnare le foto. Un incubo. Ed in più, c’è limite delle 8 fotografie. Con questo tool (esiste sia per Windows che per Mac OS X) invece tutti questi limiti vengono spazzati via: trascinate da una vostra cartella tutte le foto che volete, dite di creare un nuovo set e date tutti i tag che volete. E’ sufficiente cliccare su Finish per cominciare il processo di upload.

Come sviluppare un’app tutta vostra
La stessa cosa potete farla voi. Potete sviluppare utility che si interfacciano con Flickr per fare tutto quello che volete. Se siete sviluppatori seri e volete sviluppare una desktop application, leggete questa pagina per avere un’infarinatura su quello che dovete fare. La morale è che per fare qualsiasi cosa, dovete innanzitutto autenticarvi nei confronti di Flickr: la vostra applicazione deve avere il consenso per poter accedere alle API. Questo implica che vi dovete registrare qua per ottenere una api key, che vi serve nel codice che vedremo dopo. A questa api key è associata una secret key.

Vediamo in breve come utilizzare tutte queste informazioni per buttar giù due linee di codice.

1 // Prima dell'autenticazione 2 Flickr conn = new Flickr(apiKey, secretKey); 3 string frob = conn.AuthGetFrob(); 4 string loginLink = conn.AuthCalcUrl(frob, AuthLevel.Write); 5 System.Diagnostics.Process.Start(loginLink); 6 MessageBox.Show("Autentica l'applicazione"); 7 8 // Dopo l'autenticazione 9 Auth auth = conn.AuthGetToken(frob); 10 token = auth.Token; 11 conn = new Flickr(apiKey, sharedKey, token);

Riga per riga, step by step
Guardiamo una ed una le linee di codice. La linea (1) si connette a Flickr usando la api key e la secret key. Entrambi i parametri sono due normalissime stringhe, e ci vengono date da Flickr: nessun problema. La linea (2) chiede a Flickr un frob – sono ignorante: non chiedetemi da dove arrivare questo nome. Tramite il frob, possiamo richiedere a Flickr i permessi di scrittura: alla linea (4), inizializziamo una stringa che contiene un url per richiedere l’autenticazione. Il metodo AuthCalcUrl richiede il frob e il livello di permessi richiesti.

La linea (5) apre il browser predefinito per farlo navigare all’url indicato. Evidentemente, Flickr registra il frob e consente l’accesso alla nostra applicazione. La linea (6) aspetta che l’utente prema Ok, cosa che deve essere fatta solo dopo che il browser ha raggiunto l’url. Questo processo viene effettuato da tutte le applicazioni di terze parti, comprese quelle che ho indicato sopra. Il frob cambia ad ogni compilazione, per cui mentre stiamo sviluppando dobbiamo richiedere l’autenticazione ad ogni esecuzione del progetto: quando il progetto è terminato e l’eseguibile è sempre lo stesso, l’autenticazione la si fa la prima volta e poi basta.

Una volta che la richiesta di autenticazione è stata accettata, possiamo riconnetterci a Flickr alla linea (11), che passa attraverso il costruttore dell’oggetto Flickr. Notare la differenza tra la linea (1) e la linea (11): in quest’ultima usiamo api key, secret key e token. Il token viene ottenuto dal nuovo livello di autorizzazioni richiesto alla linea (9).

Concludo: la classe Flickr, la cui istanza conn è ben visibile alla linea (11) è il succo del discorso. Se avete un IDE degno di tal nome e non sviluppate in .NET usando UltraEdit, TextPad o il blocco note, provate a digitare “.” dopo l’oggetto conn: vedrete un gran numero di metodi che permettono di accedere a tutto quello che volete.

Ma magari ne parlerò la prossima volta, adesso ho una riunione!

Send to Kindle

"Prose is dead. PowerPoint has won." – spero di no!

Ho letto con estremo interesse i vari post che commentavano il libro di Charles Petzold su WPF. Mi ha colpito molto il suo post intitolato “The Future of Writing”, dal quale ho tratto il titolo di questo post. La faccenda mi ha interessato, perchè io stesso sto finendo di leggere il libro di Petzold (30 pagine alla fine) e non ne sono rimasto particolarmente impressionato, come ho detto qualche tempo fa. Tutto è partito da una discussione su CodingHorror che mi sono letto, leggendo critiche, impressioni e commenti inseriti nel post; non ho seguito gli ultimi sviluppi perchè non ho molto tempo.

Partendo dal presupposto che ognuno può preferire l’uno o l’altro libro, una cosa è sicura. Indipendentemente da quello che può pensare Petzold, la prosa non è morta e PowerPoint non ha vinto un bel nulla. Tutto dipende da che tipo di libro si sta scrivendo e dal tema che si desidera trattare. Un libro su WPF, con molto XML/XAML/C#, e soprattutto con esempi così lunghi (a volte anche 3-4 facciate) dovrebbe evidenziare meglio il codice colorandolo e commentandolo adeguatamente. Questo non significa far vincere i colori a dispetto del contenuto o della forma, significa semplicemente far entrare le cose un po’ meglio nella testa di chi legge. Questo non sono io a dirlo, ma lo dice chiunque programmi in modo serio: rendere il codice leggibile è un tema fondamentale. Petzold questo deve saperlo molto bene. Poi, sia chiaro, penso che il fatto che non ci siano colori nel testo non dipenda direttamente da lui, ma non dovrebbe comunque offendersi se gli viene mossa questa critica, ecco. Mi rifiuto di credere che PowerPoint abbia vinto sulla prosa e sulla forma scritta più pura. Credo che sia importante aiutare la lettura con immagini, diagrammi e grafici (viene detto anche in uno dei numerosi commenti: “Professional technical writers use a combination of active-voice writing and visual layout to facilitate the efficient identification and transfer of information“), quando è il caso, soprattutto quando è una cosa che il lettore fa comunque, dovendosi immaginare nella testa il visual tree di un certo blocco XAML. Se Petzold mi riporta 50 linee di XAML, e io mi devo immaginare cosa ottengo, posso sbagliare: perchè farmi fare uno sforzo mentale per ottenere magari un risultato non corretto?

E’ stato fatto un confronto tra il libro di Petzold e Code Complete di Steve McConnell. Quest’ultimo è un libro che ben si presta ad essere scritto in prosa, perchè il codice ha scarsa rilevanza ed in molte pagine è molto più discorsivo che tecnico. Ritengo che il confronto non possa sussistere, sono troppo diversi ed hanno scopi davvero troppo diversi. Altro discorso se lo si paragona con Chris Sells, che invece è molto più conciso e soprattutto affrontano argomenti simili, nel senso che entrambi sono libri dedicati ad una particolare tecnologia. Tra i due modi di scrivere, forse la spunta Petzold, perchè scende molto, molto, molto più in profondità nelle cose, e questa non è una cosa da sottovalutare. Se correggesse i problemi che non solo io ho segnalato, allora Petzold diventerebbe davvero il top.

Petzold ha anche scritto un altro post un po’ più lungo e dove esplica altri concetti. Se Petzold crede davvero che la prosa sia stata sconfitta, forse dovrebbe leggere qualcuno dei miei racconti sui bytes o divertirsi a scriverne uno. 🙂

Send to Kindle

Volete sviluppare con Visual Basic 2005: un libro che fa per voi

Da quando ho aperto il mio blog su UGIdotNET, e da quando mi sono seriamente dato da fare nello studio di .NET, il mio linguaggio preferito è C#. Non chiedetemi perchè, è stata una scelta dettata dal capriccio, nel senso che dopo quasi 10 anni passati a sviluppare con Visual Basic, sentivo il bisogno di ricominciare daccapo con una sintassi come quella del C. Motivo superficiale, vero? E’ quello che dico a tutti.

Tutto questo per dirvi che se invece volete lavorare con Visual Basic, c’è il libro ch fa per voi. Alessandro Del Sole, membro della community Visual-Basic.it, ha scritto un libro, “Programmare con Visual Basic 2005 Oltre il Codice“, dedicato proprio a questo amatissimo linguaggio di programmazione. Ne parla qua in un suo post. Lo dico sinceramente come al solito: non è un libro che mi interessa, però gli argomenti che tratta sono molto interessanti, soprattutto per chi vuole sviscerare per bene tutti gli aspetti legati allo sviluppo di un’applicazione. Si parla dell’IDE di Visual Studio, del deploy di un’applicazione, della creazione della guida per gli utenti, di FxCop, di refactoring e così via. Non prendete questo post come una pubblicità, io non ci guadagno nulla ovviamente, ma magari questa segnalazione può essere utile a qualcuno.

Send to Kindle