Archive for the ‘Uncategorized’ Category

Event Bindings outside of WPF

June 8, 2014

Event Bindings outside of WPF

Code Location

The code for this blog post can be downloaded from EventBindingTests.zip.

The solution file EventBindingTests.sln is located under EventBindingTests\TESTS\EventBindingTests
folder.

Introduction

Here I continue a series of blog posts about implementing WPF concepts outside of WPF.

In fact here, I am going to describe a concept/pattern that does not exist in WPF but, based on
my experience will be useful in WPF-esq universe – the Event Binding.

WPF creates various hierarchies of objects – there is a logical tree, there is a visual tree. When programming
MVVM there is also unspoken, but widely used hierarchy of the view models – e.g. a top level View Model might
contain some member representing another View Model or it might contain a collection of the view models representiong e.g. rows in a table or entries in a ListView.

Many time there should be an action from a sub-View Model to the one of its ‘anscestors’ in the View Model
hierarchy. This might happen, e.g. when a visual action is invoked on the sub-View Model but should result in
a change on its ‘anscestor’ level. The simplest example would be a remove button on each of the items within a list view. If implemented view the View Model patters, the remove button will have access only to the sub-View Model corresponding to individual item. However, the remove action should happen on the collection that contains the items’ View Models, i.e. a level higher. The way to implement it would be to create a ‘remove action’ event that fires at the item View Model level. When item becomes part of the collection in the higher level View Model – it adds a handler to the event that actually removes the item. The higher level View Model needs to manage adding and removing handlers to the items as they are added or removed to or from the collection or as the collection of items is getting totally overriden by a different collection.

The purpose of the Event Binding is precisely to make it easier to
manage the event handlers added at the ‘anscestor’ level to the ‘descendant’ item events.

Demonstration of what one can do with Event Binding

The main program is in Programs.cs file of EventBindingTests project. It demonstrates
binding an event handler to a single object or to a collection of objects.

Single Object Event Binding

Here is the single object event binding code (do not try to read to much into it since it is explained step by step below:

PopulatedOrganization wonkaFactory = new PopulatedOrganization();

Organization chocolateDepartment = new Organization();

#region SINGLE OBJECT EVENT BINDING

// create the event binding for single object
EventBinding<Organization, string> eventBinding =
    new EventBinding<Organization, string>();

// specify the source object and the path to the source binding property that contains the event
// we want to bind to
eventBinding.SourceObj = wonkaFactory;
eventBinding.SourcePathLinks =
     StringCodePathResolver.ResolveStringPath("TheMostImportantDepartment").ToList();

// do the binding itself
eventBinding.Bind();

// specify the event name (it can be done either before or after bind()
// method is called
eventBinding.EventName = "SomethingHappenedInOrgEvent";

// add the event hanlder whose signature is similar to that of 
// SomethingHappenedInOrgEvent event to the binding
eventBinding.TheEvent += eventBinding_SomethingHappenedInTheDepartment;

// nothing is printed to the console because wonkaFactory.TheMostImportantDepartment
// is still not set to chocolateDepartment object
chocolateDepartment.FireSomethingHappenedEvent("Augustus Gloop went to the chocolate creek. (Before the department added - should not show)" );

// set wonkaFactory.TheMostImportantDepartment 
wonkaFactory.TheMostImportantDepartment = chocolateDepartment;

// this message is printed on the console
chocolateDepartment.FireSomethingHappenedEvent("Augustus Gloop is out of the game (should show)");

// unbind the event
eventBinding.Unbind();

#endregion SINGLE OBJECT EVENT BINDING

Here is the description of what is going on in the code. Organization class
has a property TheMostImportantDepartment which is also of Organization type.
Organization also has an event SomethingHappenedInOrgEvent.
This event is of the type SomethingHappenedDelegate which is similar to
Action<string>. Method FireSomethingHappenedEvent(string message)
fires the event passing the message to it.

We want to bind the SomethingHappenedInOrgEvent on the TheMostImportantDepartment
property of the organization to a handler at the main program level. For this purpose we use the Event Binding:

// create the event binding for single object
EventBinding<Organization, string> eventBinding =
    new EventBinding<Organization, string>();

// specify the source object and the path to the source binding property that contains the event
// we want to bind to
eventBinding.SourceObj = wonkaFactory;
eventBinding.SourcePathLinks =
     StringCodePathResolver.ResolveStringPath("TheMostImportantDepartment").ToList();

// do the binding itself
eventBinding.Bind();

// specify the event name (it can be done either before or after bind()           
// method is called
eventBinding.EventName = "SomethingHappenedInOrgEvent";

The above code does the binding. Note that the binding is already there even though the
TheMostImportantDepartment property has not been set yet.

Now we add the event handler to the Event Binding
and not to the original event:

// add the event handler whose signature is similar to that of 
// SomethingHappenedInOrgEvent event to the binding
eventBinding.TheEvent += eventBinding_SomethingHappenedInTheDepartment;

This event handler will simply print the message argument from the event.

Now if we try to fire the event on the chocolateDepartment object – nothing should
change, because TheMostImportantDepartment property of the wonkaFactory
object is still not set to the chocolateFactory:

// nothing is printed to the console because wonkaFactory.TheMostImportantDepartment
// is still not set to chocolateDepartment object
chocolateDepartment.FireSomethingHappenedEvent("Augustus Gloop went to the chocolate creek. (Before the department added - should not show)" )

Now we set the property and fire an event again and the corresponding message should be printed on the console:

// this message is printed on the console
chocolateDepartment.FireSomethingHappenedEvent("Augustus Gloop is out of the game (should show)");

Note that the Event Binding takes full care of figuring out if
the property is null or not and making the event binding behave accordingly as long as the binding notification
is on (for simple properties – that means firing INotifyPropertyChanged.PropertyChanged
event when the TheMostImportantDepartment property changes. Similar notifications
are available for AProperties or Attached/Dependency properties – but the
SourcePathLinks will have to reflect the corresponding PropertyKind.

Note also that the even though we considered a path containing only one path link – we can
use arbitraty path links of arbitrary length for Event Bindings
as long as each link provides binding notifications.

Collection Event Binding

Collection Event Binding provides even more dramatic refactoring.
Not only it takes case of collection being reset, but also if the collection implmements
INotifyCollectionChanged interface (i.e. ObservableCollection,
it adds or removes proper handlers when the items of the
collection are added or removed correspondingly.

An organization has AllDepartments property of type
ObservableCollection<Organization>. We want to set the collection, add a couple of departments
to it use Event Binding to bind the SomethingHappenedInOrgEvent
on the collection objects to our event handler. Here is the corresponding code:

#region COLLECTION EVENT BINDING

// create the collection AllDepartments
wonkaFactory.AllDepartments = new ObservableCollection();

// add chocolate department to it
wonkaFactory.AllDepartments.Add(chocolateDepartment);

// create collection event binding
CollectionEventBinding<Organization, string> collectionEventBinding =
    new CollectionEventBinding<Organization, string>();

// set the objects that contain the event we want to bind to 
// to be "AllDepartments" collection property of "wonkaFactory" object 
collectionEventBinding.SourceObj = wonkaFactory;
collectionEventBinding.SourcePathLinks =
     StringCodePathResolver.ResolveStringPath("AllDepartments").ToList();

// bind the event
collectionEventBinding.Bind();

// set the event name (can be done before or after the binding)
collectionEventBinding.EventName = "SomethingHappenedInOrgEvent";

// add event handler
collectionEventBinding.TheEvent += collectionEventBinding_TheEvent;

// create gumDepartment
Organization gumDepartment = new Organization();

// fire an event (should not be handled since gumDepartment is not part of the collection yet)
gumDepartment.FireSomethingHappenedEvent("We had great sales (Before the department is added - should not show)");

// Add gum department to the collection
wonkaFactory.AllDepartments.Add(gumDepartment);

// fire the event (should be handled, since now gumDepartment is part of the collection)
gumDepartment.FireSomethingHappenedEvent("We had great sales (After the department is added - should show)");

// remove gum department from All Department collection
// collectionEventBinding should be sufficiently smart to disconnect 
// the event of gumDepartment object from the handler
wonkaFactory.AllDepartments.Remove(gumDepartment);

// fire the event again - (the handler should not run, since gumDepartment has been removed from the collection)
gumDepartment.FireSomethingHappenedEvent("We had great sales (After the department is Removed - should not show)");

#endregion COLLECTION EVENT BINDING  

The binding code is sufficiently similar to the case of a single object so that we do go
over each step again in detail. I’d like to re-iterate, however, that the CollectionEventBinding
will manage the event handlers on each of the members of the collection both in case the whole collection
is re-assigned (if all the path links to the collection have binding notifications)
or in case elements are added or removed to or from it (if the collection implements
INotifyCollectionChanged interface).

Implementation Notes

The central class for both EventBinding and CollectionEventBinding implementation
is NP.Paradigms.EventBindingBase<ObjectType, EventObjectType>. It provided the actual binding
from the actual object in the hierarchy to the Event Binding‘s property
TheObj. This class has two generic parameters: ObjectType and EventObjectType.
ObjectType is the type of the object that we bind to – in case of a single event binding – it is the
same as the type of the object that contains the event (EventObjectType), while in case of a collection
event binding it is a collection of objects of type EventObjectType.

This class contains two important abstract methods
Disconnect() and Reconnect() that control removing or setting the event handler
on the corresponding object(s). These methods are overriden in concrete implementation of EventBinding
and CollectionEventBinding functionality.

This class defines also the name of the method that will be attached to the bound object(s) events: "EventHadler".
This method is also defined in the sub-classes.

The reflection based actual implementation of adding and removing the handlers to the object is located
within NP.Paradigms.EventManager class.

Class SingleObjectEventBindingBase is derived from EventBindingBase it overrides
Disconnect() and Reconnect() methods to act on a single object.

A number of EventBinding classes with various generic parameters specifying different possible
arguments to the event is derived from SingleObjectEventBindingBase class.

CollectionEventBindingBase class is also derived from EventBindingBase by overriding the same
functions Disconnect() and Reconnect() and specifying some handling when items are added or removed
to or from the collection.

A number of CollectionEventBinding classes with various generic parameters is also derived
from CollectionEventBindingBase class.

Conclusion

In this blog post I describe a new concept of Event Binding which is not part
of WPF but should come handy for programming using WPF related concepts (whether it used in WPF or outside of WPF).

 

Advertisements

Composite Path Bindings outside of WPF

June 27, 2013

Composite Path Bindings outside of WPF

Introduction

In AProperties and Bindings outside of WPF Revisited I presented implementation of binding concepts using IPropGetter and IPropSetter interfaces. This implementation allowed binding a source property on a source object to a target property on a target object. Both plain properties and AProperties could be used as source and target.

The binding dicussed at the link above, has a limitation, though, in that it only deals with immediate properties of the source or the target. You cannot bind to a property with a complex path to it. This blog entry aims to resolve this problem. Not only it will provide the functionality for binding using a complex path to the source property (something the WPF binding functionality also allows), but it will show how to use a complex path at the target side as well (something that WPF does not permit).

When dealing with complex path to the source property, there is always a posibility that the such path simply does not exist. In that case the binding can provide a default value to the target property. This default value is similar to WPF binding’s FallbackValue property.

The source code for the article is located under CompositePathTests.zip file.

Sample that Uses Composite Path Bindings

The main project is CompositePathToTargetTest. Most of the sample code is located within Program.cs file.

Both source and target object of this sample are of ParentDataClass type. ParentDataClass has a property TheData of type DataClass. DataClass in turn has a property MyStringProp of type string. The sample shows how to bind MyStringProp property of the TheData property of the source object to the same path within the target object.

The class that was called BindingPath in the previous articles is renamed to BindingPathLink. This class chooses correct property “getter” and “setter” for the binding. The composite paths consist of a collection of the BindingPathLink objects. Here is how such collection is created for the source object:

CompositePathGetter sourcePathGetter =
    new CompositePathGetter
    (
        new BindingPathLink<object>[]
        {
            new BindingPathLink<object>("TheData"),
            new BindingPathLink<object>("MyStringProp"),
        },
        "A Default String"
    );

CompositePathGetter requires a collection of path links and a default value that will be sent to the target if the path to the source does not exist (remember it is similar to the FallbackValue of the WPF binding).

The setter for the binding’s target is created in a similar way:

CompositePathSetter targetPathSetter = new CompositePathSetter
    (
        new BindingPathLink<object>[]
        {
            new BindingPathLink<object>("TheData"),
            new BindingPathLink<object>("MyStringProp")
        }
    );

only here we do not need to pass the default value parameter.

Then we set the source and target objects of the source getter and target setter:

 sourcePathGetter.TheObj = sourceDataObj;
 targetPathSetter.TheObj = targetDataObject;

We set the corresponding getter and setter properties of the binding:

binding.SourcePropertyGetter = sourcePathGetter;
binding.TargetPropertySetter = targetPathSetter;

Then after we call function Bind() on the binding object, the binding becomes operational and the source value is set on the target: calling Console.WriteLine(targetDataObject.TheData.MyStringProp); will print “Hello World”.

Then if we change the source property: sourceDataObj.TheData.MyStringProp = "Hi World"; the target property will also change to “Hi World”. If we change the TheData property of the source object, the target will also reflect the change:

 sourceDataObj.TheData = new DataClass { MyStringProp = "bye bye" };

will set the target property to “bye bye”.

If TheData property of sourceDataObj is set to null, the default binding value “A Default String” will be set to the target property.

If TheData property of the targetDataObj is set to null, the old binding value is retained and will be set to the MyStringProp property of the new TheData object, if at some point it becomes non-null.

Notes on Implementation

Instead of IPropGetter<PropertyType> and IPropSetter<PropertyType> interfaces, used in the previous articles for implmenting the binding’s getter and setter, we use IObjWithPropGetter<PropertyType> and IObjWithPropSetter<PropertyType> interfaces that also allow setting the object for which the properties are read or set. This is done in order not to recreate the getter and setters every time the path’s objects are created or destroyed.

CompositeClassGetter represents a chain of IObjWithPropGetter<PropertyType> objects built from a list of BindingPathLink objects that represent the path to the source property from the source object. The PropertyChangedEvent of each IObjWithPropGetter is handled by setting the corresponding object for the next property getter. The handler for the last object is set to call the PropertyChangeEvent on the CompositeClassGetter object:

IObjWithPropGetter<object> previousPropGetter = null;
foreach (var pathLink in _pathLinks)
{
    IObjWithPropGetter<object> propGetter = pathLink.GetPropertyGetter();

    _propGetters.Add(propGetter);

    if (previousPropGetter != null)
    {
        previousPropGetter.PropertyChangedEvent += (obj) =>
            {
                propGetter.TheObj = obj;
            };
    }

    previousPropGetter = propGetter;
}

previousPropGetter.PropertyChangedEvent += (obj) =>
    {
        if (this.PropertyChangedEvent == null)
            return;

        if (!LastPropGetter.HasObj)
        {
            PropertyChangedEvent(_defaultValue);
        }
        else
        {
            PropertyChangedEvent(obj);
        }
    };

CompositePathSetter consists of IObjWithPropSetter object corresponding to the last link of the target property path and a chain of IObjWithPropertyGetter objects corresponding to the rest of the links. The PropertyChangedEvent of each of the property getters sets the object on the next property getter (or setter):

IObjWithPropGetter<object> previousPropGetter = null;
foreach (var propGetter in _propGetters)
{
    if (previousPropGetter != null)
    {
        previousPropGetter.PropertyChangedEvent += (obj) =>
        {
            propGetter.TheObj = obj;
        };
    }

    previousPropGetter = propGetter;
}

// set the last property getter to the set the setter
previousPropGetter.PropertyChangedEvent += (obj) =>
{
    _theSetter.TheObj = obj;
};

Attached Properties outside of WPF

April 29, 2013

Here I continue talking about re-implementing and improving WPF concepts outside of WPF and in a way that is not necessarily connected to GUI development. The first article in the series was discussing implementation of property and collection bindings outside of WPF and is available at Binding without WPF or at Codeproject: Binding without WPF. The final goal of these series is to implement most of the concepts that WPF introduced outside of WPF without dependency on any MS visual libraries and, perhaps, even in different languages, like JavaScript, Java and Objective-C.

This article discusses re-implementing WPF Attached Properties.

As a reminder – WPF Attached Properties serve the same purpose as the usual properties: they allow to get a property value from an object. They are, however, implemented very differently from the usual properties: instead of being part of the object, they are defined outside of it. If an Attached Property was set on an object, it can be retrieved from some memory store outside of the object with the object serving as a key. If an Attached Property was never defined on an object, the Attached Property’s default value will be returned. This value is defined per Attached Property and will be the same for any object.

WPF’s Attached Properties provide a number of very useful features:

  1. Attached Properties were used in WPF to reduce the storage required for all the numerious
    WPF properties. Indeed, if an object uses default Attached Property value, it does not
    require any additional storage. This type of storing property values
    is called sparse storage.
  2. WPF Attached Properties virtually allow adding new data to an object
    without modifying the object’s type.
  3. WPF Attached Properties allow setting callbacks that fire when a property
    changes on an object.
  4. In WPF only Attached (and Dependency) Properties can be a binding’s target.
    (Dependency Properties are very similar to the AttachedProperties but can
    only be defined within the type to which they can be attached).
  5. Attached Properties propagate down the visual tree.
  6. WPF’s built-in animation framework can only animate Attached and Dependency Properties.

Here we show how to build a framework providing capabilities very similar to the WPF Attached Properties. In order to differentiate between the WPF Attached Properties and this framework’s properties I call them AProperties or AProps. Here are the AProps capabilties that match those of the Attached Properties:

  1. AProps provide sparse storage.
  2. AProps allow to add external data to the objects without changing
    the objects’ type or class.
  3. AProps allow to add a callback to be fired when a value changes on an object.

On top of the features above that are also available for the WPF attached properties it will also provide the following nice features:

  1. AProps can be attached to a C# entity of any type, not only to those descended from DependencyObject.
  2. Unlike WPF Attached Properties, the mechanism of operating with AProps is strongly typed.
  3. In WPF one can specify an Attached Propertie’s callback when it is created or registered. This callback fires after an object’s property changes and it is the same for any object that has the Attached Property. AProps allow to specify also a callback to be fired before a property is changed on an object. If this callback returns false, the property changed is cancelled. Moreover, the framework allows adding callback to the individual objects. This callbacks are fired on when the AProperty is changed on the object to which the callback was added. Other objects are not affected by the callback.
  4. Unlike Attached Properties, AProps do not have to be defined as static variables (even though they can be defined static).

Now I would like to list the functionality that the Attached Properties have, but AProps (at this point yet) do not.

  1. The binding framework from the previous article is not made to bind to or from AProps. Even though this functionality is coming soon.
  2. Attached Properties change the property value within UI thread, while the AProps change in the thread of the caller. Perhaps, at some point, I’ll add another degree of freedom to the AProps that would allow to specify property change thread.
  3. There is no (yet) visual framework built around AProps, so there is no propagation down the visual tree or animation classes that use AProps.
  4. There is no value coercion mechanism for AProps (which anyways not used very frequently in WPF).

The AProps code together with the test project that shows how to use them is can be downloade from APropsCode.zip.

The main (virtually the only) class for dealing with AProps is AProperty under NP.AProps project.
It provides a functionality for creating AProperty object. AProperty contains a Dictionary (map) that maps the objects to their property values, or rather to some entities that contain their corresponding property values. If the object does not exist in the Dictionary, the default value gets returns as its AProperty value.

The central public methods of AProperty class are the following:


  1. public PropertyType GetProperty(ObjectType obj)

    Given an object returns its AProperty value.

  2. public void SetProperty(ObjectType obj, PropertyType newPropertyValue)

    Sets AProperty value on the passed object.
  3. public void AddOnPropertyChangedHandler
    (
        ObjectType obj, 
        OnPropertyChangedDelegate propChangedHandler
    )

    Adds object’s individual property change handler (other objects won’t be affected by it).

  4. public void RemoveOnPropertyChangedHandler
    (
        ObjectType obj,
        OnPropertyChangedDelegate propChangedHandler
    )

    Removes object’s individual property change handler.


  5. public void ClearAProperty(ObjectType obj)

    Clears AProperty value from the object (essentially removes the object from the AProperty‘s Dictionary.

The constructor of AProperty class has the following signature:

public AProperty
(
    PropertyType defaultValue = default(PropertyType),
    Func beforePropertyChangedFn = null, 
    OnPropertyChangedDelegate  onPropertyChangedFn = null
)

As you can see, it allows to pass the default value of the AProperty and two delegates: beforePropertyChangedFn and onPropertyChangedFn. The first of the delegates executes before AProperty changes on some object. If it returns false the property change is cancelled. The second delegate executes after the property change. Unlike individual object property change handlers these delegates execute for any object whose corresponding AProperty changes. The provided API does not allow modifying these delegate once they were set; otherwise all the objects that had their corresponding AProperty set might be affected. The OnPropertyChangedFn delegate is similar to OnPropertyChanged delegate that can be passed to the Attached Property’s metadata as the second argument.

The code that shows how to use AProperty API is under APropertyTest project. MyTestClass is a class with one property Name of type string. We want to add some integer index to MyTestClass object by using AProperty functionality.

Here is how we create indexAProperty object:

AProperty<MyTestClass, int> indexAProperty = new AProperty
(
    -1, // default indexAProperty value
    null, // no function is called before the property is set.
    (obj, oldVal, newVal) =>// to be called after the property is set
    {
        Console.WriteLine("This is a generic (not individual) property change event handler, oldValue: {0}, newValue: {1}", oldVal, newVal);
    } 
);

We set the default value for indexAProperty to -1, the generic delegate to fire before the property change is not set (null), and the generic post-property-change delegate prints a message with old and new value.

After that, we create a list of MyTestClass object and populate it with 3 objects. The indexAProperty for those 3 objects is set from is set to 1, 2 and 3 correspondingly. The object with index 2 is assigned an individual property change event handler:

// list to populate with objects
List myTestObjList = new List();

for (int i = 1; i < 4; i++)
{
    // create the object
    MyTestClass myTestObj = new MyTestClass { Name = "Obj " + i };

    // set an individual property change event handler for the second object
    if (i == 2)
    {
        indexAProperty.AddOnPropertyChangedHandler
        (
            myTestObj,
            (obj, oldVal, newVal) => // individual object delegate
            { 
                Console.WriteLine("This is individual property change event handler, oldValue: {0}, newValue: {1}", oldVal, newVal); 
            }
        );
    }

    // add an object to the list
    myTestObjList.Add(myTestObj);

    // set the indexAProperty on the myTestObj object to i
    indexAProperty.SetProperty(myTestObj, i);
}

Finally we iterate through the list of objects an print the indexAProperty value for each of the objects:

// print indexAProperty values for every object in the list
foreach (MyTestClass myTestObj in myTestObjList)
{
    int objNumber = indexAProperty.GetProperty(myTestObj);

    Console.WriteLine(objNumber);
}

Restarting the blog.

March 15, 2013

Hi All,

This blog has been dead for a while and I was posting technical articles mainly on codeproject.com.

I plan to restart this blog posting programming tit-bits and software-related ideas on it while still publishing longer articles on codeproject.com.

New articles on Silverlight and Prism

February 21, 2011

It has been a while and I kind of neglected the blog, but I did publish a bunch of new articles on code project:

Prism for Silverlight/MEF in Easy Samples. Part 1 – Prism Modules

Prism for Silverlight/MEF in Easy Samples. Part 2 – Prism Navigation

Prism for Silverlight/MEF in Easy Samples. Part 3 – Communication between the Modules

Silverlight Animations along Arbitrary Mathematical Paths via Easing

Parameter Substitution within Expression Trees

Why I started this blog

September 19, 2008

I have a lot of thoughts, sketches and projects that I would like to share with the world.