The PDFx is a lightweight open source .NET library that allows developers to describe dependencies between Properties in declarative C# code. Once relationships are registered, the framework monitors property changes and ensures that the INotifyPropertyChanged.PropertyChanged event is fired for all directly and indirectly dependent properties in a very efficient way. The library is available for WPF, Silverlight, WinRT (Windows Store) and Windows Phone.
I’ve developed the PDFx as an InterKnowlogy RECESS project and published the source code and examples on codeplex.
In a series of blog posts I am going to cover the library’s most important features:
- Part I: Introduction
- Part II: Library Versions
- Part III: Getting Started
- Part IV: Using PDFx with an existing 3rd party framework
- Part V: Simple Property Dependencies
- Part VI: External Property Dependencies
- Part VII: Dynamic External Property Dependencies
- Part VIII: Collection Dependencies
- Part IX: Dynamic Collection Dependencies
- Part X: Caching
- Part XI: Smart Property Changed Notification
- Part XII: Callbacks
- Part XIII: Sanity Checks
- Part XIV: Data Delegation
- Part XV: Two Way Converters
- Part XVI: One Way Converters
Using PDFx with MVVM Light
Full Disclosure: The implementation presented in this post is experiential. While it passes the PDFx’s Unit Tests successfully, it has not undergone several months of stress tests in IK’s production environments (in contrast to the PDFx itself) because we’re using our own in house ViewModel base class and are consequently able to derive from BindableExt.
In Getting Started you’ve learned what steps you have to take in order to use the PDFx in your own project. As it was explained, every class that wants to leverage PDFx’s features needs to ultimately derive from PDFx’s Bindable or BindableExt because all the functionality is exposed through protected methods.
In certain scenarios, however, the ViewModel Base class that you’re using throughout the project might live in a 3rd party assembly and you might consequently not have the option to modify its source code to include the PDFx.
In order to still support those scenarios, I’ve extended the PDFx’s base classes to expose their functionality not only through protected methods but also through explicitly implemented interfaces. This allows you to use the PDFx in your project by implementing an intermediate man-in-the-middle ViewModel class that bridges the gap between your ViewModel base class and the PDFx. The following steps are necessary to implement such an intermediate ViewModel (You can skip the following steps and immediately head to the next section of this post if you would like to reuse my implementation):
Let’s assume every ViewModel in your project derives from ViewModelBase that is exposed by a 3rd party library.
- Create a new class MyViewModel and derive it from ViewModelBase.
- Change every reference in your project from ViewModelBase to MyViewModel.
- Create a nested BindableExt or Bindable instance inside of MyViewModel (See Library Versions to find out which one suits your needs best)
- If you use Bindable, create delegating methods within MyViewModel for every method the Bindable instance exposes through its explicitly implemented interface IBindableAccessToProtectedFunctionality. Omit the “Tunnelled” prefixes.
- If you use BindableExt, create delegating methods within MyViewModel for every method the BindableExt instance exposes through its explicitly implemented interface IBindableExtAccessToProtectedFunctionality. Omit the “Tunnelled” prefixes.
- Intercept every method call to ViewModelBase which ultimately results in raising the PropertyChange event and forward it instead to the Bindable instance’s TunnelledNotifyPropertyChanged method.
- Forward every PropertyChanged event that the Bindable instance raises to ViewModelBase’s PropertyChanged event.
- Implement the IDependencyFrameworkNotifyPropertyChangedInTransaction interface in MyViewModel
- Forward the interface’s FirePropertyChanged method to the Bindable Instance’s, which also implements the IDependencyFrameworkNotifyPropertyChangedInTransaction interface.
- Forward every PropertyChangedInTransaction event that is raised by the Bindable Instance to the PropertyChangedInTransaction event MyViewModel now exposes.
I’ve implemented such an intermediate ViewModel class for MVVMLight. You can find the full example here. In this scenario I’ve chosen to use PDFx’s BindableExt version (See Library Versions for more information).
How to use PDFx with a framework different from MVVM Light
In case you don’t use MVVM Light, you can still use the intermediate class i’ve implemented for MVVM Light as a starting point and follow a few simple steps to make it work with your framework:
- Get the intermediate class’s source code from here.
- Change the intermediate class’s base class from MVVMLight’s ViewModelBase to the ViewModel base class that comes with your framework.
- Change the intermediate class’s MVVM Light Specific region
- Override whatever method your base class uses to ultimately raise the PropertyChanged event and forward it to the PDFx’s TunnelledNotifyPropertyChanged method.
- Change the FirePropertyChanged method’s implementation to call your base class’s method which raises the PropertyChanged event. This should be the very same method you overwrote in the previous step.
If you want to make sure that you followed the steps correctly and that the PDFx is ready to use, I recommend running the MVVMLightExtension’s Unit Tests against your new intermediate ViewModel.