Monday, August 6, 2012

Simpler WPF Binding

WPF has a lot of great concepts. One of my favorite was the implementation of data binding. The syntax though can get pretty tough and you end up having to look it up every time or using some kind of cheat sheet. Also you can't bind directly to methods, you have to wrap methods around commands.

There limitation really slowed me down, luckily WPF binding is extendedable, so I created my own binding which simplified things a lot. It simply allows you to use a simpler syntax. Below are some examples an a link to download the source code.

// before
{Binding Path=PathToProperty, RelativeSource={RelativeSource Self}}
// after
{BindTo PathToProperty}

// before
{Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}
// after
{BindTo Ancestor.typeOfAncestor.PathToProperty}

// before
{Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}
// after
{BindTo Template.PathToProperty}

// before
{Binding Path=Text, ElementName=MyTextBox}
// after
{BindTo #MyTextBox.Text}

// BEFORE
// in your class (RelayCommand available separately)
private ICommand _saveCommand;
public ICommand SaveCommand {
 get {
  if (_saveCommand == null) {
   _saveCommand = new RelayCommand(x => this.SaveObject());
  }
  return _saveCommand;
 }
}

private void SaveObject() {
 // do something
}
// in your xaml
{Binding Path=SaveCommand}

// AFTER
// in your class
private void SaveObject() {
 // do something
}
// in your xaml
{BindTo SaveObject()}

The 'BEFORE' example for binding to a method is already shorter than it would have been without the aid of RelayCommand which I don't think of a native part of WPF. You can find the code for it here: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

Source Code WpfBindTo.zip
Just the DLL WpfBindTo.dll

11 comments:

  1. You're link to the source code is broken. Perhaps you could post it on CodeProject or on CodePlex?

    ReplyDelete
    Replies
    1. I just tried it and it worked, can you try it again.

      Delete
  2. For some odd reason, it says "The type 'BindTo' was no found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built."

    But it still works.... I just can't see my XAML designer anymore

    ReplyDelete
  3. Luis this is beautiful!!! I just implemented it in a huge wpf project and the bindings are being simplified all the way down!!! Im happy as a dog with two tails!

    ReplyDelete
    Replies
    1. I'm happy your happy Anonymous. Spread the word and maybe one day we can live in a world where bindings don't have to be complicated.

      Delete
    2. Hey Luis, I write the above comment, BindTo is really impressive!! is there a shortcut for binding to StaticResources?? I have not tested that yet! thanks!!

      Delete
    3. Hey Salvador, thanks again for your comment. I don't believe I created a binding for static resources, I created this library a long time ago, more than 2 years before I posted it here.

      What it does it parse the string sent to it and then create the corresponding equivalent WPF binding. You can extend the code, specifically the portion that parses "Ancestor" or "Template" and add one for "StaticResource".

      But to be honest with you I don't know what you would gain. The syntax for StaticResource is already pretty concise already "{StaticResource ResourceName}".

      The shortest syntax you could create with BindTo would be {BindTo StaticResource.ResourceName} or maybe just {BindTo Resource.ResourceName}. Unless you wanted to use a symbol like {BindTo $ResourceName}.

      Unless there's an opportunity to simplify more complex variations of StaticResource? But I'm not familiar with any.

      I hope that answers your question.

      Delete
  4. Have you done some performance tests on your binding extensions?

    ReplyDelete
    Replies
    1. I have not performance tested it.

      I suspect that my bindings are a little slower on load when the expressions are parsed.

      The method binding invocation would technically be slower due to the use of reflection for method invocation. But the difference would not be noticeable in most cases since events don't fire in "tight" loops.

      I created the library mostly for development productivity. I think because it's easy to write and read maintenance is easier.

      Also binding to methods directly is faster and requires less code than binding to commands.

      That said it would be interesting to do some performance testing and see how it does.

      Any suggestions on how I could performance test it?

      Delete
  5. Great thank you Luis for sharing! The ability to bind directly to a class method (and not an ICommand) property solved an important problem for me. I use MVVM and wanted to reuse my ViewModel classes in Mono, which does not support ICommand (in System.Windows.Input). Your creative use of a MarkupExtension allow me to remove the System.Windows.Input dependency from my ViewModel classes so they can be reused in Mono. :)

    ReplyDelete

Privacy Policy