Monday, September 28, 2009

Lambda expression in Silverlight 3 Databinding

First of all let me thank to M. Orçun Topdağı for pointing out a useful cs file in the samples provided by Microsoft.You may get those samples in the below location.

[Install drive]:\Program Files\Microsoft Visual Studio 9.0\Samples

The file is Dynamic.cs which provides a bunch of functionality to work more with Lambda expressions.That sample was written for .Net 3.5 and I was afraid whether I can use that in my Application since I am working in Silverlight 3. But I was able to use the same classes for Silverlight and a sample which takes Lambda Expression from xaml and executes through converter is attached with this post.

How to specify a Lambda expression in XAML data-binding

I am using the ConverterParameter to get the lambda expression.The no of parameters to Lambda expression is limited because we can pass only one value to the converter.
<UserControl x:Class="SL_LambdaInConverter.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:SL_LambdaInConverter">
    <UserControl.Resources>
        <local:LambdaConverter x:Key="lambda" />
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot">
        <TextBlock 
            Text="{Binding Converter={StaticResource lambda},ConverterParameter='dt=>dt.ToString()'}" />
    </Grid>
</UserControl>
In the above sample I have set DateTime.Today as DataContext of the UserControl in the constructor.So it will take that value into the converter.Here is the converter code.

Option Strict On
Imports System.Windows.Data
Imports System.Linq.Expressions
Imports System.Linq.Dynamic
 
Public Class LambdaConverter
    Implements IValueConverter
    Dim _delegate As [Delegate]
 
    Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
        If Me._delegate = Nothing Then
            ConstructOperation(value, targetType, CType(parameter, String))
        End If
        Return Me._delegate.DynamicInvoke(value)
    End Function
 
    Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Throw New InvalidOperationException("Convert back operation is not supported")
    End Function
    Sub ConstructOperation(ByVal value As Object, ByVal t As Type, ByVal lambdaString As String)
        Dim opi As Integer = lambdaString.IndexOf("=>")
        If (opi < 0) Then Throw New Exception("No lambda operator =>")
        Dim param As String = lambdaString.Substring(0, opi)
        Dim body As String = lambdaString.Substring(opi + 2)
 
        Dim p As ParameterExpression = Expression.Parameter(value.GetType(), param)
        Dim lambda As LambdaExpression = DynamicExpression.ParseLambda(New ParameterExpression() {p}, t, body, value)
        Me._delegate = lambda.Compile()
    End Sub
End Class

Now you might wonder where is the System.Linq.Dynamic ? Here comes the importance of Dynamic.cs which I had mentioned at the beginning.You may find all those classes there.

Download and enjoy the sample here.

No comments: