Technology Experience
.NET World

Usare un DateTimeConverter nei progetti WPF

Eventuali imprecisioni sono dovute all’ascolto, durante la stesura del post, di un concerto del Liga.
Chiedo scusa: aiutatemi con i vostri commenti. 🙂

La classe DateTimeConverter è definita nel namespace System.ComponentModel nell’assembly System.dll. Il primo pensiero che ho avuto quando ho scoperto la presenza di questa classe – con questo nome – è stato: cavolo, posso metterla nelle risorse di una Window e sfruttarla nel meccanismo di data-binding tra un tipo DateTime ed un semplice controllo come la TextBox.

Supponiamo di avere una Window semplice definita così:

1 <Window x:Class="StudyWPF.DataBindingWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:cnv="clr-namespace:System.ComponentModel;assembly=System" 5 Title="StudyWPF" Height="300" Width="300"> 6 <Window.Resources> 7 <cnv:DateTimeConverter x:Key="cnvDateTime" /> 8 </Window.Resources> 9 </Window>

Ho aggiunto un riferimento al namespace System.ComponentModel dentro l’assembly System.dll con i metodi di cui abbiamo parlato più o meno tutti in passato. Due note. Primo: occhio, la “a” di “assembly” alla riga (4) nel mapping del namespace deve essere obbligatoriamente minuscola. Secondo: il riferimento all’assembly, sempre alla riga (4) non deve avere estensione. Ogni volta ci perso mezz’ora, spero che scrivendolo questo tempo diminuisca. 🙂

Fatto questo, ho definito fra le risorse un’istanza di DateTimeConverter, usando come key la stringa “cnvDateTime”. Se provate a compilare, non avrete alcun errore. L’istanza del converter viene creata. Ma se provate ad usarla in un qualche data-binding, fallirà. Ve lo dimostro, sperando di non dire qualche stupidaggine (in tal caso, leggere il prologo all’inizio). Guardate il seguente XAML:

<Window x:Class="StudyWPF.DataBindingWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:StudyWPF" xmlns:cnv="clr-namespace:System.ComponentModel;assembly=System" Title="StudyWPF" Height="300" Width="300" DataContext="{DynamicResource player}"> <Window.Resources> <s:HockeyPlayer x:Key="player" /> <cnv:DateTimeConverter x:Key="cnvDateTime" /> </Window.Resources> <TextBox Text="{Binding Path=Data}" /> </Window>

E’ una sorta di evoluzione di quello di prima. Fra le risorse c’è ancora il DateTimeConverter di prima. Ho aggiunto un nuovo namespace ed una nuova risorsa, per avere a disposizione un oggetto di business che mi vada ad esporre una proprietà pubblica di tipo DateTime. Tale oggetto è uno HockeyPlayer (ve lo ricordate?) e mi espone una semplice proprietà Data. Ho impostato il DataContext della Window sulla risorsa player. In questo modo alla Window posso aggiungere una TextBox bindata all’oggetto secondo il Path=Data. Cosa mostra la TextBox? E’ presto detto…

Ovvero…una semplice ToString() sull’oggetto definita nella risorsa, che giustamente ha i valori di default per un’istanza di DateTime. Supponiamo adesso di voler sfruttare il converter: modifichiamo la definizione del data-binding sulla TextBox:

<TextBox Margin="4" Text="{Binding Path=Data, Converter={StaticResource cnvDateTime}}" />

Al data-binding ho detto di usare un converter, e nello specifico quello definito dalla risorsa. Il codice non compila: il messaggio di errore è:

Cannot convert the value in attribute ‘Converter’ to object of type ‘System.Windows.Data.IValueConverter’. Object of type ‘System.ComponentModel.DateTimeConverter’ cannot be converted to type ‘System.Windows.Data.IValueConverter’.  Error at object ‘System.Windows.Data.Binding’ in markup file ‘StudyWPF;component/databindingwindow.xaml’ Line 15 Position 23.

Il messaggio è chiaro. WPF si aspetta converter che implementino l’interfaccia IValueConverter del namespace System.Windows.Data. La classe DateTimeConverter che abbiamo usato noi non fa nulla di tutto questo: grazie ad un giro con Reflector, vedo che deriva da TypeConverter, e non c’entra nulla.

Le soluzioni sono almeno due: o vi scrivete voi un DateTimeConverter adatto a funzionare con WPF (operazione semplicissima, al punto che è la strada che ho seguito), oppure date un’occhiata a questo progetto su CodeProject.com, che oltre al DateTimeConverter vi dà altri converter che potrebbero esservi utili in altri contesti.

Technorati Tags:   

Send to Kindle

Igor Damiani

La sua passione per l'informatica nasce nella prima metà degli anni '80, quando suo padre acquistò un Texas Instruments TI-99. Da allora ha continuato a seguire l'evoluzione sia hardware che software avvenuta nel corso degli anni. E' un utente, un videogiocatore ed uno sviluppatore software a tempo pieno. Igor ha lavorato e lavora anche oggi con le più moderne tecnologie Microsoft per lo sviluppo di applicazioni: .NET Framework, XAML, Universal Windows Platform, su diverse piattaforme, tra cui spiccano Windows 10 piattaforme mobile. Numerose sono le app che Igor ha creato e pubblicato sul marketplace sotto il nome VivendoByte, suo personale marchio di fabbrica. Adora mantenere i contatti attraverso Twitter e soprattutto attraverso gli eventi delle community .NET.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.