Saturday, September 29, 2012

Dynamically Generated Properties using CustomTypeDescriptor for WPF Binding

In the previous post we discussed how we can use DynamicObject to add dynamically generated properties to our types. This post would continue the discussion but here we are going to discuss ICustomTypeDescriptor to add dynamically generated properties. We will also discuss how we can use these properties for WPF Binding. In the last part of our discussion we will be adding the missing bit to support change notifications for these properties.

System.ComponentModel has a default implementation of ICustomTypeDescriptor. This provides the interface implementation requirements in the form of virtual methods which can be overridden in your custom type. We will be using this implementation as part of our discussion. Basically the following methods from the interface do all the magic. We can provide implementation of these methods to introduce our custom properties in order to fake the client that the type already has these properties.

This is also more to do with WPF Binding System. If the DataContext implements ICustomTypeDescriptor then WPF Binding system uses the Type Descriptor instead of relying on reflection. From msdn, this discussion is very useful to learn how binding references are resolved.

Both of the overloads of GetProperties() methods return PropertyDescriptorCollection. It is a collection of PropertyDescriptor. Overriding these methods and adding further items to the collection can give the impression to the WPF Binding system of having these properties by the type itself. Let's provide a descriptor inheriting from PropertyDescriptor.

In the above property descriptor, please look at GetValue and SetValue methods. The type is holding a field called propertyValue. These methods operate on this field. We don't need these methods for working with WPF Binding system and need them to work with the additional properties in our code. Let's use this descriptor to create a Type implementing ICustomTypeDescriptor. We are maintaining an internal collection _myProperties to hold the additional properties which are not provided by the type itself. This would create perception of dynamically generated properties. An additional method, called AddProperty, is provided to add an item to the collection. The method is generic to support a property with any supported type. The type is also implementing INotifyPropertyChanged interface providing change propagation support. This would raise familiar PropertyChanged event when a value is changed using SetValue method.

Now let's use this type and introduce a new type called StudentViewModel. It maintains a property called FirstName. Now here is the intersting part. We are adding another property LastName using AddProperty method of the base type ViewModelBase.

Similarly, we add a new type called MainViewModel. Here also we are adding a property called MainTitle. We are setting the value of this property as "Main App Window". It is maintaining a collection holding a collection of StudentViewModel. Here we are adding members to the collection. We are setting the property of FirstName directly. We are setting the other property LastName using SetPropertyValue method. Another property SelectedStudent is provided to hold the currently selected student.

Now let's use these view models for WPF Binding. We are using MainViewModel as the DataContext of MainWindow. The view mainly has a ListBox and DataGrid to show items from Students collection in the DataContext. There is no difference in the use of FirstName and LastName properties from StudentViewModel even when LastName is being dynamically generated. You can also notice MainTitle being used for App banner.

Since the basic setup is done. Now let's run the application now. We should see the following display:

Supporting Change Notifications
This looks perfect but this has one limitation. This doesn't support change notifications for newly added properties. Since we are using PropertyDescritptor to add dynamic properties, we can easily add this behavior using OnValueChanged from the type. We first need to update the ViewModelBase so that whenever a property is added, we add the ValueChanged to the property descriptor and call OnPropertyChanged from ViewModelBase similary to the existing properties from the inheriting types.

Next we need to add the support in the inheriting PropertyDesriptor type i.e. CustomPropertyDescriptor. This would cause the ValueChanged to be used when SetValue method is called. In turn, PropertyChanged from ViewModelBase would be raised for the same property.


Friday, September 21, 2012

DynamicObject & WPF Binding

In this post we are going to find out how .net 4.0 dynamic types can help us introducing dynamically generated properties which could be used by WPF binding system.

Properties with dynamic types in a Custom Class:
We can always declare properties with dynamic type. It allows to bypass static type checking along with duck-type support for our members. This is unlike object type where if it is not provided by the object type then we needed to use reflection in order to fulfill static type checks. Please remember that the properties of an object marked as dynamic is already supported in .net framework 4.0. Those properties have a dynamic type but they are not dynamically generated. Their usages are just replaced by expressions at compile-time. At runtime, these expressions are going to resolve and could cause binding exceptions if the assigned type does not support the expected members. Further detalis can be found here. Anyhow, WPF binding system does support binding to properties with dynamic type.

.net framework dynamic feature has three main types including DynamicObject, ExpandoObject and IDynamicMetaObjectProvider. As a matter of fact, DynamicObject can be smartly used to support dynamically generated properties. In the following example, let's look at a type called ViewModelBase. We can use this type as a base for all those view models which might need dynamically generated properties. This example is using an overlapped concept of model and view model. Most of the time, you might want your view models to be having dynamically generated properties based on the data streams available through XML or JSON. You might read some data from your database and might want to add properties based on this data.

Overriding DynamicObject's members including TrySetMember and TryGetMembers is providing us the means to introduce dynamically generated information which could be used as properties for WPF Binding. TrySetMembers is used by the runtime when WPF binding system updates the value of the property. On the other hand, TryGetMember is used to get the value of the property. You can see we have even implemented INotifyPropertyChanged to provide change notifications for these dynamically generated properties.

The dynamic members and their values are maintained in a Dictionary. We can simply make the members as of dynamic type. But since there is no expected behavior, I have just kept it as System.Object. The collection is filled up the first time this Dictionary is used in the code. We are simply filling it up the collection in the constructor using passed in values in the parameter propertyNames.

Unlike an ExpandoObject, the access to members of DynamicObject are statically checked in c# code at compile time. That is why we need to provide a special pair of methods to get and set the properties identified by its name. The members are named as SetPropertyValue and GetPropertyValue.

We need to pay special attention to the constructor. This is accepting the list of perceived dynamically generated members. Child types can also pass the members when their constructor is called for instantiation. This is exactly what we have done in the case of MainViewModel. It just needs a property, called MainTitle. This is passed to the base class which would do the whole magic required for the binding system to work.

We are setting the value of MainTitle in the constructor. Let's try to use this view model as a DataContext. The following is a view called MainWindow. Here we are binding MainTitle to a TextBox's Text property. With a TextBox, we can test if it is set and get as expected.

Let's run this now. The view is loaded on the screen as follows. put some break points in your code and try to update the Title. You should notice the breakpoints being hit. You should eventually see ViewModelBase.TryGetMember being called.

Basically we haven't even created a type with dynamically generated properties. We have created an object which could hold name / value pairs which supports DataBinding. There might be types inheriting from ViewModelBase which takes the property names as input parameters of their constructors. Now the same type can be instantiated with different property names and hence it would have different perceived properties. Now we can have different products supporting different properties altogether. This is different than the concept of a type which has specific set of properties.

One issue with using DynamicObject for such purpose is the absence of type description. We have been using the termss "perceived" and "fake" throughout this post as they are not real. There is no way we can find out what members are supported except keep try setting their value. A type should provide a mechanism to expose its type information. We should be able to query for its members. In the DynamicObject based implementation, there is no way we can find out what properties are there for an object's type.

Collections of DynamicObject based Types
Now let's see how we can handle collection of DynamicObject type of objects. Here we are adding a collection called Students. This is of type StudentViewModel which is eventually based on DynamicObject. We have also added an AmazingStudent property which is to hold an amazing student from this collection.

The following XAML code uses the collection for Binding. We are using the collection to bind to a ListBox and a DataGrid. As you can see we can bind element's members from a collection using a DataTemplate in the ListBox. The columns in the DataGrid can be directly bound.

Let's run this again. Now we can see the collection members correctly shown in the two panels. The view is loaded as follows:

As we know DataGrid has this amazing capability of showing auto-generatd columns using its AutoGenerateColumns property. Setting the proerty to true allows us to bind a collection holding auto-generated properties. We can use it to bind types including DataTable with no information about its column names. DataGrid discovers these columns and binds to them. Please remember that this auto-generation does not support DynamicObject based types. Let's update the DataGrid code as follows:

Now we try to run it again. Please notice the empty grid in the view.

Download Code

Saturday, September 15, 2012

Static Properties and Change Notification [WPF 4.5 RC New Features]

Change propagation is one of the features in XAML technologies which makes MVVM possible. We have included it as one of the MVVM enablers for WPF and Silverlight in the book MVVM Survival Guide for Enterprise Architectures in WPF and Silverlight. Up until .net 4.0, change propagation support was only available for instance properties i.e. they weren't available for static properties. In .net 4.5, this feature is added. In this post, we are going to discuss how we can add change propagation support for our static properties.

Let's add a user control which takes first and last names as input. It binds the Text property of these text boxes to properties in the data context.

Now let's add another user control, it also expects properties with the same names in the data context. The only difference is that it is a view only kind of a control which just displays the values of these properties in the form of a TextBlock. Since there is no change propagation from view to the data context side, we are using OneWay mode for Binding.

Now we can add these controls to a Window. This window is using a DockPanel to display these controls docking the edit control on top and the view-only control on the bottom side. It is also adding a TextBlock to show banner. In case you haven't noticed, this is a Cool Student App. The view is also instantiating MainViewModel in-line and using it as the DataContext. The is passing the Student property from the DataCotext as the DataContext of both the user controls.

Now let's look at the definition of MainViewModel. As expected, it has a property, named Student.

Now let's see how we can add Student type. As expected by the two user controls, it has FirstName and LastName properties. The view model is implementing INotifyPropertyChanged to support change notifications.

Now let's run this cool application. The following view is shown on the screen. Change the FirstName and LastName. Notice that the same values appear in the view-only user control as well. This is all because of change propagation support in WPF through INotifyPropertyChanged implementation by the view model.

Let's add the following to StudentViewModel.cs. Here we want to maintain the number of students created into the Student type itself. We do this by introducing _numberOfStudents. In order to have ease in binidng, we are exposing a string based property NumberOfStudents which just returns the value of _numberOfStudents. We also have introduced a changed event for the property. We will be discussing this event later in this discussion.

Just for the example purposes, let's assume we have a timer which fakes the creation of students. This is done by just incrementing the _numberOfStudents counter. Since OnPropertyChanged() is an instance method, we cannot directly use it in the property setter for the counter property.

If we just run it like this there would be no updates in the view for the changes in the static property. This shows that PropertyChanged() doesn't support changed notification for static properties. You can verify this by using this code after updating the view as specified later in this discussion. This would show the view without any change notifications for the static property.

[NameOfProperty]Changed Event for Static Properties
And that is why we introduced NumberOfStudentsChanged. This would allow us to provide change notifications for the changes in the static property. Let's update the code like this. This is a new feature of .net 4.5. There are no worth-mentioning arguments for this event. The first argument is passed as null and the other as Empty. This is unlike PropertyChanged event where we need to pass Magic string. The magic string must be exactly same as the name of the property, otherwise, the property would have no change notification support. Here the name of event is enough. It has to be named as [NameOfProperty]Changed.

Now let's try showing the number of students in our view.

x:Static Markup Extension
In order to show the static members, the first choice which comes to our mind is the use of x:Static markup extension. In the snippet below we are using a TextBlock for this purpse. Here we are using x:Static extension to display the same.

Let's run the application now. It shows up as follows:

It's quite strange as the number of students count is not being updated. From the screenshot below, you can see that this is inspite of the value being updated.

Basically this is because x:Static doesn't support change propagation no matter how source property is defined. But now you should atleast realize why we introduced NumberOfStudents as string type. Basically the markup extension doesn't do the necessary value conversions compared to Binding markup extension. This is what msdn has to say about this:

Use caution when you make x:Static references that are not directly the type of a property's value. In the XAML processing sequence, provided values from a markup extension do not invoke additional value conversion.

Using Binding Markup Extension with Parenthesis in Property Path [Partial Qualification]
As we have seen above, x:Static supports displaying values of static properties but it doesn't support change notification. As we know Biniding resource extension supports specification of source using the simple DataContext or by specifying ElementName or Static / Dynamic resource extensions. But we should be having instance of the source object to bind to its properties. Does it support binding to a type's static members. Actually, it does but the syntax is a bit different. This is the same syntax used to bind to attached properties. It is to say that directly bind to whatever is specified in the Path property without worrying about the source. This can be called the Parenthesis syntax for binding. You can find further details about this on msdn. Here the source property can be an attached property or a static property.

Let's update the TextBlock used to display the NumberOfStudents from StudentViewModel as follows:

The designer gets a little confused as the source property is bound like an attached property but in actual it is not defined like one. You see the following issue in the designer window.

But the code does build fine and when you run the application you see the view as displayed below:

You can see the count being updated. This means this does support change notification. Here the change notification is supported by the NumberOfStudentsChanged event which is used by the Binding extension.

event EventHandler<PropertyChangedEventArgs>
Now our view models can be more complex. The might have more than a few properties defined. Adding an event for each of the property would be a real task. Yes, we have an alternative.

This is the second option provided in .net 4.5 for achieving the same result. This is more like our implementation of INotifyPropertyChanged where we added an OnPropertyChanged method. Why can't we add an interface like that for our static properties. The answer is, Because we can't... The interfaces are defined for instances to provide the details about the object's features i.e. what an object can do. Most certainly, we can define the method in one of the base classes used for view models. Now the child classes can use this for their static methods if it is marked as protected. No, since it doesn't make sense, a static member cannot be marked as virtual or abstract :)

Now we can use this in the same place in the constructor as follows:

Is Partial Qualification necessary for Binding
We don't need to use partial qualification. We can also bind these properties using the DataContext as follows:

Here the source property is used from the current DataContext.
Download Code:

Sunday, September 9, 2012

Code Camp @ SW Florida

It has been a great experience speaking @SW Florida Code Camp yesterday [08th Sep].

My session was about Portable Class Library Tools and their use in MVVM Design. As is general for code camps, we got a great chance to meet the like minded technology enthusiasts. As you know I have had a few posts about the same. So the session was just about the issues / solutions in these posts. You can find them here:
Code camp is a great opportunity to meet like minded technology enthusiasts, and SW Florida Code camp seemed to be no exception. You get amazed by talking to these individuals with their depth and breadth of technology knowledge. Their openness to learn / unlearn certainly deserves an appreciation.

Muhammad (myself), Scott Dorman, Shayne Boyer

Muhammad (myself) & Jay Hill

Muhammad (myself) & Patrick Roeper