Click here to Skip to main content
6,921,363 members and growing! (20,673 online)
Email Password   helpLost your password?
    Intermediate License: The Code Project Open License (CPOL)

From Lambda Dependencies to Lambda Bindings

By Philipp Sumi

Lamba bindings allow you to perform object-to-object data binding using simple LINQ expressions.
C# (C#1.0, C#2.0, C#3.0), .NET (.NET3.5), LINQ, Architect, Dev
Revision:5 (See All)
Posted:14 May 2009
Updated:14 May 2009
Views:5,587
Bookmarked:23 times
Technical Blog
printPrint Friendly   add Share
      Discuss Discuss   Broken Article?Report  
8 votes for this technical blog.
Popularity: 4.29 Rating: 4.75 out of 5

1

2

3
2 votes, 25.0%
4
6 votes, 75.0%
5
A Technical Blog article. View entire blog here.

Lambda-based binding for the business layer or your View Model :)

Lambda Bindings are built on top of the Lambda Dependencies project I published a while ago. The original Lambda Dependencies allow you to observe object graphs for changes using simple LINQ expressions. Lambda Bindings leverage this pattern by not just publishing a change event but synchronizing target properties or fields automatically.

This provides you with a generic binding framework that can be used wherever you want to synchronize objects. Let’s have a first example:

public void TestBinding(Student student)
{
  string cityName = "";
  
  //synchronize the cityName field with the City property of the school's address
  var binding = LambdaBinding.BindOneWay(
      () => student.School.Address.City,
      () => cityName);
  
  //change the property on the School object
  student.School.Address.City = "Sin City";
  
  //the binding expression updated the local variable
  Assert.AreEqual("Sin City", cityName);
} 

What’s happening in the snippet above is that I created a binding between a nested property of a referenced object and a local field. As soon as the binding source (the City property of a school’s address) is changed, the local cityName field is being updated as well.

 

However, the Lambda Dependencies not only cover the source properties but the whole object graph. Accordingly, exchanging the whole School (or the Student instance) also triggers an update. In the snippet below, the cityName variable is being updated twice:

[Test]
public void Updating_Intermediary_Object_Should_Update_Target(Student student)
{
  string cityName = "";

  //synchronize the cityName field with the City property of the school's address
  var binding = LambdaBinding.BindOneWay(
      () => student.School.Address.City,
      () => cityName);

  //change bound City property -> triggers update of the local variable
  student.School.Address.City = "Paris";
  Assert.AreEqual("Paris", cityName);

  //create a completely different school instance
  School englishSchool = new School();
  englishSchool.Address = new Address {City = "London"};

  //assign the new school to the student
  student.School = englishSchool;

  //setting the School property also triggered the binding
  Assert.AreEqual("London", cityName);
}

Value Conversion

You can do simple value conversion by just submitting a converter to the binding expression. This allows you to intercept the binding pipeline or bind objects of different types together. If you’re coming from WPF, this feels natural anyway, but the solution here does not require you to implement a value converter - a simple Func<TSource, TTarget> is sufficient.

Here’s a simple sample that performs a conversion of a boolean flag to into a corresponding Visibility enum value:

[Test]
public void Boolean_Should_Be_Converted_To_Visibility()
{
  //create a hidden window
  Window window = new Window { Visibility = Visibiliy.Collapsed };

  //create a view model
  MyViewModel viewModel = new MyViewModel { IsVisible = false };

  //create binding that casts the Visibility into a boolean
  LambdaBinding.BindOneWay(
      () => viewModel.IsVisible,
      () => window.Visibility,
      b => b == true ? Visibility.Visible : Visibility.Collapsed;

  //a change in the ViewModel shows/hides the window
  viewModel.IsVisible = true;

  Assert.AreEqual(Visibility.Visible, window.Visibility);
}

Two-Way-Binding

Two way binding works too, of course:

[Test]
public void Updates_Should_Work_Both_Ways()
{
  //create two-way binding
  var binding = LambdaBinding.BindTwoWay(
    () => FirstStudent.Name,
    () => SecondStudent.Name);

  //change property on source
  FirstStudent.Name = "Peter";
  Assert.AreEqual("Peter", SecondStudent.Name);

  //change property on target
  SecondStudent.Name = "Parker";
  Assert.AreEqual("Parker", FirstStudent.Name);
} 

In case you need to perform type conversion, you need to supply two converter functions for forward / reverse conversion:

//bind a boolean property to a control's Visibility property
var binding = LambdaBinding.BindTwoWay(
    () => ModelItem.IsEnabled,
    () => MyControl.IsVisible,
    b => b == true ? Visibility.Visible : Visibiliy.Collapsed
    v => v == Visibility.Visible ? true : false); 

Default Values

In case the object graph is being broken (e.g. because the School was set to null), the target node will be automatically set to its default value (null for an object, 0 for an int etc.). However, you can also specify a default value of your own:

//a local field to be updated
private string schoolCity;

[Test]
public void Breaking_The_Chain_Should_Assign_Default_Value_To_Target_If_Specified()
{
  var binding = LambdaBinding.BindOneWay(
      () => Student.School.Address.City,
      () => schoolCity,
      "[No City]");

  //break the source chain
  Student.School = null;

  //the default value was assigned to the target
  Assert.AreEqual("[No City]", schoolCity);
} 

(btw: the above snippet also shows you that you can easily bind to a field rather than a property).

 

Weak References

The underlying Lambda Dependencies only use weak references so you’re not at risk of creating memory leaks. However, LambdaBinding implements IDisposable, so the proper way to clean things up would be to dispose your binding.

Things to Consider

Remember that that the underlying Lambda Dependencies rely on the INotifyPropertyChanged interface, so don’t expect source binding to fields (or properties that do not fire a PropertyChanged event) to magically update your targets.

 

Download: lambda-dependencies.zip

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Philipp Sumi


Member
Philipp is an independent software engineer with great love for all things .NET.
He lives in Winterthur, Switzerland and his home on the web is at http://www.hardcodet.net.
Occupation: Architect
Company: I'm a gun for hire
Location: Switzerland Switzerland

Other popular C# articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 11 of 11 (Total in Forum: 11) (Refresh)FirstPrevNext
GeneralPropertyDescriptor PinmemberMKrul23:46 8 Jun '09  
GeneralRe: PropertyDescriptor PinmemberPhilipp Sumi22:05 9 Jun '09  
GeneralRe: PropertyDescriptor PinmemberMKrul22:44 10 Jun '09  
GeneralBy the way I like the WeakEvent stuff we do the following [modified] PinmvpSacha Barber5:52 15 May '09  
GeneralRe: By the way I like the WeakEvent stuff we do the following PinmemberPhilipp Sumi13:59 15 May '09  
GeneralRe: By the way I like the WeakEvent stuff we do the following PinmvpSacha Barber3:32 17 May '09  
GeneralVery nice man PinmvpSacha Barber10:45 14 May '09  
GeneralRe: Very nice man PinmemberPhilipp Sumi10:53 14 May '09  
GeneralRe: Very nice man PinmvpSacha Barber22:45 14 May '09  
GeneralRe: Very nice man PinmemberPhilipp Sumi22:49 14 May '09  
GeneralRe: Very nice man PinmvpSacha Barber0:31 15 May '09  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+PgUp/PgDown to switch pages.

PermaLink | Privacy | Terms of Use
Last Updated: 14 May 2009
Editor: Chris Maunder
Copyright 2009 by Philipp Sumi
Everything else Copyright © CodeProject, 1999-2010
Web09 | Advertise on the Code Project