Technology Experience
.NET World

Impostare un trigger quando TextBox.Text == string.Empty

Stamattina mi è venuta una piccola idea facilmente realizzabile in WPF. Immaginatevi una TextBox su una Window nella quale l’utente può digitare una qualsivoglia informazione. Supponiamo adesso di voler evidenziare in qualche modo quando la TextBox è vuota, magari per dire all’utente che quella casella è obbligatoria e che va riempita per forza.

La prima cosa che ho pensato è di impostare un trigger sulla TextBox stessa. Lo XAML iniziale è:

<TextBox Height="20" VerticalAlignment="Top" Margin="6" Name="txtUsername" />

Il trigger va impostato nelle risorse associate alla TextBox, per cui lo XAML va spezzato in questo modo:

<TextBox Height="20" VerticalAlignment="Top" Margin="6" Name="txtUsername"> <TextBox.Resources> </TextBox.Resources> </TextBox>

Nel blocco <TextBox.Resources></TextBox.Resources> inseriamo lo stile che contiene il trigger:

<Style TargetType="TextBox"> <Style.Triggers> <Trigger Property="Text.Length" Value="0"> <Setter Property="Background" Value="Red"/> </Trigger> </Style.Triggers> </Style>

La logica è: quando la proprietà Text.Length è 0, allora il Background della TextBox deve diventare rosso. Ma il codice non compila: l’errore è : Value ‘Text.Length’ cannot be assigned to property ‘Property’. Ma possiamo girare la frittata in un’altra maniera. Se riusciamo a far scatenare il trigger quando la proprietà Text == string.Empty, otteniamo esattamente lo stesso risultato. Ok, ragioniamo.

Empty è una proprietà statica della classe String. String è definita dentro il namespace System. L’assembly è mscorlib.dll. Ok, detto questo, procediamo. Importiamo nello XAML l’assembly che ci serve:

xmlns:s="clr-namespace:System;assembly=mscorlib.dll"

Il blocco qui sopra va incollato nella definizione della Window. A questo punto il trigger può essere impostato in questo modo (riporto l’intero blocco XAML che definisce la TextBox, che così potete copiare ed incollare facilmente):

<TextBox Height="20" VerticalAlignment="Top" Margin="6" Name="txtUsername"> <TextBox.Resources> <Style TargetType="TextBox"> <Style.Triggers> <Trigger Property="Text" Value="{x:Static s:String.Empty}"> <Setter Property="Background" Value="Red"/> </Trigger> </Style.Triggers> </Style> </TextBox.Resources> </TextBox>

In pratica, utilizzo x:Static per accedere alla proprietà statica Empty della classe String. Quando la condizione è verificata, il trigger si scatena ed il Background della TextBox diventa rosso. Ricordo che ci pensa WPF a riportare il Background allo stato originario nel momento in cui la condizione del trigger diventa falsa.

La cosa più comoda, IMHO, è spostare la definizione dello stile dentro il blocco <Application.Resources></Application.Resources> del file App.xaml, in modo tale che lo stile sia accessibile non solo a quella particolare TextBox, ma a qualsiasi TextBox della nostra applicazione alla quale decidiamo di associare quello stile. Mi spiego meglio: apriamo il file App.xaml e fra le risorse incolliamo questo blocco XAML:

<Style x:Key="mandatory" TargetType="TextBox"> <Style.Triggers> <Trigger Property="Text" Value="{x:Static s:String.Empty}"> <Setter Property="Background" Value="Red"/> </Trigger> </Style.Triggers> </Style>

Da notare che ho associato una Key allo stile, oltre che definire il Type sui quali possiamo associare lo stile stesso. Lo stile ha una Key = “mandatory”. Adesso possiamo semplicemente prendere tutte le TextBox che vogliamo rendere obbligatorie (perlomeno visivamente) e dire loro di usare quello stile particolare. Ad esempio:

<TextBox Height="20" VerticalAlignment="Top" Margin="6" Name="txtUsername" Style="{StaticResource mandatory}">

Ed il gioco è fatto. Ricordo che non c’è alcuna logica di validazione: l’utente può spostarsi da un controllo all’altro e via dicendo. Quello che abbiamo fatto ha solo un riscontro visivo e nulla di più.

Send to Kindle
IV del Venerdì

[IV] del Venerdì (4)

Lo sguardo del cantante vagava avanti ed indietro, saltando da una testa all’altra, cercando colui che aveva osato profanare la sacralità della sua canzone. Non era arrabbiato, solo indispettito. Sentiva che quello starnuto non era stato casuale, ma un atto voluto con una maleducazione che non si sapeva spiegare. Dopo qualche secondo, l’artista lo trovò. La persona teneva un fazzoletto in mano. Si stava pulendo goffamente il naso. La persona era solo un bambino, probabilmente di 7 o 8 anni. La rabbia dell’artista fu tale che sentì un bruciore allo stomaco. Come poteva esistere un bambino così maleducato? Cosa ci faceva a teatro ? Dov’erano i suoi genitori? Perchè non si curavano di lui? Tra razionalità e follia prevalse quest’ultima: il cantante sentì il peso del freddo della pistola che teneva infilata nei pantaloni di scena, e si preparò ad usarla.

Pochi minuti fa ho parlato con il mio “capo” per organizzare le ferie all’interno del team nel quale lavoro. Sono sempre stato piuttosto flessibile, perchè non sono il tipo che si organizza le ferie molto tempo prima per andare chissà dove. Ho segnato le due settimane centrali di agosto, ma posso variare se c’è bisogno. Non ho mai avuto grandi progetti per l’estate, di solito improvviso e vedo un po’ quello che mi succede. Non ho un motivo preciso per agire così. So solo di essere un cattivo turista, perchè una volta sì ed una volta no perdo sempre qualcosa: portafoglio con tutti i documenti, per esempio. Recentemente ho lasciato incustodita la mia fotocamera in un posto – per fortuna l’ho ritrovata qualche minuto. Insomma, per dirla in modo un po’ superficiale, più tempo passo a casa e più sono al sicuro. Quando avevo problemi economici, qualche anno fa, ho preferito fare così: i miei giù in Puglia, mio fratello a spasso per il mondo, io tranquillo a casa con Jolly. Ho un giardino con il portico, gestivo la casa sotto tutti i punti di vista e così via, qualche uscita con gli amici quando si poteva. Più relax di così!

D’altro canto, invece, mi piace molto di più impegnarmi i weekend, come ho fatto nei mesi scorsi. Che sia Barcellona, Mestre o un qualche paesino fra i monti, io se posso il sabato e la domenica li passo sempre fuori. Piuttosto che farmi 2 settimane tutte di fila ad agosto, preferisco di gran lunga spezzare il periodo lavorativo cliccando su Pause ad intervalli regolari di 7 giorni. Il lunedì poi ho molta più voglia di rimettermi al lavoro. Non so se è una cosa in comune a molti, so solo che per me funziona meglio così. Si controllano meglio le spese – cosa che comunque non sto lì a fare per pura pigrizia, è più divertente, si può viaggiare in auto, si conosce meglio la nostra Italia e così via. Questo weekend vado in Riviera per la Nove Colli, cicloturistica intitolata a Marco Pantani, di cui parlerò in un post dedicato la settimana prossima. Il prossimo weekend ancora sarò a Roma per la Giornata Azzurra, manifestazione dedicata al volo militare che si terrà all’aeroporto di Pratica di Mare. Poi, non si sa bene quando, visiterò i Giardini di Sigurtà.

Insomma, credo che nelle prossime settimane mi divertirò e rilasserò un sacco. E la mia fotocamera si deve preparare a scattare le sue brave foto. Alla prossima!

Send to Kindle
.NET World

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

Ci siamo lasciati l’ultima volta con il seguente screenshot:

Per sapere come ho ottenuto un risultato simile con WPF è sufficiente leggere i miei post precedenti (questo, questo e quest’altro). Impostando la proprietà ItemTemplate della ListBox, abbiamo fatto in modo che ogni riga venga visualizzata esattamente come vogliamo noi. Su ciascuna riga, vediamo tutti i dati che ci interessa vedere: nome del giocatore, peso ed altezza. Possiamo modificare quest’ultima agendo su ciascuno Slider. Divertente, no?

La cosa brutta è – come si vede sopra – il fatto che il binding tra lo Slider e la TextBox produce un effetto che non mi piace. La proprietà Value dello Slider è di tipo double, e quindi la proprietà Text della TextBox mostra un double, con tutti i decimali del caso. Se vogliamo fare le cose per bene, dobbiamo mettere mano al codice…oserei dire, finalmente. Dobbiamo realizzare una classe che implementa l’interfaccia IValueConverter: lo scopo di tale classe è quello di convertire i valori che vengono utilizzati nel processo di Binding. Nel nostro caso, nei due sensi:

  1. dallo Slider alla TextBox (quindi, da double a string)
  2. dalla TextBox allo Slider (quindi, da string a double)

Siccome mi piace l’idea che l’utente utilizzi lo Slider, eliminiamo la seconda possibilità: trasformiamo la TextBox in TextBlock. Immaginate la TextBlock come la classica Label delle Windows Form: visualizza qualcosa ma ovviamente non permette alcuna modifica. Lo vediamo fra un attimo. Detto questo, possiamo tranquillamente eliminare la conversione del punto (2): scriveremo lo stesso il codice perchè non siamo pigri, ma sappiamo a priori che non verrà utilizzato.

Arriviamo al dunque. Implementiamo una classe SliderValueConverter:

1 [ValueConversion(typeof(double), typeof(int))] 2 public class SliderValueConverter : IValueConverter 3 { 4 public object Convert(object value, Type targetType, 5 object parameter, 6 System.Globalization.CultureInfo culture) 7 { 8 double input = (double)value; 9 int output = (int)input; 10 return (output); 11 } 12 13 public object ConvertBack(object value, Type targetType, 14 object parameter, 15 System.Globalization.CultureInfo culture) 16 { 17 int input = (int)value; 18 double output = (double)input; 19 return (output); 20 } 21 }

L’implementazione dell’interfaccia IValueConverter è molto semplice: c’è un metodo Convert ed un metodo ConvertBack. Il primo converte da double ad integer. Il secondo da integer a double. In parole semplici: quando il Value dello Slider sta per essere spedito alla TextBox, passa prima dalla nostra classe, subìsce la conversione in intero ed arriva alla Text della TextBox. Basta impostare un breakpoint alla linea (8) per avere la conferma. 🙂

L’implementazione della classe SliderValueConverter da sola non è sufficiente per compiere la magia. Occorre modificare anche lo XAML, per fornire qualche informazione in più. Vediamo come e dove.

Inseriamo tra le risorse dello XAML un’istanza della classe SliderValueConverter:

<Window.Resources> <a:HockeyPlayers x:Key="players" /> <a:SliderValueConverter x:Key="conv"/> </Window.Resources>

Ricordo che con il prefisso a facciamo riferimento al namespace MyItemTemplate, che è il namespace col quale stiamo sviluppando l’applicazione. Poi prendiamo lo XAML che definisce la TextBox che viene bindata allo Slider e modifichiamolo come segue:

<TextBlock Margin="4" Text="{Binding ElementName=sldHeight, Path=Value, Converter={StaticResource conv}}" Width="60" />

Nel Binding abbiamo adesso forniamo l’ElementName, il Path ed infine il Converter, che per l’appunto fa uso della risorsa identificata dalla key conv. Compiliamo ed eseguiamo. Se tutto è ok, adesso quando spostiamo lo Slider vediamo qualcosa di un po’ più carino e leggibile (soprattutto per l’utente finale):

Stay tuned, perchè mica è finita qua! 🙂

Send to Kindle
.NET World

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

Ci sono diversi metodi per rendere un po’ più gradevole l’interfaccia della nostra applicazione. Adesso la ListBox mostra ogni HockeyPlayer mostrando solo il nome – comportamento, abbiamo detto, dovuto al fatto che abbiamo fatto l’override del metodo ToString() della nostra classe. Con WPF possiamo andare ben oltre. Chi sta leggendo la mia serie di post su Flickr ne sa qualcosa. 🙂

Questo diventa realizzabile fornendo un template per ogni item che vogliamo visualizzare sulla ListBox. Questo template può essere un Panel di qualche tipo, che contiene altri controlli, tutti bindati a determinate proprietà della classe HockeyPlayer. Vediamo bene e con calma come farlo in pratica. Lo XAML è il seguente:

<Window x:Class="MyItemTemplate.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:a="clr-namespace:MyItemTemplate" Title="MyItemTemplate" Loaded="Window1_Loaded" Width="390" Height="430"> <Window.Resources> <a:HockeyPlayers x:Key="players" /> </Window.Resources> <StackPanel> <ListBox Name="lstPlayers" ItemsSource="{Binding Source={StaticResource players}, Path=HockeyPlayer}" /> </StackPanel> </Window>

Alla Window ho aggiunto una risorsa la cui key è players, che viene utilizzata come ItemsSource della ListBox. Nell’evento Loaded ottengo il riferimento alla risorsa, che è di tipo HockeyPlayers. Trattandosi di una lista, la popolo con 10 HockeyPlayer a caso e la riassegno alla proprietà ItemsSource della ListBox per trovamela popolata. Notare l’utilizzo del Binding: imposto il Source – dicendo che si tratta della risorsa players – ed imposto anche Path, che serve a specificare il tipo che viene bindato su ciascun Item. In questo caso, si specifica che ogni Item appartiene al tipo HockeyPlayer.

E’ arrivata l’ora di assegnare un template alla ListBox. Per farlo, è sufficiente lavorare sulla proprietà ItemTemplate della ListBox, impostandola ad esempio così:

<ListBox Name="lstPlayers" ItemsSource="{Binding Source={StaticResource players}, Path=HockeyPlayer}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Margin="4" Orientation="Horizontal"> <TextBox Text="{Binding Path=Name}" Margin="4" Width="120" /> <TextBox Margin="4" Text="{Binding Path=Weight}" Background="LightCoral" Width="30" /> <TextBlock Margin="4" Text="{Binding ElementName=sldHeight, Path=Value}" Width="60" /> <Slider Name="sldHeight" Value="{Binding Path=Height}" Minimum="140" Maximum="230" Width="120" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>

Fantastico! Dunque, vediamo cosa è successo. Assegniamo la proprietà ItemTemplate della ListBox: il template è composto da uno StackPanel che contiene 3 TextBox ed uno Slider. La prima TextBox visualizza il nome del giocatore, mentre la seconda il suo peso. La terza TextBox e lo slider lavorano assieme: lo slider è bindato all’altezza del giocatore, mentre la TextBox visualizza il valore effettivo, cosa che lo slider non può fare. In pratica, mentre prima potevamo modificare l’altezza di uno HockeyPlayer solo dopo averlo selezionato dalla ListBox, adesso lo slider compare su ogni riga ed abbiamo subito un impatto un po’ più immediato. Ecco un esempio:

Il tutto senza scrivere una sola linea di codice e, come disse una volta Corrado, con una mano sola. 🙂

Adesso posso tranquillamente agire su ciascuno Slider per modificare l’altezza di ogni giocatore. Vogliamo fare la prova del 9 come alle elementari? Aggiungiamo un pulsante allo StackPanel

<Button Margin="6" Name="btnShowCurrentHeight" Content="Show Height" Click="btnShowCurrentHeight_Click" />

e scriviamo l’event handler specificato:

void btnShowCurrentHeight_Click(object sender, RoutedEventArgs args) { HockeyPlayer pl = lstPlayers.SelectedItem as HockeyPlayer; if (pl != null) { MessageBox.Show(pl.Height.ToString()); } }

Lanciamo l’applicazione, spostiamo un po’ gli Slider a sinistra e a destra, selezioniamo una riga a caso della ListBox e clicchiamo sul pulsante che abbiamo appena creato. Visualizza l’altezza che abbiamo determinato con lo Slider. Se con un DAL riuscissimo a salvare ogni istanza di HockeyPlayer (oppure serializzando su file), salveremmo i valori così come li vediamo sulla UI.

C’è ancora qualcosa da sistemare, primo fra tutti fare in modo che il binding sulla TextBox non visualizzi tutti quei decimali. Ma sarà l’occasione per un successivo post.

Send to Kindle
.NET World

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

Se avete seguito le indicazioni del post precedente, vi ritroverete fra le mani un’applicazione WPF che mostra una cosa simile a quella riportata qui sotto:

Fino ad adesso, non abbiamo in alcun modo fatto uso di data-binding. Cominciamo adesso. Invece di aggiungere manualmente uno ad uno ogni oggetto alla ListBox, possiamo utilizzare la proprietà ItemsSource della ListBox. Modifichiamo l’event handler associato all’evento Loaded della Window:

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

Creiamo un’istanza di HockeyPlayers ed aggiungiamo a questa lista 10 istanze di HockeyPlayer, con gli stessi valori di prima. Alla fine, assegniamo alla proprietà ItemsSource della ListBox l’oggetto coll che abbiamo creato via codice. Questa cosa è tanto interessante che a questo punto possiamo modificare lo XAML aggiungendo un po’ di controlli in questo modo:

<TextBox Text="{Binding ElementName=lstPlayers, Path=SelectedItem.Weight}" /> <Slider Name="sdrHeight" Value="{Binding ElementName=lstPlayers, Path=SelectedItem.Height}" Minimum="140" Maximum="230" SmallChange="1" LargeChange="5" /> <TextBox Text="{Binding ElementName=sdrHeight, Path=Value}" />

La prima TextBox è bindata alla ListBox ed accede alla proprietà Weight dello HockeyPlayer correntemente selezionato sulla lista.
Poi ho messo uno slider, che in pratica permette di vedere e modificare l’altezza del giocatore selezionato sulla ListBox: ho bindato la proprietà Value, che accede alla proprietà Height del SelectedItem. Ho impostato altre proprietà dello slider (minimo, massimo, etc.).
L’ultima TextBox riporta il valore dello slider, altrimenti l’utente sposta lo slider ma non capisce il valore dell’altezza che sta impostando. 🙂

Il risultato di tutto ciò è che quando cambiamo la selezione sulla ListBox i controlli riflettono il cambiamento, mostrando peso ed altezza del giocatore selezionato e permettendone la modifica.

Abbiamo dimostrato (e non ci voleva granchè) che per fare data-binding non è assolutamente vero che le proprietà pubbliche che vogliamo bindare debbano essere obbligatoriamente dependency properties (come sostenevo io :-), ma è sufficiente che la classe implementi l’interfaccia INotifyPropertyChanged. Questo vale sia per WPF, di cui abbiamo parlato adesso, che con le classiche Windows Forms.

Ma l’interfaccia rimase decisamente bruttina. Stay tuned!

Send to Kindle
.NET World

[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
My personal life

La mia vita è sempre più integrata…

Man mano che passano i giorni, mi accorgo che la mia vita lavorativa quotidiana è piena zeppa di dispositivi e apparecchiature come palmari, cellulari, navigatori, siti Web, applicativi su desktop capaci di interagire fra loro in una maniera devastante ed iperproduttiva. Il mio parere personale è che la tecnologia fornisce hardware molto, molto complesso, che solo gli addetti ai lavori e gli esperti riesce a padroneggiare veramente.

Utilizzo un palmare, sul quale giorno per giorno segno le giornate lavorative. Quando arrivo a casa, lo sincronizzo (non tutti i giorni) con il mio PC Desktop, con il risultato che dentro MS Outlook 2007 mi ritrovo mese per mese tutti i giorni in cui ho lavorato. Il risultato finale è che posso fare rapportini e fatture in modo totalmente automatico, grazie ad una utility da command-line che mi sono scritto nel tempo libero. Alla fine di ciascun mese, la lancio, lei mi dice quanti giorni ho lavorato, mi crea la fattura sul mio db SQL Server 2005 (in pratica…un paio di record in due tabelle, ma passando dal domain-model e dall’API della mia applicazione che utilizza NH), mi crea automaticamente un’e-mail nelle Bozze di Outlook con il testo precompilato e con l’allegato in PDF della fattura già pronto. Sembra uno scherzo, ma mi evito un bel po’ di lavoro, sul serio.

Altra cosa divertente: ho un dominio su WH4L, che dà la possibilità di utilizzare WSS 3.0. Ciò significa Sharepoint con liste condivise e collaborative. Ok, mi son detto: perchè non sfruttare questo po-po di tecnologia, ad esempio, per aiutarmi a stampare mensilmente le spese che sostengo per mangiare? Non pensate ad uno sfizio o ad un capriccio: ogni giorno spendo dai 6 ai 10 euro, tengo fatture/ricevute/scontrini da portare al commercialista, il quale tuttavia non vuole mettersi lì a sommare gli importi di ciascun scontrino per capire quanto ho speso nel mese di Aprile 2007. Potrebbe anche sbagliare. Mio fratello ha messo in piedi un sistema credo semplice ma devastante: una lista fatta con WSS 3.0 nel quale sia io che lui inseriamo giorno per giorno dove mangiamo, cosa mangiamo e quanto spendiamo. Qualche campo calcolato (ad esempio, il totale), qualche GROUP BY ed il gioco è fatto. Adesso ho una lista sempre pronta che stampo ed allego alla mazzetta di scontrini da portare al commercialista. Mica male, sul serio. Grazie Omar.

Questo è il mio caso personale. Lo so che sembra folle, che sembro un tecnologo impazzito, ma in fondo, cavolo, utilizzo tutti i giorni un mare di tecnologia che alla fin fine un risultato me lo dà anche, e bello grosso anche. Stasera invece di tornare a casa e sapere di essere impegnato per stampare e spedire fatture via e-mail, so di poter far altro. Tutto questo perchè l’hardware è sempre più integrato, c’è un’ampia possibilità di dialogo grazie ad infrarossi, Bluetooth, XML, API e quant’altro. Mi rammarica solo che queste possibilità non siano – credo – davvero alla portata di tutti, perchè c’è molta gente che dal punto di vista informatico è ancora ignorante e che chiede corsi anche per sapere come utilizzare una chiavetta USB o per ascoltare qualche mp3.

Send to Kindle
.NET World

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
My personal life

Scioperto ATM e rampe contromano (azione alla Ocean’s Eleven)

Ieri dalle 18 alle 22 c’era il classico sciopero ATM di Milano, azienda (per chi non lo sapesse) che gestisce metropolitana, tram, filobus e quant’altro. Insomma, l’infrastruttura dei trasporti intracittadina. Niente di male: basta uscire 20 minuti prima dall’ufficio giusto per non viaggiare come sardine e raggiungere il parcheggio di Famagosta dove lasciamo la macchina. Arrivo io: sono da solo. Aspetto 5 minuti ed arriva Fabio, un mio amico col quale viaggio. Aspettiamo ancora un po’ ed arriva anche mio fratello. Ok, possiamo raggiungere il 3° piano, prendere la macchina e tornare a casa.

La scena che ci si presenta davanti agli occhi al 3° piano è quella che appare nella foto qui sotto:

In pratica, un fila devastante di automobili per uscire dal parcheggio. Di solito ci mettiamo 2 minuti ad uscire, basta scendere dalle rampe, infilare l’abbonamento e finita lì. Ieri probabilmente il tempo di attesa sfiorava l’oretta scarsa.

Mio fratello Omar fa due passi a piedi per ragionare sul da farsi, mentre io ho tutta la voglia di bloggare (incavolato) direttamente da lì. Omar torna e sicuro di sè, dice: “Oh ragazzi, facciamo così: scendo dalle rampe di salita, tanto non entra nessuno, ci vuole un attimo. E poi, siamo al 3° piano, perciò basta che uno di noi va a piedi al piano di sotto e ci avvisa se la rampa è libera oppure no.” Io non sono mica tanto convinto, qualcosa può andare storto. Ma di fronte alla scelta di buttare via il tempo, decido di avvallare il piano alla Ocean’s Eleven.

Realizzazione: Omar alla guida (l’auto era la sua), io di fianco con il cellulare in mano, Fabio che percorre le rampe a piedi comunicando luce verde, proseguire o luce rossa, annullare. Fa davvero uno strano effetto andare contromano su quelle rampe, perchè ti aspetti davvero che ti ritrovi un’auto che sale da un momento all’altro!

Alla fine l’operazione è durata meno di un minuto. Come è giusto che sia: un sacco di preparazione iniziale ed uno svolgimento rapido ed efficace. Quando siamo sbucati fuori ci hanno guardato tutti chiedendosi da dove arrivassimo. Siamo usciti tranquillamente, ma io ho comunque trovato il tempo di inveire contro il tipo dell’ATM ed il loro maledetto sciopero.

Send to Kindle