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
Dynamic Collection Dependencies
Declarative Usage
As described in Collection Dependencies, the PDFx allows you to register dependencies not only on single objects’s properties, but also on ObservableCollections’ children’s properties.
If the Collection is hotswappable, you can instruct the PDFx to listen for replacements of the entire collection instance:
class Demonstration : BindableExt { DependencyFrameworkObservableCollection<ChildClass> _children = new DependencyFrameworkObservableCollection<ChildClass>(); public DependencyFrameworkObservableCollection<ChildClass> Children { get { return _children; } set { _children = value; NotifyPropertyChanged(() => Children); } } public AnyType CombinationOfAllChildren { get { Property(() => CombinationOfAllChildren) .Depends(p => p.OnCollectionChildProperty(() => Children, k => k.ChildProperty)); //Note how a delegate points to the Collections' property, //thereby allowing the collection to be swapped out. //Do something with all children and return } } public void ReplaceChildren() { Children = new DependencyFrameworkObservableCollection<ChildClass>(); } class ChildClass : INotifyPropertyChanged { private AnyType _childProperty; public AnyType ChildProperty { get { return _childProperty; } set { _childProperty = value; OnPropertyChanged("ChildProperty"); } } } }
Overloads of the methods OnCollectionChildProperty and AndOnCollectionChildProperty both allow you to pass in a DependencyFrameworkObservableCollection instance as the first parameter and point to any property of that collection’s children in the Lambda Expression you pass in as the second parameter.
To support hot swapping of the Collection’s instance, you pass a delegate to the OnCollectionChildProperty and AndOnCollectionChildProperty overloads, which points to the Property that contains the Collection.
Example
The source code of this example can be found in ViewModel DynamicCollectionDependencyVM which is part of the WPFSample’s source code.
Let’s assume we are required to implement the following system:
By clicking the “Click here to use Children”-buttons, the user can change the source collection that ultimately feeds into the Destination object:
Green circles stand for Input Properties while purple circles indicate calculated properties. The arrows show the underlying math operations as well as the property dependencies.
Using the PDFx, we can easily implement the depicted system:
class DestinationVM : BindableExt { public DestinationVM() { Children1 = new DependencyFrameworkObservableCollection<ChildVM>(); Children2 = new DependencyFrameworkObservableCollection<ChildVM>(); Children = Children1; Children1.Add(new ChildVM(Children1)); Children1.Add(new ChildVM(Children1)); Children1.Add(new ChildVM(Children1)); Children2.Add(new ChildVM(Children2) { B1 = 2 }); Children2.Add(new ChildVM(Children2) { B1 = 2 }); Children2.Add(new ChildVM(Children2) { B1 = 2 }); } private DependencyFrameworkObservableCollection<ChildVM> _children = new DependencyFrameworkObservableCollection<ChildVM>(); public DependencyFrameworkObservableCollection<ChildVM> Children { get { return _children; } set { _children = value; NotifyPropertyChanged(() => Children); } } public DependencyFrameworkObservableCollection<ChildVM> Children1 { get; set; } public DependencyFrameworkObservableCollection<ChildVM> Children2 { get; set; } public DelegateCommand AddToChildren1Command { get { return new DelegateCommand(() => Children1.Add(new ChildVM(Children1))); } } public DelegateCommand AddToChildren2Command { get { return new DelegateCommand(() => Children2.Add(new ChildVM(Children2))); } } public DelegateCommand UseLeftCommand { get { return new DelegateCommand(() => Children = Children1); } } public DelegateCommand UseRightCommand { get { return new DelegateCommand(() => Children = Children2); } } public int A1 { get { Property(() => A1) .Depends(p => p.On(() => B1).AndOn(() => B2)); return B1 + B2; } } public int B1 { get { Property(() => B1) .Depends(p => p.OnCollectionChildProperty(() => Children, k => k.A1)); //Note how a delegate points to the Collections' property, //thereby allowing the collection to be swapped out. if (Children.Count == 0) return 0; return Children.Select(k => k.A1).Sum(); } } private int _b2; public int B2 { get { return _b2; } set { _b2 = value; NotifyPropertyChanged(() => B2); } } class ChildVM : BindableExt { private DependencyFrameworkObservableCollection<ChildVM> _children; public ChildVM(DependencyFrameworkObservableCollection<ChildVM> children) { _children = children; } private int _b1 = 1; public int B1 { get { return _b1; } set { _b1 = value; NotifyPropertyChanged(() => B1); } } public int A1 { get { Property(() => A1) .Depends(p => p.On(() => B1)); return B1 * 3; } } public DelegateCommand RemoveCommand { get { return new DelegateCommand(() => _children.Remove(this)); } } } }
Pingback: PDFx – Property Dependency Framework – Part I, Introduction | //InterKnowlogy/ Blogs
Pingback: PDFx – Property Dependency Framework – Part V, Simple Property Dependencies | //InterKnowlogy/ Blogs
Pingback: PDFx – Property Dependency Framework – Part VI, External Property Dependencies | //InterKnowlogy/ Blogs