Lambda Expression in Windows Presentation Foundation

di Cristian Civera, in .NET 3.5,

Preso da LINQ, Expression e compagnia bella, mi è venuto in mente di provare ad applicare LINQ anche in WPF, la mia primissima passione. Ho pensato al Binding, che è bellissimo, ma spesso mi trovo a dover usare converter che, anche se molto stupidi, richiedono di creare una classe che implementi IValueConverter, referenziarla e instanziarla nel markup.

Ho creato quindi una MarkupExtension personalizzata che imposti in fase di inizializzazione un converter basato su espressioni inserite direttamente nel markup. Partiamo quindi dalla fine; l'utilizzo è il seguente e permette di mettere in maiuscolo ciò che è stato immesso nella TextBox txt:

<TextBox x:Name="txt" Text="Testo" />
<TextBlock
Text="{Binding Path=Text,ElementName=txt,
Converter={m:Expression value.ToString().ToUpper(culture)}}" />

Creare una MarkupExtension è abbastanza semplice. Basta ereditare dalla classe e implementare ProvideValue, chiamato in fase di inizializzazione del markup. La mia implementazione effettua il parsing dell'espressione, ottiene un delegate e la passa ad una nuova istanza di una mia ExpressionValueConverter che implementa IValueConverter e semplicemente chiama questo delegate:

public delegate object ExpressionConverterDelegate(object value, object target, Type targetType, object parameter, CultureInfo culture);

Il parsing dell'espressione l'ho poi affidato ad una serie di classi contenute nell'esempio DynamicLinq presente nel SDK del .NET Framework 3.5. Fatte alcune piccole modifiche, chiamando DynamicExpression.ParseLambda possiamo ottenere una lambda expression, in questo caso con la nostra firma, da poter compilare così da ottenere il delegate:

public override object ProvideValue(IServiceProvider serviceProvider)
{
IProvideValueTarget provideValueTarget = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
LambdaExpression le = DynamicExpression.ParseLambda<ExpressionConverterDelegate>(
new ParameterExpression[] { 
Expression.Parameter(typeof(object), "value"),
Expression.Parameter(typeof(object), "target"),
Expression.Parameter(typeof(Type), "targetType"),
Expression.Parameter(typeof(object), "parameter"), 
Expression.Parameter(typeof(CultureInfo), "culture")
},
typeof(object),
this.ConvertExpression,
null);
ExpressionConverterDelegate converter = (ExpressionConverterDelegate)le.Compile();
return new ExpressionValueConverter(provideValueTarget.TargetObject, converter);
}

Figo no? Le performance poi una volta creato il delegate sono le medesime di una normale classe.

Qui il codice sorgente.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Nella stessa categoria
I più letti del mese