Who knew overriding GetHashCode() was so much fun?


So, I have a project with Code Analysis turned on and it treats warnings as errors. In this project, I have a class that overrides Equals() so that I can use some of the nice collection based linq expression (like Except()). Well, code analysis doesn’t like it if you override Equals, but forget to override GetHashCode().

Needless to say, I have to override GetHashCode(). But how does one do this? Some searching turned up a bunch of interesting resources showing how to do this. However, there isn’t some cut and paste code that solves the problem. You have to really understand the implications and usage of this method. For that purpose, I recommend: MSDN’s Object.GetHashCode Method documentation. I also found some interesting discussions on StackOverflow regarding the issue.

In my case, I have an object that I want to be “Equal” to another if three internal values are the same. This is where things get interesting. GetHashCode is just an integer. As such, how to I get it to return a value that is guaranteed not to have the same value as another object with a different set of 3 properties?

For Example, if I just add the numbers, then I could have a problem like this:

  Object A Object B
Field 1 Hash 1 1
Field 2 Hash 5 100
Field 3 Hash 100 5
Sum of Hashes 106 106

The above sums are equal, but the objects are different!

So, a number of implementations use seeds and factors to adjust the numbers and reduce the collisions. One such example (from the above stack overflow article) does so like this:

int hash = 13; 
hash = (hash * 7) + field1.GetHashCode(); 
hash = (hash * 7) + field2.GethashCode(); 
hash = (hash * 7) + field3.GethashCode(); 
return hash;

I’m not sure I fully understand this yet, but I guess I can see how this would improve the chance that things are not going to collide. In the above scenario, I would end up with something like the following:

  Object A Object B
Field 1 Hash 1 1
Field 2 Hash 5 100
Field 3 Hash 100 5
Sum of Hashes wtih Seed and Factor 91 + 1 + 644 + 5 + 4543 + 100

= 4643
91 + 1 + 644 + 100 + 5208 + 5

= 5213

So this seems better, but we’re still not guaranteed that these are unique (at least as far as my feeble mind can comprehend).

Microsoft’s MSDN documentation uses a bitwise XOR to combine hash codes from multiple contained fields. This too seems a bit risky, but I haven’t explored how it works in detail.

So all you intelligent people out there, please tell me what I’m missing. Is there some “algorithm” or factor + seed magic that does guarantee unique hash codes?

Cheers!

author: Nathan Allen-Wagner | posted @ Friday, March 05, 2010 2:23 PM | Feedback (0)

Making WPF Remember Window Size, State, and Position…


I had a need to make my WPF app remember it’s size, position and state for the main window. A bit of “Binging” and I eventually heard the sound of found. Turns out there are a couple ideas out there, but the WINDOWPLACEMENT solution from MSDN seemed to fit the bill the best.

This solution requires using some WIN32 API calls to get and set the information. The upside is that it seems to leverage the smarts built in to Windows regarding multi-monitor detection. The sample says that if the app was previously displayed on a secondary monitor that is no longer available, the app will show up on the available monitor instead. Nice.

The sample also shows how to store these settings in the App’s user settings store. I took this approach for now, but I have a feeling this will be relocated to a more generic location at some point in the future.

Cheers!

author: Nathan Allen-Wagner | posted @ Thursday, March 04, 2010 11:15 AM | Feedback (1)

Except() Extension method Returns the “Difference”


Maybe I’m late to the party, but I just found the Except() LINQ extension method. I knew I loved .NET!

For those of you familiar with set theory, this returns the “difference” between two collections. In my case, I needed to append a set of items to an existing collection, but only if they’re not already in the target collection. This thing was just what I needed.

Here’s the definition:

//
// Summary:
//     Produces the set difference of two sequences by using the default equality
//     comparer to compare values.
//
// Parameters:
//   first:
//     An System.Collections.Generic.IEnumerable<T> whose elements that are not
//     also in second will be returned.
//
//   second:
//     An System.Collections.Generic.IEnumerable<T> whose elements that also occur
//     in the first sequence will cause those elements to be removed from the returned
//     sequence.
//
// Type parameters:
//   TSource:
//     The type of the elements of the input sequences.
//
// Returns:
//     A sequence that contains the set difference of the elements of two sequences.
//
// Exceptions:
//   System.ArgumentNullException:
//     first or second is null.
public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second);

 

Couple this with the ToList() and ForEach() extension method, and you can do this work in about 2 lines of code. Love it!

Cheers!

author: Nathan Allen-Wagner | posted @ Tuesday, March 02, 2010 5:44 PM | Feedback (0)

Should the Domain Model implement INotifyPropertyChanged?


I’ve been discussing an architectural question with a colleague this week. We’re working on a WPF application and using Domain Driven Design and MVVM. The current implementation has a relatively “pure” domain model where the classes in the model do not depend on any UI specific or other external assemblies. They are pretty much pure “POCO” objects.

The question is whether it’s reasonable to have the domain model implement INotifyPropertyChanged and INotifyCollectionChanged (via ObservableCollection).

  • INotifyPropertyChanged is defined in System.dll. It’s part of System.ComponentModel namespace.
  • INotifyCollectionChanged and ObservableCollection are both in WindowsBase.dll. These are in System.Collections.Specialized and System.Collections.ObjectModel respectively.

My take… go for it! Implement INotifyPropertyChanged on the domain model.

We’ve discussed a number of considerations, options and alternatives. A couple of things to consider:

  • WPF has very strong binding support. It works well with a number of different patterns. Each of these provide a way for the UI to keep in sync with the data.
    • INotifyPropertyChanged
    • Raise “___Changed” events; one for each property
    • Other legacy binding interfaces
  • With MVVM, do we fully wrap the model behind view models, or do we allow the view to bind to model directly. If we fully wrap the model, then the ViewModel can intercept all of the changes and raise PropertyChanged accordingly. If the View does bind directly to portions of the model, when we may need to force the UI to rebind manually.

The team came up with a cool option that may help… Wrap the domain model with a “decorator” that adds INotifyPropertyChanged support. The implementation from the team uses ICustomTypeDescriptor to expose the properties of the model, but intercept the “setter” so that the decorator can raise PropertyChanged. WPF honors ICustomTypeDescriptor, which makes this a pretty slick idea. I definitely think this is cool.

Another approach might involve using a “dynamic proxy” to add a decorator automatically. While I haven’t looked into it yet, I’m wondering if this could be done with an AOP framework like Spring.NET. This approach would hide more of the complexity under the surface. Code would interact with something that looks and feels like the original object instance.

There are some challenges with the decorator approach that I’m still wresting through.

  • Complexity – Adding this decorator adds complexity. It must implement the ICustomTypeDescriptor interface, which has quite a few methods. The logic inside uses reflection to return PropertyDescriptors that represent each of the properties on the model. To be complete, the decorator needs to traverse any of it’s child objects and collections so that they are also wrapped with this decorator. This is especially important if the Views bind directly to any portion of the domain model.
  • Decentralized – If two different views create separate instances of the decorator over the same instance a domain model, then one of these views will not get notified when the other view (or ViewModel) changes values on the model. This means that the ViewModels need to implement an additional mechanism for change notification.
  • Loss of Fidelity – One of the use cases that can happen with an object is a relationship between properties. A change in one property may result in changes to other properties. In these cases, the typical INotifyPropertyChanged logic will raise PropertyChanged multiple times; once for each property that was changed. In a decorated scenario, the decorator may not be aware that the model has this dependency between properties and will not raise PropertyChanged for the dependent properties. The work-around is to raise PropertyChanged for all properties, but this means that we loose a little bit of fidelity.

In my mind, taking a dependency on System.dll and WindowsBase.dll is acceptable for the simplicity and functionality that you get in return. Additionally, I think that the disruption caused by these interfaces is minimal. They don’t change the core behavior of the model or add any sort of constraints on implementation (as a base class might do). Instead, they "augment” the functionality.

The model is the single source of truth. Adding change notification on the model means that I have a single source of truth for change notification too. This is huge because it makes things simpler.

The jury is still out on this one. I think that either way is viable. Drop a comment if you have an opinion on the matter.

Cheers!

author: Nathan Allen-Wagner | posted @ Friday, February 26, 2010 12:20 AM | Feedback (0)

Skinning WPF – Call InitializeComponent in App.Xaml


For the past two days, I’ve been trying to get the infrastructure in place for skinning a WPF application. My goal is to support multiple skins and swap them out dynamically while the app is open.

I could get the skin to affect the UI if I set it in the main window’s resource dictionary. However there was a quirk… The application uses WPF frames and pages. The skin was not showing up on frame’s pages. It would only show up on the main window.

I searched Bing, Google and StackOverflow for answers. No luck.

I setup VS to pull down the MS debug symbols so that I could step through the source code for the .NET framework. This was very cool, but not an immediate help.

I went back to StackOverflow and searched for stuff about pages, frames and resource dictionaries. I stumbled on this article and found a comment that provided the solution. It wasn’t the accepted answer, nor was it detailed, but it worked for me! The comment by “Chris” indicating that I should check that the App.Xaml’s code-behind is calling InitializeComponent. I added this call and all of a sudden my pages were skinned too!

Chris indicated that this call to InitializeComponent is what “merges the resource dictionaries.” I looked at the code that is in this generated method and it appears that it is responsible for calling LoadComponent on the App.Xaml file. Without this call, there is no “Application Level” resource dictionary defined in the application. As such, it seems that there is no application container (resource dictionary) available to host the resources for the app.

There is an interesting quirk. At one point, I removed the explicitly included skin such that the App.Xaml file had no resources in its resource dictionary. Then, my code wouldn’t compile. It said that there was no “InitializeComponent” method defined on the App code-behind. What the heck! It was just there!

I added an item back into the App.Xaml’s resource dictionary and then the method was back, plus my app was responding to the skin properly.

So, I’m thinking that I need to follow these rules to get reliable styling / skinning in a WPF app.

  1. Make sure there is at least one resource in the App.Xaml’s resource dictionary.
  2. Make sure the App.Xaml’s code-behind calls InitializeComponent.

Cheers!

author: Nathan Allen-Wagner | posted @ Thursday, February 25, 2010 10:48 PM | Feedback (0)

MVVM: To Wrap or Not to Wrap? BLINQ and CLINQ to the Rescue! (Part 3)


In part 1, I asked the question “Do I expose the model directly, or do I wrap each item in its own view model?” We looked at two plausible options for handling this and saw some code examples of each.

In part 2, I asked the question “Do I expose the model’s collections directly, or do I wrap each collection?” We saw the progression of code to implement this "brute-force". Then we quickly ran away screaming.

This installment (part 3) asks "How do I cleanly and easily wrap the model’s collections with collections of ViewModels?" We'll take a look at a couple LINQ extensions that should make this pretty simple and straight forward. We may even find that these frameworks solve other problems too!

Source code for this article, including the code from part 2, part 3, and unit tests is available for download:

Background:

MVVM says that a ViewModel sits between the View (XAML) and the Model. The ViewModel (VM) exposes data from the model plus additional view-specific details that the view (V) can easily bind to. Ideally, the view can be constructed with zero code-behind. Pure XAML with bindings to manage data and UI state. This is all well and good.

Now, lets say that our model is reasonably real-world and has a entities that contain collections of other entities, which in turn contain collections of other entities. Maybe some of these even have references back to other trees of data. The classic example is customers and orders.

The Model:

Customer
    |_ Shipping Addresses (Collection)
    |_ Billing Address
    |_ Orders (Collection)
    |_ First Name
    |_ Last Name
    |_ Etc…

Step 2 - Revisited: Shipping Addresses (Collection)

We want to bind the shipping addresses into the view. This is a collection of shipping address objects, exposed by the model’s customer object. Previously, we created the ViewModel to expose the customer to the view.

In part 1, we left off with the following customer ViewModel implementation:

using System.ComponentModel;
using System.Collections.ObjectModel;
 
namespace MvvmWrappers.ViewModels
{
    public class CustomerVM : INotifyPropertyChanged
    {
        private Models.Customer _Customer = null;
 
        /// <summary>
        /// Constructor - Add an event handler for PropertyChanged.
        /// </summary>
        public CustomerVM(Models.Customer customer)
        {
            _Customer = customer;
            _Customer.PropertyChanged += new PropertyChangedEventHandler(_Customer_PropertyChanged);
        }
 
        /// <summary>
        /// Watch for changes in the underlying model and propagate those that
        /// are exposed by this ViewModel.
        /// </summary>
        void _Customer_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "FirstName":
                case "LastName":
                    this.OnPropertyChanged(e.PropertyName);
                    break;
            }
        }
 
        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string FirstName
        {
            get { return _Customer.FirstName; }
            set { _Customer.FirstName = value; }
        }
 
        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string LastName
        {
            get { return _Customer.LastName; }
            set { _Customer.LastName = value; }
        }
        
        #region INotifyPropertyChanged
        ...
        #endregion
 
    }
 
}
 

The code in part 2 worked, but overwhelmed the implementation with complex “plumbing” code. So, we seek a better solution.

Enter Bindable LINQ (BLINQ) and Continuous LINQ (CLINQ). These are two frameworks on Codeplex that provide potential solutions to the problem. Both of them implement enhanced LINQ implementations that return a collection that implements INotifyCollectionChanged (like ObservableCollection). Furthermore, they keep that collection in sync with a separate “source” collection.

Bindable LINQ (BLINQ)

For example, if I have an ObservableCollection<Customer>, I could write a LINQ query that looked something like:

ObservableCollection<Models.Customer> customers = new ObservableCollection<MvvmBlinq.Models.Customer>();

IBindableCollection<Models.Customer> filteredCustomers = (
    from c in customers.AsBindable()
    where c.LastName.StartsWith("A")
    select c);

customers.Add(new MvvmBlinq.Models.Customer() { LastName = "Adams" });
customers.Add(new MvvmBlinq.Models.Customer() { LastName = "Benedict" });

Debug.Assert(filteredCustomers.Count == 1, "Filtered customers should have 1 and only 1 record.");

In the above code, you can see that we create an ObservableCollection to hold Customer objects. Initially it is empty. Next, we define a Linq query over that collection that selects customers with a last name that starts with the letter “A”. This query holds records in an IBindableCollection, which also implements INotifyCollectionChanged among other standard collection interfaces. Next, we add 2 customers to the underlying (source) customers ObservableCollection. Lastly, we check the filteredCustomers  linked collection.

Astute readers will notice that without the BLINQ provider, we would not expect to find anything in  filteredCustomers because it was created before we even added items to the customers collection. This is the gift of BLINQ and CLINQ. They will keep the second collection in sync with the underlying source collection.

You say, “So what…. how does this help me?”

Glad you asked! In our case of ViewModels, we want to expose the ShippingAddresses collection by creating a new collection of ShippingAddressVM ViewModels. Each one of these ShippingAddressVMs will wrap the underlying ShippingAddress model.

You say, “Code please…”

using System;
using System.ComponentModel;
using Bindable.Linq;

namespace MvvmBlinq.ViewModels
{
    public class CustomerVM : INotifyPropertyChanged
    {
        private Models.Customer _Customer = null;

        /// <summary>
        /// Constructor - Add an event handler for PropertyChanged.
        /// </summary>
        public CustomerVM(Models.Customer customer)
        {
            _Customer = customer;
            _Customer.PropertyChanged += new PropertyChangedEventHandler(_Customer_PropertyChanged);

            ShippingAddresses = (from sa in _Customer.ShippingAddresses.AsBindable()
                                 select new ShippingAddressVM(sa));
        }

        /// <summary>
        /// Watch for changes in the underlying model and propagate those that
        /// are exposed by this ViewModel.
        /// </summary>
        void _Customer_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "ShippingAddresses":
                    // If this is set to a new collection, then we need to reset the binding here.
                    ShippingAddresses = (from sa in _Customer.ShippingAddresses.AsBindable()
                                         select new ShippingAddressVM(sa));
                    this.OnPropertyChanged(e.PropertyName);
                    break; 

                case "FirstName":
                case "LastName":
                    this.OnPropertyChanged(e.PropertyName);
                    break;
            }
        }

        /// <summary>
        /// A collection of shipping addresses, wrapped in a ShippingAddressVM ViewModel
        /// </summary>
        private IBindableCollection<ShippingAddressVM> _ShippingAddresses;
        public IBindableCollection<ShippingAddressVM> ShippingAddresses
        {
            get { return _ShippingAddresses; }
            set
            {
                if (value == _ShippingAddresses)
                    return;

                _ShippingAddresses = value;

                OnPropertyChanged("ShippingAddresses");
            }
        }

        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string FirstName
        {
            get { return _Customer.FirstName; }
            set { _Customer.FirstName = value; }
        }

        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string LastName
        {
            get { return _Customer.LastName; }
            set { _Customer.LastName = value; }
        }

        #region INotifyPropertyChanged
        ...
        #endregion

    }
}

Compared to our last attempt, this version is much simpler! We hook the ShippingAddresses ViewModel collection up to the Model in the constructor via the Bindable LINQ query. This query is a standard LINQ query, except for the additional “AsBindable()” extension method in the query. The query doesn’t filter out any records. Rather, it creates a new ShippingAddressVM instance to wrap each of the underlying ShippingAddress model instances.

Net Result: A synchronized, bindable, ViewModel-wrapped collection.

You may also note that we re-bind the BLINQ collection if the model’s ShippingAddress PropertyChanged notification fires. This is to support the case where the model’s collection of shipping addresses is completely replaced with a new collection.

Continuous LINQ (CLINQ)

The pattern for using CLINQ is very similar to BLINQ. The two frameworks are remarkably similar, although each has some unique features.

using System;
using System.ComponentModel;
using ContinuousLinq;

namespace MvvmClinq.ViewModels
{
    public class CustomerVM : INotifyPropertyChanged
    {
        private Models.Customer _Customer = null;

        /// <summary>
        /// Constructor - Add an event handler for PropertyChanged.
        /// </summary>
        public CustomerVM(Models.Customer customer)
        {
            _Customer = customer;
            _Customer.PropertyChanged += new PropertyChangedEventHandler(_Customer_PropertyChanged);

            ShippingAddresses = (from sa in _Customer.ShippingAddresses
                                 select new ShippingAddressVM(sa));
        }

        /// <summary>
        /// Watch for changes in the underlying model and propagate those that
        /// are exposed by this ViewModel.
        /// </summary>
        void _Customer_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "ShippingAddresses":
                    // If this is set to a new collection, then we need to reset the binding here.
                    ShippingAddresses = (from sa in _Customer.ShippingAddresses
                                         select new ShippingAddressVM(sa));
                    this.OnPropertyChanged(e.PropertyName);
                    break; 

                case "FirstName":
                case "LastName":
                    this.OnPropertyChanged(e.PropertyName);
                    break;
            }
        }

        /// <summary>
        /// A collection of shipping addresses, wrapped in a ShippingAddressVM ViewModel
        /// </summary>
        private ReadOnlyContinuousCollection<ShippingAddressVM> _ShippingAddresses;
        public ReadOnlyContinuousCollection<ShippingAddressVM> ShippingAddresses
        {
            get { return _ShippingAddresses; }
            set
            {
                if (value == _ShippingAddresses)
                    return;

                _ShippingAddresses = value;

                OnPropertyChanged("ShippingAddresses");
            }
        }

        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string FirstName
        {
            get { return _Customer.FirstName; }
            set { _Customer.FirstName = value; }
        }

        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string LastName
        {
            get { return _Customer.LastName; }
            set { _Customer.LastName = value; }
        }

        #region INotifyPropertyChanged
        ...
        #endregion

    }
}

 

You’ll notice that the above code is almost identical to the BLINQ example. In fact, it is slightly simpler since CLINQ doesn’t require the “AsBindable()” call. CLINQ returns a “ContinuousCollection” or a “ReadOnlyContinuousCollection”. This output also supports the standard collection interfaces, including INotifyCollectionChanged. In this case, CLINQ sees that the query reshapes the data and returns a Read Only collection.

CLINQ vs. BLINQ vs. Others

So what is the difference between these frameworks? Kyle Lanser posted a nice answer to this question on StackOverflow. He indicates that they are very similar in some respects. Both projects come with source code and both have some pretty nice sample applications.

BLINQ includes the ability to walk the query tree and detect other objects & collections that support change notification. It will then monitor these to keep the bound collection fully in sync with the underlying collection and other objects in the LINQ query. (See the BLINQ site on CodePlex for further details.)

CLINQ appears to support the possibility for Bi-Directional synchronization in cases where the CLINQ query does not reshape the data, but simply filters it. In this case, it may be possible to make changes against the bound query and see those changes in the source query. I have not tested this yet since it doesn’t really help with MVVM model wrapping scenario. You can find Continuous LINQ on CodePlex.

There are other frameworks out there. The one that I’ve seen is called Obtics. This is another CodePlex project. It appears to be quite feature rich, but time did not permit me to investigate it all that much. My initial skimming of the project made me feel a bit overwhelmed. There is a lot of “stuff” in there, which prevented me from grasping it quickly.

Bi-Directional Sync?

The implementations above do not support bi-directionally synchronization of the source and the bound collection. Changes to the model will show up in the BLINQ collection, but not vice-versa.

In our case, this makes sense. We are projecting a new object from the LINQ query, which reshapes the data. A given projection may not have all the data needed to reverse the flow of data. This is the same behavior as a SQL Server view. SQL won’t let you insert into a view that pulls from multiple sources or restructures the data. (Yes, there are InsteadOf triggers, but that’s beside the point ;-)

So what do we do to get data back into the model?

I’m going to have to get back to you on that. The short answer is that you route that “command” or logic through your ViewModel, which in turn modifies the underlying model on your behalf. In many cases, this should be relatively straight forward. In cases where you need the View to be able to push data into the ViewModel’s bound collection, you may want to take a look at the code in part 2 of this series and see if you can morph that toward a workable solution.

Other Uses of BLINQ / CLINQ

These two frameworks offer some pretty compelling features in a couple other scenarios.

Filtering

WPF offers the CollectionView as an intermediary between your collection and the bound control. This supports some nice features for data navigation, filtering and grouping. This is a good option, but BLINQ and CLINQ offer an alternative that may be more or less appropriate depending on your scenario.

WPF’s CollectionViewSource implements filters by raising the Filter event. In that event, you indicate whether or not to include the current item in the view.

Using BLINQ / CLINQ, the filtering could be done in the ViewModel by exposing a bound collection that is backed by a single LINQ query which defines the filter.

Scalar Values

BLINQ has a nice feature that lets you create a scalar value output of a LINQ query that is bound to an underlying collection. This scalar value is kept in sync with the underlying collection automatically. The View could then bind to this value and it would update automatically whenever any records in the underlying collections changed the resulting aggregate.

Conclusion

We started with the question of whether to try and fully wrap the Model behind ViewModels. Part 1 showed two options. If you take the approach of exposing the Model to the View directly, then you may not need the structure outlined above.

However, if you decide that you do want to fully (or mostly) wrap the Model, then the above seems like a feasible approach. It is relatively straight forward to construct and maintain. Plus, the usage of LINQ provides a really powerful way to filter, aggregate, and reshape the data from the Model. Isn’t that the whole point of ViewModels anyway?

Drop a comment if you have an opinion or experience on the matter.

Cheers!

author: Nathan Allen-Wagner | posted @ Tuesday, February 09, 2010 10:45 PM | Feedback (2)

MVVM: To Wrap or Not to Wrap? Should ViewModels wrap collections too? (Part 2)


In my previous post, I asked the question “Do I expose the model directly, or do I wrap each item in its own view model?” We looked at two plausible options for handling this and saw some code examples of each.

Now it’s time for a more interesting and challenging scenario: Do I expose the model’s collections directly, or do I wrap each collection? Let me paint this picture a bit so that we can see the scenario and the challenges.

MVVM says that a ViewModel sits between the View (XAML) and the Model. The ViewModel (VM) exposes data from the model plus additional view-specific details that the view (V) can easily bind to. Ideally, the view can be constructed with zero code-behind. Pure XAML with bindings to manage data and UI state. This is all well and good.

Now, lets say that our model is reasonably real-world and has a entities that contain collections of other entities, which in turn contain collections of other entities. Maybe some of these even have references back to other trees of data. The classic example is customers and orders.

The Model:

Customer
    |_ Shipping Addresses (Collection)
    |_ Billing Address
    |_ Orders (Collection)
    |_ First Name
    |_ Last Name
    |_ Etc…

Step 2: Shipping Addresses (Collection)

We want to bind the shipping addresses into the view. This is a collection of shipping address objects, exposed by the model’s customer object. Previously, we created the ViewModel to expose the customer to the view. One option fully wrapped the customer object and the other exposed portions of the model directly to the view.

Disclaimer:
The code below shows an intermediate solution on the road to something reasonable. Please see future posts in this series for improved options.

In the previous post, we left off with the following class:

using System.ComponentModel;
using System.Collections.ObjectModel;
 
namespace MvvmWrappers.ViewModels
{
    public class CustomerVM : INotifyPropertyChanged
    {
        private Models.Customer _Customer = null;
 
        /// <summary>
        /// Constructor - Add an event handler for PropertyChanged.
        /// </summary>
        public CustomerVM(Models.Customer customer)
        {
            _Customer = customer;
            _Customer.PropertyChanged += new PropertyChangedEventHandler(_Customer_PropertyChanged);
        }
 
        /// <summary>
        /// Watch for changes in the underlying model and propagate those that
        /// are exposed by this ViewModel.
        /// </summary>
        void _Customer_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "FirstName":
                case "LastName":
                    this.OnPropertyChanged(e.PropertyName);
                    break;
            }
        }
 
        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string FirstName
        {
            get { return _Customer.FirstName; }
            set { _Customer.FirstName = value; }
        }
 
        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string LastName
        {
            get { return _Customer.LastName; }
            set { _Customer.LastName = value; }
        }
        
        #region INotifyPropertyChanged
        ...
        #endregion
 
    }
 
}
 

Now we need to add a collection that exposes the Shipping Addresses, but not directly. We want to expose each shipping address through a ViewModel. This means that we need to somehow wrap each item, and put these into a collection. Additionally, we are good binding citizens and expose the data as a collection that supports INotifyCollectionChanged, such as ObservableCollection.

Assuming that we previously created a ViewModel for shipping address, our first attempt at modifying the CustomerVM might look like this:

using System.ComponentModel;
using System.Collections.ObjectModel;
using System;

namespace MvvmWrappers.ViewModels
{
    public class CustomerVM : INotifyPropertyChanged
    {
        private Models.Customer _Customer = null;

        /// <summary>
        /// Constructor - Add an event handler for PropertyChanged.
        /// </summary>
        public CustomerVM(Models.Customer customer)
        {
            _Customer = customer;
            _Customer.PropertyChanged += 
                new PropertyChangedEventHandler(_Customer_PropertyChanged);

            // Wrap each ShippingAddress in a ViewModel.
            _ShippingAddresses = new ObservableCollection<ShippingAddressVM>();
            foreach (var sa in customer.ShippingAddresses)
                _ShippingAddresses.Add(new ShippingAddressVM(sa));
        }

        /// <summary>
        /// Watch for changes in the underlying model and propagate those that
        /// are exposed by this ViewModel.
        /// </summary>
        void _Customer_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "FirstName":
                case "LastName":
                    this.OnPropertyChanged(e.PropertyName);
                    break;
            }
        }


        private ObservableCollection<ShippingAddressVM> _ShippingAddresses;
        public ObservableCollection<ShippingAddressVM> ShippingAddresses
        {
            get { return _ShippingAddresses; }
            set
            {
                if (value == _ShippingAddresses)
                    return;

                _ShippingAddresses = value;
                OnPropertyChanged("ShippingAddresses");
            }
        }
        


        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string FirstName
        {
            get { return _Customer.FirstName; }
            set { _Customer.FirstName = value; }
        }

        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string LastName
        {
            get { return _Customer.LastName; }
            set { _Customer.LastName = value; }
        }
        
        #region INotifyPropertyChanged
        ...
        #endregion

    }
}

 

This is a good start, but lacking a couple things. First off, the model’s collections support INotifyCollectionChanged (via ObservableCollection). We’d like the UI to automatically respond if an item is added or removed from the model.

Likewise, we’d like any changes to the ViewModel collections to be propagated to the Model.

As in the previous case, this probably means that we need to intercept the CollectionChanged event and handle it accordingly. Here’s a brute-force approach, albeit a quite painful and ugly:

using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;

namespace MvvmWrappers.ViewModels
{
    public class CustomerVM : INotifyPropertyChanged
    {
        private Models.Customer _Customer = null;
        private bool _IgnoreChanges = false;



        /// <summary>
        /// Constructor - Add an event handler for PropertyChanged.
        /// </summary>
        public CustomerVM(Models.Customer customer)
        {
            _Customer = customer;
            _Customer.PropertyChanged += new PropertyChangedEventHandler(_Customer_PropertyChanged);

            // Wrap each ShippingAddress in a ViewModel.
            _ShippingAddresses = new ObservableCollection<ShippingAddressVM>();
            foreach (var sa in customer.ShippingAddresses)
                _ShippingAddresses.Add(new ShippingAddressVM(sa));


            _ShippingAddresses.CollectionChanged += 
                new NotifyCollectionChangedEventHandler(ShippingAddressVMs_CollectionChanged);
            _Customer.ShippingAddresses.CollectionChanged += 
                new NotifyCollectionChangedEventHandler(ShippingAddresses_CollectionChanged);
        }

        void ShippingAddressVMs_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (_IgnoreChanges)
                return;

            _IgnoreChanges = true;

            // If a reset, then e.OldItems is empty. Just clear and reload.
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset)
            {
                _Customer.ShippingAddresses.Clear();

                foreach (var sa in ShippingAddresses)
                    _Customer.ShippingAddresses.Add(sa.GetUnderlyingObject());
            }
            else
            {
                // Remove items from collection.
                var toRemove = new List<Models.ShippingAddress>();

                if (null != e.OldItems && e.OldItems.Count > 0)
                    foreach (var item in e.OldItems)
                        foreach (var existingItem in _Customer.ShippingAddresses)
                            if (((ShippingAddressVM)item).IsViewFor(existingItem))
                                toRemove.Add(existingItem);

                foreach (var item in toRemove)
                    _Customer.ShippingAddresses.Remove(item);

                // Add new items to the collection.
                if (null != e.NewItems && e.NewItems.Count > 0)
                    foreach (var item in e.NewItems)
                        _Customer.ShippingAddresses.Add(((ShippingAddressVM)item).GetUnderlyingObject());
            }

            _IgnoreChanges = false;
        }

        void ShippingAddresses_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (_IgnoreChanges)
                return;

            _IgnoreChanges = true;
            
            // If a reset, then e.OldItems is emtpy. Just clear and reload.
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset)
            {
                ShippingAddresses.Clear();

                foreach (var sa in _Customer.ShippingAddresses)
                    _ShippingAddresses.Add(new ShippingAddressVM(sa));
            }
            else
            {
                // Remove items from collection.
                var toRemove = new List<ShippingAddressVM>();

                if (null != e.OldItems && e.OldItems.Count > 0)
                    foreach (var item in e.OldItems)
                        foreach (var existingItem in ShippingAddresses)
                            if (existingItem.IsViewFor((Models.ShippingAddress)item))
                                toRemove.Add(existingItem);

                foreach (var item in toRemove)
                    ShippingAddresses.Remove(item);

                // Add new items to the collection.
                if (null != e.NewItems && e.NewItems.Count > 0)
                    foreach (var item in e.NewItems)
                        ShippingAddresses.Add(new ShippingAddressVM((Models.ShippingAddress)item));
            }

            _IgnoreChanges = false;
        }

        /// <summary>
        /// Watch for changes in the underlying model and propagate those that
        /// are exposed by this ViewModel.
        /// </summary>
        void _Customer_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "FirstName":
                case "LastName":
                    this.OnPropertyChanged(e.PropertyName);
                    break;

                case "ShippingAddresses":
                    // Underlying collection was rebuilt.
                    this.ShippingAddresses_CollectionChanged(
                        this,
                        new NotifyCollectionChangedEventArgs(
                            NotifyCollectionChangedAction.Reset
                        )
                    );

                    break;
            }
        }

        /// <summary>
        /// A collection of shipping addresses, wrapped in a ShippingAddressVM ViewModel
        /// </summary>
        private ObservableCollection<ShippingAddressVM> _ShippingAddresses;
        public ObservableCollection<ShippingAddressVM> ShippingAddresses
        {
            get { return _ShippingAddresses; }
            set
            {
                if (value == _ShippingAddresses)
                    return;

                _ShippingAddresses.CollectionChanged -= ShippingAddressVMs_CollectionChanged;
                _ShippingAddresses = value;
                _ShippingAddresses.CollectionChanged += ShippingAddressVMs_CollectionChanged;

                // Underlying collection was rebuilt.
                this.ShippingAddressVMs_CollectionChanged(
                    this,
                    new NotifyCollectionChangedEventArgs(
                        NotifyCollectionChangedAction.Reset
                    )
                );

                OnPropertyChanged("ShippingAddresses");
            }
        }

        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string FirstName
        {
            get { return _Customer.FirstName; }
            set { _Customer.FirstName = value; }
        }

        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string LastName
        {
            get { return _Customer.LastName; }
            set { _Customer.LastName = value; }
        }

        #region INotifyPropertyChanged
        ...
        #endregion

    }
}

 

 

 

Now we see that the collections stay in sync when items are added to the Model. The Model also stays in sync with changes to the ViewModel (I wrote Unit Tests to prove it ;-). This implementation works, but is less than ideal.

What to do? Is there a simple way to achieve MVVMs goals of wrapping the Model in VMs, including collections?

There may be hope! See part 3 for a review of some interesting frameworks that help with objects that support change notification. We’ll look into using something like BLINQCLINQ, or Obtics. These three frameworks offer LINQ based implementations that can expose an observable collection as a new, synchronized collection that is based on a LINQ query against the source.

Cheers!

author: Nathan Allen-Wagner | posted @ Tuesday, February 09, 2010 2:48 PM | Feedback (4)

MVVM: To Wrap or Not to Wrap? How much should the ViewModel wrap the Model? (Part 1)


The WPF community seems pretty happy with the MVVM pattern for WPF development. I can see why. It’s a great fit for WPF and its strong data-binding support. It provides a very nice layer for managing UI state, translating, formatting, and aggregating data.

So let’s say that I adopt MVVM for my project. I think there are some scenarios that still need definition. One of these is “To Wrap or Not to Wrap?” Let me explain…

MVVM says that a ViewModel sits between the View (XAML) and the Model. The ViewModel (VM) exposes data from the model plus additional view-specific details that the view (V) can easily bind to. Ideally, the view can be constructed with zero code-behind. Pure XAML with bindings to manage data and UI state. This is all well and good.

Now, lets say that our model is reasonably real-world and has a entities that contain collections of other entities, which in turn contain collections of other entities. Maybe some of these even have references back to other trees of data. The classic example is customers and orders.

The Model:

Customer
    |_ Shipping Addresses (Collection)
    |_ Billing Address
    |_ Orders (Collection)
    |_ First Name
    |_ Last Name
    |_ Etc…

The Question:

I want to use MVVM, so I start working on the view models. I create one for Customer, start adding my properties and realize that I have a decision to make. Do I expose the model directly, or do I wrap each item in its own view model?

We have a couple options, and each has some consequences.

STEP 1: The Customer Object

Let’s start with the Customer object itself:

Customer has a bunch of data on it. The VM guidelines suggest that the VM should expose a property for each value on the model that it wants to expose. In this case, I want to show the first and last name on the view.

Option 1: Wrap Customer Model

To wrap first and last name, I create two new properties on the VM. One for each property. Being a good binding citizen, I make the VM support INotifyPropertyChanged and setup my property setter’s accordingly. (See my INotifyPropertyChanged Snippets post).

My model happens to support INotifyPropertyChanged too, and I want the View to know right away if the data changes in the underlying model. What to do? Looks like I need to add an event handler on my Customer instance’s PropertyChanged event. In that event, I need to check what property changed and bubble selected events via my VM’s own PropertyChanged event. Here’s the CustomerVM class so far…

using System.ComponentModel;
using System.Collections.ObjectModel;

namespace MvvmWrappers.ViewModels
{
    public class CustomerVM : INotifyPropertyChanged
    {
        private Models.Customer _Customer = null;

        /// <summary>
        /// Constructor - Add an event handler for PropertyChanged.
        /// </summary>
        public CustomerVM(Models.Customer customer)
        {
            _Customer = customer;
            _Customer.PropertyChanged += new PropertyChangedEventHandler(_Customer_PropertyChanged);
        }

        /// <summary>
        /// Watch for changes in the underlying model and propagate those that
        /// are exposed by this ViewModel.
        /// </summary>
        void _Customer_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "FirstName":
                case "LastName":
                    this.OnPropertyChanged(e.PropertyName);
                    break;
            }
        }

        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string FirstName
        {
            get { return _Customer.FirstName; }
            set { _Customer.FirstName = value; }
        }

        /// <summary>
        /// Delegate the storage to the model.
        /// Also delegate the INotifyPropertyChanged handling to the model.
        /// </summary>
        public string LastName
        {
            get { return _Customer.LastName; }
            set { _Customer.LastName = value; }
        }
        
        #region INotifyPropertyChanged
        ...
        #endregion

    }

}
 

Option 2: Not to Wrap

Let's say that I decide the above code is too much. So, I choose to expose the Customer model directly to the view. I keep the VM around though, because I may have other view related properties that I want to manage. These might include things like whether to expand or collapse the shipping addresses section. The VM is still valuable, but is not doing as much.

public class CustomerVM : INotifyPropertyChanged
{
    private Models.Customer _Customer = null;
    public CustomerVM(Models.Customer customer)
    {
        _Customer = customer;
    }

    
    private Models.Customer _Customer;
    public Models.Customer Customer 
    {
        get{ return _Customer;}
        set
        {
            if (value == _Customer)
                return;
            
            _Customer = value;
            OnPropertyChanged("Customer");
        }
    }

    #region INotifyPropertyChanged
    ...
    #endregion

}

 

Conclusions:

Where do we stand? Both options are viable (IMHO anyway).

The first options seems to be a more rigorous and “pure” implementation, but the cost is additional plumbing. In some cases, this is definitely justified. For example, I may want to have a property that exposes the full name in a single field. Here, the VM is very helpful and makes this task simple. However, there are many cases where the values are simply passed through.

The second option is simpler and seems more pragmatic. It says “I’ll add properties on the VM where they are needed, but I’m not trying to control all access to the model.”

In reviewing the sample application from the Caliburn framework, they implement the VM using option 2. The ViewModel exposes the model directly, including a number of child collections. The view then binds to both the model and the VM. This seems reasonable and simpler, but exposes the model directly to the view.

There are discussions of this question by others, but I don’t see conclusive answers. Ward Bell asks the question in his Birth and Death of MVVM Triads. The question is also asked on StackOverflow.

For me, the jury is still out. I prefer Option 1 because is it a bit more pure and clean. In the above case, the complexity is manageable. Things get more interesting in Part 2 of this post, where I’ll show some scenarios related to exposing a collection.

Cheers!

author: Nathan Allen-Wagner | posted @ Tuesday, February 09, 2010 11:11 AM | Feedback (4)

C# Snippets for Properties that support INotifyPropertyChanged


Since WPF likes INotifyPropertyChanged on bound objects, I looked for a snippet to help out.

Matthias Shapiro had a good version for the interface implementation and a property declaration. I made a couple adjustments to the snippets based on personal preference (check if the value has changed before raising the event / remove the region from the property.

Then added some property verification support based on the snippet sample from Philipp Sumi. The property verification uses reflection to check if the property exists. If not, it throws an exception. This function is marked with a Conditional attribute so that it is only called in DEBUG builds.

The resulting snippets are as follows:

INotifyPropertyChanged Interface Implementation

<?xml version="1.0" encoding="utf-8" ?>
<
CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<
CodeSnippet Format="1.0.0">
<
Header>
<
Author>
Matthias Shapiro (Original),
Philipp Sumi (VerifyProperty method),
Nathan Allen-Wagner (Modifications)
</Author>
<
HelpUrl>http://blog.alner.net/</HelpUrl>
<
SnippetTypes>
<
SnippetType>Expansion</SnippetType>
</
SnippetTypes>
<
Title>
NotifyObject:
Use this to add the INotifyPropertyChange implementation
to a class. Supports property name verification in DEBUG
builds.
</Title>
<
Shortcut>notifyo</Shortcut>
</
Header>
<
Snippet>
<
Code Language="csharp">
<![CDATA[
#region INotifyPropertyChanged

/// <summary>
/// The PropertyChanged event is used by consuming code
/// (like WPF's binding infrastructure) to detect when
/// a value has changed.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;

/// <summary>
/// Raise the PropertyChanged event for the
/// specified property.
/// </summary>
/// <param name="propertyName">
/// A string representing the name of
/// the property that changed.</param>
/// <remarks>
/// Only raise the event if the value of the property
/// has changed from its previous value</remarks>
protected void OnPropertyChanged(string propertyName)
{
// Validate the property name in debug builds
VerifyProperty(propertyName);

if(null != PropertyChanged)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

/// <summary>
/// Verifies whether the current class provides a property with a given
/// name. This method is only invoked in debug builds, and results in
/// a runtime exception if the <see cref="OnPropertyChanged"/> method
/// is being invoked with an invalid property name. This may happen if
/// a property's name was changed but not the parameter of the property's
/// invocation of <see cref="OnPropertyChanged"/>.
/// </summary>
/// <param name="propertyName">The name of the changed property.</param>
[System.Diagnostics.Conditional("DEBUG")]
private void VerifyProperty(string propertyName)
{
Type type = this.GetType();

// Look for a *public* property with the specified name
System.Reflection.PropertyInfo pi = type.GetProperty(propertyName);
if (pi == null)
{
// There is no matching property - notify the developer
string msg = "OnPropertyChanged was invoked with invalid " +
"property name {0}. {0} is not a public " +
"property of {1}.";
msg = String.Format(msg, propertyName, type.FullName);
System.Diagnostics.Debug.Fail(msg);
}
}

#endregion
$end$
]]>
</
Code>
</
Snippet>
</
CodeSnippet>
</
CodeSnippets>

Property Declaration for INotifyPropertyChanged

<?xml version="1.0" encoding="utf-8" ?>
<
CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<
CodeSnippet Format="1.0.0">
<
Header>
<
Author>
Matthias Shapiro (Original),
Nathan Allen-Wagner (Modifications)
</Author>
<
HelpUrl>http://blog.alner.net/</HelpUrl>
<
SnippetTypes>
<
SnippetType>Expansion</SnippetType>
</
SnippetTypes>
<
Title>
INotifyPropertyChanged Property: Use this to create a
new property INotifyPropertyChanged implementation.
</Title>
<
Shortcut>notifyp</Shortcut>
</
Header>
<
Snippet>
<
Declarations>
<
Literal>
<
ID>publicProperty</ID>
<
ToolTip>The name of the private property</ToolTip>
<
Default>MyProperty</Default>
</
Literal>
<
Literal>
<
ID>type</ID>
<
ToolTip>
The type of the property
(e.g. string, double, bool, Brush, etc.)
</ToolTip>
<
Default>string</Default>
</
Literal>
</
Declarations>
<
Code Language="csharp">
<![CDATA[
private $type$ _$publicProperty$;
public $type$ $publicProperty$
{
get{ return _$publicProperty$;}
set
{
if (value == _$publicProperty$)
return;

_$publicProperty$ = value;
OnPropertyChanged("$publicProperty$");
}
}

$end$
]]>
</
Code>
</
Snippet>
</
CodeSnippet>
</
CodeSnippets>

 

As usual, use at your own risk. Let me know if you find any issues.

Cheers!

author: Nathan Allen-Wagner | posted @ Monday, February 01, 2010 3:08 PM | Feedback (2)

Win7: Large Fonts a Little Rough…


Previously, I posted:

Large Fonts – Not sure yet…
My machine has a pretty high resolution display (1680 x 1050). Win 7 defaulted the fonts to use “medium” fonts, instead of small fonts. This is nice because things are not so tiny, but it has to resize some of the images here an there. Also, not all applications have good support for “larger fonts”, so the windows can have an odd layout in some cases. I like that Win 7 is supporting large fonts and hi-res displays better. I think it’s just a matter of time for apps to start handling this more gracefully.

So, I like the fact that it makes my fonts readable on a high-res monitor, but I have noticed that many apps don’t work quite right. This shows up on web sites, Seesmic’s intro screens, etc. It also makes a number of items slightly blurry since windows has to re-size bitmap images.

I think that “large font” support will improve over time, but for the next couple days, I’ll switch to the default size and see how that goes.

Cheers!

author: Nathan Allen-Wagner | posted @ Wednesday, January 27, 2010 12:02 PM | Feedback (0)