Lambda Binder for WPF and Silverlight

On March 20, 2011, in C#, Technology, by Akash Kava

LambdaBinder class helps in creating complex binding expressions without having to create IValueConverter and IMultiValueConverter, it lets you write inline expresions with advanced binding scenarios.

Lets say, you have two TextBox for first and last name and you want a Title to be displayed as addition of both.

So lets say, you can write it as follow,

Adding Two Properties
title.Bind(TextBlock.TextProperty,
    () => firstName.Text + " " + lastName.Text);

Formatting Properties
title.Bind(TextBlock.TextProperty,
    () => string.Format("{0} {1}",
        firstName.Text, lastName.Text));

You can pass on the Linq expression to Bind extension method of LamdaBinder and that will convert and set binding so that anytime if firstName or lastName is modified, the title will be updated automatically.

Assuming I want some hypothetical visibility logic, for example, only if the firstName is entered, lastName should be visible.

Conditional Visibility Binding
lastName.Bind(TextBox.VisibilityProperty,
    () => firstName.Text.Length > 0 ? Visibility.Visible :
        Visibility.Collapsed);

You can also use this to avoid writing IValueConverters and do inline binding in code very easily.

Lambda Binder
public static class LambdaBinder
{

    public static void Bind(
        this DependencyObject dest,
        DependencyProperty destProperty,
        Expression<Func<object>> func)
    {
        MultiBinding b = new MultiBinding();
        b.Converter = new MultiDelegateConverter(func.Compile());
        LambdaBindingBuilder bb = new LambdaBindingBuilder(b);
        bb.Visit(func.Body);
        BindingOperations.SetBinding(dest, destProperty, b);
    }

}

public class LambdaBindingBuilder : ExpressionVisitor
{
    private MultiBinding multiBinding;

    private string lastPath = null;

    public LambdaBindingBuilder(MultiBinding mb)
    {
        this.multiBinding = mb;
    }

    protected override System.Linq.Expressions.Expression VisitMember(MemberExpression node)
    {
        PropertyInfo p = node.Member as PropertyInfo;
        if (p != null) {
            if (string.IsNullOrWhiteSpace(lastPath))
            {
                lastPath = p.Name;
            }
            else {
                lastPath = p.Name + "." + lastPath;
            }
        }
        FieldInfo f = node.Member as FieldInfo;
        if (f != null) {
            Binding b = new Binding(lastPath);
            b.Source = System.Linq.Expressions.Expression.Lambda<Func<object>>(node).Compile()();
            multiBinding.Bindings.Add(b);
            lastPath = null;
        }
        return base.VisitMember(node);
    }

    protected override System.Linq.Expressions.Expression VisitConstant(ConstantExpression node)
    {
        if (!string.IsNullOrWhiteSpace(lastPath)) {
            Binding b = new Binding(lastPath);
            b.Source = node.Value;
            multiBinding.Bindings.Add(b);
            lastPath = null;
        }
        return base.VisitConstant(node);
    }
}

public class MultiDelegateConverter : IMultiValueConverter
{
    private Func<object> func;

    public MultiDelegateConverter(Func<object> func)
    {
        this.func = func;
    }

    public object Convert(object[] values,
        Type targetType,
        object parameter,
        System.Globalization.CultureInfo culture)
    {
        return func();
    }

    public object[] ConvertBack(object value,
        Type[] targetTypes,
        object parameter,
        System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

 

LambdaBinder is part of UI Atoms suite. At NeuroSpeech, we do research on UI and we are coming up with more interesting featues in UI Atoms.

Please Click Here to download latest update of UI Atoms with AtomForm including Tabs in the form.

Share
Tagged with:  

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>