WPF Tips'n'Tricks #8: Use your code-behind for binding

In the View-ViewModel-DataModel pattern that has been documented a fair bit for WPF, it is often the case that you want to have a testable class that wraps your data to expose an object model that will make binding from Xaml code easier. However, when writing prototyping or simply answering messages on the Msdn forums, as well as for the code examples on my blog, it's often the case that you want to have a sort-of ViewModel that you want to quickly hack together.

The solution is to simply leverage the code-behind of your window! Let's create a simple property on our window code-behind.

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

        }

 

 

        public bool IsFlagSet

        {

            get { return (bool)GetValue(_isFlagSetProperty); }

            set { SetValue(_isFlagSetProperty, value); }

        }

        public static readonly DependencyProperty _isFlagSetProperty =

            DependencyProperty.Register("IsFlagSet", typeof(bool), typeof(MainWindow), new FrameworkPropertyMetadata(false));

 

    }

And now in the Xaml code you just need to bind the DataContext property to the class itself.

<Window x:Class="CaffeineIT.Blog.XamlCollections.MainWindow"

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  DataContext="{Binding RelativeSource={RelativeSource Self}}">

    <TextBlock>The flag value is:

        <TextBlock Text="{Binding Path=IsFlagSet}"/>

    </TextBlock>

</Window>

Voila! You can now bind straight to the properties defined on your Window class! But as the complexity of your project increases, you'll want to unit test the ViewModel, and for this you'll have to separate the code in a separate class. The way I choose to do it is to embed the object directly inside the Xaml code. With this approach, you'll have the a ViewModel class. Here I implement it by inheriting from DependencyObject to keep the DP we defined earlier, as it provides support for validate and coerce callbacks, but this is absolutely not necessary. You're more than welcome to implement your property through accessors and INotifyPropertyChanged.

    public class NewWindowViewModel : DependencyObject

    {

        public bool IsFlagSet

        {

            get { return (bool)GetValue(_isFlagSetProperty); }

            set { SetValue(_isFlagSetProperty, value); }

        }

        public static readonly DependencyProperty _isFlagSetProperty =

            DependencyProperty.Register("IsFlagSet", typeof(bool), typeof(NewWindowViewModel), new PropertyMetadata(false));

    }

And now I can declare this object in my Xaml.

<Window x:Class="CaffeineIT.Blog.ViewModel.NewWindow"

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:vm="clr-namespace:CaffeineIT.Blog.ViewModel" DataContext="{DynamicResource ViewModel}">

    <Window.Resources>

        <vm:NewWindowViewModel x:Key="ViewModel" />

    </Window.Resources>

    <TextBlock>The flag value is:

        <TextBlock Text="{Binding Path=IsFlagSet}"/>

    </TextBlock>

</Window>

I find the code very tidy. Through this mechanism, you can also bind properties from your view to the ViewModel. Imagine: View updates ViewModel updates View... You can abstract all the logic of your view in your ViewModel in an oh-so-clean way it makes me salivate every time. You can then leverage commands to encapsulate actions that modifies the ViewModel which update the View. No more tier leakage!

Technorati Tags: , , ,

Ads

Comment