Tag Archives: WPF

When enough ViewModel is enough

In the last few years, we’ve seen the WPF and Silverlight community embracing the MVVM methodology. As one of the early adopters of MVVM (one of my first post about the subject was late 2008), I’ve seen the pattern evolving both in the web community and with developers I’ve met in my daily life.

Today, I’d like to share with you a simple concept I try to stick to when I’m doing WPF, Silverlight or Windows Phone 7 development. It can be summarized as “Enough ViewModel is enough”.

The simple idea behind this slogan is that there ARE stuff which are view-related and SHOULD NOT be embedded in the ViewModel layer. I’ve seen too many developers going the “100% viewmodel way” which means for them absolutely no code-behind without any dispensation.

For example, I came across this code. It’s the ViewModel layer associated to a simple view where the user fills various input and has immediate feedback about the progress (like “75% of the fields are completed”). If by the way you’re interested in implementing this behavior you can check out this article I wrote on CodeProject)

The following code is simplified to the sake of the article:

public class ViewModel
{
    // data field acts as the model object behind the VM layer
    private Data data;

    // missing code...
    // public properties used by the view using databinding

    public ViewModel()
    {
        // very simplified for this article...
        this.data = new Data();
        this.data.SelectedValuesChanged += new EventHandler(data_SelectedValuesChanged);
    }

    public void UpdateProgress()
    {
        // some code...
    }

    void data_SelectedValuesChanged(object sender, EventArgs e)
    {
        this.UpdateProgress();
        this.Initialize();
    }

    public void Initialize()
    {
        var item = this.data.GetItem("id1");
        if (item != null)
        {
            item.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
            item.SelectedValuesChanged += new EventHandler(item_SelectedValuesChanged);
            foreach (var value in item.Values)
                value.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
        }

        item = this.data.GetItem("id2");
        if (item != null)
        {
            item.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
            item.SelectedValuesChanged += new EventHandler(item_SelectedValuesChanged);
            foreach (var value in item.Values)
                value.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
        }
    }

    void item_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        this.UpdateProgress();
    }

    void item_SelectedValuesChanged(object sender, EventArgs e)
    {
        this.UpdateProgress();
    }
}

The idea is simple, as soon as the user changes a value in the View, we must compute the current progress. Because the ViewModel have several levels, we end-up having to register to every single PropertyChanged event which leads to cumbersome code. By the way, this code can also creates memory leaks since we register a lot of event handlers without removing them, but that’s another discussion…

Here is my way to solve this problem:

public partial class View : UserControl
{
    private readonly ViewModel viewmodel;

    public View()
    {
        InitializeComponent();

        this.viewmodel = new ViewModel();

        this.AddHandler(
            FocusManager.LostFocusEvent,
            new RoutedEventHandler(this.OnLostFocus),
            true);
    }

    private void OnLostFocus(object sender, RoutedEventArgs e)
    {
        this.viewmodel.UpdateProgress();
    }      
}

What is wrong with this way ? The View has code-behind ? That’s not a big deal: the code is more readable, maintainable. It makes also more sense: when a view-related operation occurs (in this case, focus has changed), update the progress.

The simple message I’d like to spread is the fact that there is nothing wrong with the fact to have sometime, a little bit of code-behind in your view if that facilitates your architecture. There is no need to create a complicated infrastructure with behaviors, commands or bindings just to keep the view empty if that does not make sense.

Another great example in a real application is available in the Advanced MVVM book by Josh Smith.

 

WPF databinding trick (part 2)

Ok, let’s see another strange behavior that you might have already seen with the WPF databinding engine.

INotifyPropertyChanged

When we teach WPF to new developers, at some point we need to introduce the INotifyPropertyChanged interface. Usually, the kind of speech which is given looks like this one:

When you’re doing a binding to a standard CLR property, you must add some kind of notification mechanisms in order to tell the binding when the value changes. In WPF, this is standardized by using the common INotifyPropertyChanged interface. This interface contains a single event which must be raised with the name of the property which has changed. Whenever this event is fired, the databinding engine is able to see the change and update the corresponding binding.

Demo application

Nothing really exciting here, right. Now, you start to do a demo with the following code:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.DataContext = new DataObject() { Data = "test " };
    }
}

public class DataObject
{
    private string data;

    public string Data
    {
        get { return this.data; }
        set { this.data = value; }
    }
}

Here the DataObject class I use as DataContext does not implement INotifyPropertyChanged.Then I added some XAML in the MainWindow:


    
        
        
        
    

And the goal is to display 3 TextBoxes all databound to the same property. Now, we run the application, types some text in one of the TextBox and change the focus in order to update the binding. Most of us would expect to have the 2 other Textboxes with the old value: when the focus has been lost the new string value has been pushed into the Data property, but the other Textboxes have no way to detect this change.

Actually if you run this application, you’ll see all the Textboxes being updated That’s strange…

Why does it works ?

Ok, let’s get into the dirty details. Here are what happens during initialization:

  • XAML is parsed
  • for the 3 TextBox
    • the Binding is initialized
    • a BindingExpression is created. The BindingExpression is a IWeakEventListener.
    • its AttachOverride method is called
    • if the UpdateOnLostFocus flag is set (which is the case because the default value of UpdateSourceTrigger is LostFocus), the static LostFocusEventManager type is used and the AddListener is called
      • during the initialization of the binding, the PropertyPathWorker class is added and at some point the ReplaceItem method gets called
      • then the following code gets execute
    if(source is INotifyPropertyChanged)
    {
    	PropertyChangedEventManager.AddListener(…);
    }
    else
    {
    	PropertyDescriptor descriptor = GetDescriptor(source, path);
    	ValueChangedEventManager.AddListener(…);
    }
    

    Which means:

    • if the source implements INotifyPropertyChanged, use that to track the changes to the property
    • otherwise, use the ValueChanged event of the cached PropertyDescriptor instance to track the changes

    What happens when one of the TextBox lost focus:

    • the focus changes to another control, the previously focused TextBox gets is LostFocus event raised
    • the LostFocusEventManager gets the notification
    • the notification is transferred to the BindingExpression (which is a IWeakEventListener) by calling the IWeakEventListener.ReceiveWeakEvent method
    • several method calls… ending in the PropertyPathWorker class where the PropertyDescriptor.SetValue methods is called (where the PropertyDescriptor is the one which has been cached during initialization)
    • this method raises the ValueChanged event at the PropertyDescriptor level
    • which is catched by the ValueChangedEventManager
    • and the associated dependency property (Text) is updated
    • and voila !

    So there are no miracle behind the demo application I was talking about, just the fact the binding engine is smart enough to cache the PropertyDescriptor used for setting value to CLR property and using the ValueChanged event to get notifications if the source does not implement INotifyPropertyChanged.

    Happy coding !

    WPF databinding trick (part 1)

    The last week, one of my colleague was doing a WPF training session and she ended up having a very strange behavior with the WPF databinding engine. I’ll describe a not well-known behavior of the WPF databinding engine and I’ll try to explain how its works under the scene.

    Binding the Text property of a TextBlock to a collection of objects

    This is something you’re not supposed to do, but you’ll see it actually works in an unexpected way. In the code-behind of our Window, we have the following C# code:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
                
            Person person1 = new Person { Age = 45 };
            Person person2 = new Person { Age = 63 };
            Person person3 = new Person { Age = 71 };
    
            this.DataContext = new List { person1, person2, person3 };
        }
    }
    
    public class Person
    {
        public int Age
        {
            get;
            set;
        }
    }
    

    The associated XAML looks like the following:

    
     
        
            
        
    
    

    Here we’re doing something not usual: we’re binding the Text property of the TextBlock (which is of type string) to a collection of objects.

    What do you think the Window will display ?

    The first time I saw this code, I thought the Window will remain empty. The DataContext is set to a List and we’re trying to find an “Age” property on this collection: THAT CANNOT WORK.

    Actually, it does…

    What’s happening behind the scene ?

    Let’s take a deep breath a take a look at what’s happening behind the scene to make this works.

    1. A CollectionView is created

    The first thing I was thinking while talking about the problem with my colleague was the use of a collection view. As you probably now, every time you create a binding to a collection property, the engine creates a collection view for you. This view will serve as an intermediate layer between your source and the target to manage selection, filtering and grouping. A good introduction to collection views is available here.

    What is important to know is that collection views are shared along same objects instance. It means that when you use the CollectionViewSource.GetDefaultView() method, you’re either creating a default view for the collection (if no one has requested one before) or getting the default view (if it has been created by calling the same method before you).

    To make sure I was right about my hypothesis, I added the following code in the C#:

    var collectionView = CollectionViewSource.GetDefaultView(this.DataContext);
    collectionView.MoveCurrentToNext();
    this.MouseDoubleClick += (s, e) => collectionView.MoveCurrentToNext();
    

    And the Window is now displaying the second item of the list:

    So we’re definitively dealing with a collection view. The next question was, where the value comes from, I specified “Age” as binding path…

    2. The CurrentItem property of ICollectionView

    If you take a look at the documentation about ICollectionView, you’ll find this property:

    So it looks like the Text property of my TextBlock is databound to this CurrentItem property while I explicitly set to the Age property…

    3. The magic of the PropertyPathWorker class

    Using Reflector, I looked for potential types using the ICollectionView.CurrentItem property. I found an interesting class: PropertyPathWorker.In the source code of the .Net framework, this type is defines as “the workhorse for CLR binding“.

    In particular, take a look at this method:

    private void ReplaceItem(int k, object newO, object parent)
    {
        // some code...
    
        view = CollectionViewSource.GetDefaultCollectionView(parent, TreeContext);
    
        // some more code...
    
        newO = view.CurrentItem;
        if (newO != null)
        {
            GetInfo(k, newO, ref svs);
            svs.collectionView = view;
        } 
    
        // and bam ! we're now using view.CurrentItem as source for our binding
    }
    

    So we’ve a special case when we’re creating a binding with a collection view: the CurrentItem property is automatically used and merge with the specificied path. In our case, it’s like creating a binding to CurrentItem.Age.

    3. And voila !

    Finally we’ve a lot going on within the engine to make this works. Of course the original binding was not something we would do in normal application but it was kind of cool doing the investigations to find out why it was working ! Hope you learn something cool about the databinding engine 🙂

    Next week I’ll try to write a similar article about another strange behavior you might have already seen…