Dynamic External Property Dependencies

Declarative Usage

As shown in External Property Dependencies, the declarative PDFx API allows you to register a dependency on a property that resides in any INotifyPropertyChanged-instance different from the owner of the dependent Property.

If the owner of the source property can be swapped out at runtime (or start off as null), you can instruct PDFx to listen for changes of the owner object:

class SourceClass : INotifyPropertyChanged
{
	private AnyType _sourceProperty;
	public AnyType SourceProperty
	{
		get { return _sourceProperty; }
		set
		{
			_sourceProperty = value;
			OnPropertyChanged("SourceProperty");
		}
	}
}

class DestinationClass : BindableExt
{
	private SourceClass _dynamicSource;
	private SourceClass DynSource
	{
		get { return _dynamicSource; }
		set
		{
			_dynamicSource = value;
			NotifyPropertyChanged(() => DynSource);
		}
	}

	public AnyOtherType TargetProperty
	{
		get
		{
			Property(() => TargetProperty)
		            .Depends(p => p.On(() => DynSource, k => k.SourceProperty)); 
                        //Note that the first parameter of the On method is a delegate

			//SourceProperty has changed. Do Something with it and return.
		}
	}

	public void ChangeSource()
	{
		DynSource = new SourceClass();
	}
}

Overloads of the methods On and AndOn both allow you to pass in an INotifyPropertyChanged instance as the first parameter and point to any property of that instance in the Lambda Expression you pass in as the second parameter.
To support hot swapping of the INotifyPropertyChanged instance, you pass in a delegate to the On and AndOn overloads, which points to the Property that contains the Source Property owner.

Example

The source code of this example can be found in ViewModel DynamicExternalDependencyVM which is part of the WPFSample's source code.

Let's assume we are required to implement the following graph:

DynamicExternalPropertyDependenciesI.png

By clicking the "Use External Source"-buttons, the user can change the source "External Source" that ultimately feeds into the Destination object:

DynamicExternalPropertyDependenciesII.png

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 represent the depicted graph in C#:

public class DynamicExternalDependencyVM : BindableExt
{
	public DynamicExternalDependencyVM()
	{
		ExternalSource1 = new ExternalSource();
		ExternalSource2 = new ExternalSource();
		Destination = new DestinationVM() { ExternalSource = ExternalSource1 };
	}

	public DestinationVM Destination { get; set; }
	public ExternalSource ExternalSource1 { get; set; }
	public ExternalSource ExternalSource2 { get; set; }

	private DelegateCommand _useExternalSource1Command;
	public DelegateCommand UseExternalSource1Command
	{
		get
		{
			return
			_useExternalSource1Command = _useExternalSource1Command ?? 
			new DelegateCommand(
			() => Destination.ExternalSource = ExternalSource1);
			//Hotswap ExternalSource
		}
	}

	private DelegateCommand _useExternalSource2Command;
	public DelegateCommand UseExternalSource2Command
	{
		get
		{
			return
			_useExternalSource2Command = _useExternalSource2Command ?? 
			new DelegateCommand(
			() => Destination.ExternalSource = ExternalSource2);
			//Hotswap ExternalSource
		}
	}

	public class DestinationVM : BindableExt
	{
		public int A1
		{
			get
			{
				Property(() => A1)
					.Depends(p => p.On(() => B1)
						.AndOn(() => ExternalSource, k => k.A1));
				//Tell the PDFx that ExternalSource might get hotswapped

				return B1 + ExternalSource.A1;
			}
		}

		private ExternalSource _externalSource;
		public ExternalSource ExternalSource
		{
			get { return _externalSource; }
			set
			{
				_externalSource = value;
				NotifyPropertyChanged(() => ExternalSource);
			}
		}

		private int _b1;
		public int B1
		{
			get { return _b1; }
			set
			{
				_b1 = value;
				NotifyPropertyChanged(() => B1);
			}
		}
	}

	public class ExternalSource : BindableExt
	{
		public int A1
		{
			get
			{
				Property(() => A1)
					.Depends(p => p.On(() => B1));

				return 3 * B1;
			}
		}

		private int _b1;
		public int B1
		{
			get { return _b1; }
			set
			{
				_b1 = value;
				NotifyPropertyChanged(() => B1);
			}
		}
	}
}

Last edited May 10, 2013 at 6:36 PM by KevinStumpf, version 14

Comments

No comments yet.