Archive for the ‘WPF’ Category

Data Templates Implementation Outside of WPF

May 28, 2014

Data Templates Implementation Outside of WPF

Code Location

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

Introduction

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

WPF is built around a hierarchy of visual objects the so called
Visual Tree. Any WPF control can provide an example of such hierarchy –
e.g. a WPF window might contain a grid panel which in turn contains
a number of visual objects e.g. buttons and list boxes which in turn contain
some text etc.

The object hierarchy is usually built in XAML with the help of numerous
techniques such as bindings, Control Templates and Data Templates.
Data Templates with the help of bindings
allow to translate some non-visual objects into visual objects with the
hierarchy defined by XAML. These resulting visual objects usually mimic the behaviors of the original non-visual objects – e.g. Changing a property on a
non-visual object would result in the corresponding visual property change,
adding or removing an object to or from an observable collection would result
in a corresponding item being added or removed from e.g. a ListView.

This blog entry will show how to use concepts similar to WPF Data Templates
outside of WPF and apply them for creating in XAML purely non-visual objects.

I’d like to stipulate that the utility of the concepts introduced
here might not be quite obvious yet. The usage of non-visual data templates
will be explained in the future blog posts.

Also I would like to express gratitude to the WPF re-implementation attempt
called Avalonia. It would have taken me much longer to understand the inner workings of XAML
functionality without this project and also I am using a modified version of several of its classes: AvalonXamlReader, ContentLoader and TemplateContent in order to create the
non-visual Data Templates.

Data Hierarchy Code Description

Data Hierarchy

First of all let me describe the non-visual hierarchy that we
want to build.

The WPF’s visual hierarchy is based on the natural containment of visual objects. As was stated above a window might contain a panel – a panel further might contain other panels and controls etc.

The non-visual hierarchy that we deal with is Property Map and the classes
that represent that hierarchy are contained under NP.Paradigms.DataHierarchy project. In a sense it mimics the data hierarchy within JSON code: there are Fields, Property Maps, and Collections.

A Field would only contain a value of type object.

A Property Map corresponds to a C# object –
it has a number of named properties each has a value. The values can be plain Fields, other Property Maps or Collections. The name of a property is unique within the map object. I implemented such maps as a Dictionary with string keys
corresponding to the name of the property and values – the property value. In JSON such object would be shown within curly brackets:


{
name1 : value1,
name2 : value2
}

Collection is a collection of objects (usually of similar structure) that can be either Property Maps or Fields. In JSON collections are denoted by square brackets:


[
value1,
value2
]

Clearly our Data Hierarchy can be used to represent a very wide range of models – in particular anything that can be represented by JSON or C# classes and collections can be represented by the Data Hierarchy.

Classes Describing the Data Hierarchy

As was mentioned above all the classes describing our Data Hierarchy model are locate under NP.Paradigms.DataHierarchy project.

All the Data Hierarchy classes implement IPresentationTreeNode interface. This interface has Parent property that points from the current object to its parent within the Data Hierarchy. IPresentationTreeNode also extends IDataContextContainer interface that defines DataContext property that all the members of the hierarchy should implement. Just like in WPF, the DataContext property contains the data object from which the member of the hierarchy gets its values via binding.

There is also IPresentationTreeNodeWithChildren<T> interface that extends IDataContextContainer and in addition also defines a collection Children.

FieldPresenter class corresponds to a single value Data Hierarchy node. Its property TheValue contains the corresponding value. Its subclass TextFieldPresenter also allows formatting the values for text presentation.

CollectionPresenter defines a collection within Data Hierarchy by its property Children.

PropertyMapPresenter represents the Property Map nodes within Data Hierarchy. It implements IDictionary so that one can use the indexer notations (square brackets) to define the name-value mappings, e.g:
myMap["Name"] = value

Note that classes that implement Data Hierarchy nodes fire PropertyChanged events when their properties change. Also Children property of the CollectionPresenter is implemented as ObservableCollection and correspondingly fired CollectionChanged event when the items are changed within the collection (removed, added or moved). This is necessary so that the bindings that have the Data Hierarchy nodes as source would work.

Classes for XAML Composition using Data Templates

Classes used for XAML composition are also defined under NP.Paradigms.DataHierarchy project.

DHierarchyContentControl and DHierarchyItemsControl correspond to the WPF’s ContentControl and ItemsControl classes.

DHierarchyContentControl defines properties Content and ContentTemplate.
ContentTemplate defines the sub-hierarchy of the node while Content property allows to switch the data context of its sub-nodes.

DHierarchyItemsControl defines properties ItemsSource and ItemTemplate. ItemsSource should be bound to a collection of objects. ItemTemplate specified the structure of each of the sub-nodes within DHierarchyItemsControl‘s Children collection. The resulting Children collection behaves similar to the ItemsSource collection if an item is added or removed from ItemsSource the corresponding item will be added or removed from the Children collection.

There is a number of classes for reading and processing XAML data templates. Class DHierarchyDataTemplate is used for storing the Data Hierarchy data templates within DHierarchyContentControl and DHierarchyItemsControl. DHierarchyTemplateContent together with DHierarchyContentLoader and AvalonXamlReader control loading the data templates from XAML.

Usage Code Description

Here we describe how the Data Hierarchy code with data template capabilities can be used.

The mock up data is contained under MockUpObjects. Here we consider only two classes: Organization and Person. Both are very simple Organization contains its name and a collection of people. Person simply contains first and last name of the person.

The main project in NonVisualDataTemplates. It defines an organization as its resource:

  <MockUps:Organization x:Key="TheWonkaChocolateFactoryOrganization" />

Around the organization object it defines the Data Hierarchy data template. While on top of the Data Hierarchy data template it defines a visual representation (just in order to be able to see that it works).

Data Hierarchy representation is defined by the following templates:

<hierarchy:DHierarchyDataTemplate x:Key="EmployeeNonVisualDataTemplate">
    <hierarchy:PropertyMapPresenter>
        <hierarchy:FieldPresenter x:Key="FirstName" 
                                  TheValue="{winparadigms:Bind SourcePath=FirstName, 
                                                               SourceMode=DataContext}"/>
        <hierarchy:FieldPresenter x:Key="LastName" 
                                  TheValue="{winparadigms:Bind SourcePath=LastName, 
                                                               SourceMode=DataContext}"/>
    </hierarchy:PropertyMapPresenter>
</hierarchy:DHierarchyDataTemplate>

This template define the Data Hierarchy representation of a person (employee)

<hierarchy:DHierarchyDataTemplate x:Key="TheOrganizationTemplate">
    <hierarchy:PropertyMapPresenter>
        <hierarchy:FieldPresenter x:Key="OrgName" 
                                  TheValue="{winparadigms:Bind SourcePath=OrgName, 
                                                               SourceMode=DataContext}"/>
        <hierarchy:DHierarchyItemsControl x:Key="People"
                                          ItemsSource="{winparadigms:Bind SourcePath=People, 
                                                                          SourceMode=DataContext}"
                                          ItemTemplate="{StaticResource EmployeeNonVisualDataTemplate}"/>
    </hierarchy:PropertyMapPresenter>
</hierarchy:DHierarchyDataTemplate>

This template defines the whole organization with multiple employees.

DHierarchyContentControl ‘marries’ the organization template and the organization data:

<hierarchy:DHierarchyContentControl ContentTemplate="{StaticResource TheOrganizationTemplate}"
                                       Content="{StaticResource TheWonkaChocolateFactoryOrganization}"
                                       x:Key="TheDHierarchyContentControl"/>

In order to visualize the results, a plain visual WPF hierarchy is build around the
DHierarchyContentControl:

<Grid Grid.Row="0" 
      DataContext="{winparadigms:Bind Source={StaticResource TheDHierarchyContentControl}}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <TextBlock Text="{winparadigms:Bind SourcePath=Child.-OrgName-.TheValue, SourceMode=DataContext}"
               Margin="10,0,0,0"/>

    <Border Grid.Row="1"
        BorderBrush="Black"
        BorderThickness="2"
        Margin="5">
        <ItemsControl ItemsSource="{winparadigms:Bind SourcePath=Child.-People-.Children, SourceMode=DataContext}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{winparadigms:Bind SourcePath=Child.-FirstName-.TheValue, SourceMode=DataContext}" />
                        <TextBlock Text="{winparadigms:Bind SourcePath=Child.-LastName-.TheValue, SourceMode=DataContext}" 
                                   Grid.Column="1"
                                   Margin="20,0,0,0"/>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Border>
</Grid>

Note that we are using Bind markup extension instead of Binding. This extension has been described in some of the previous blog entries.

Also note that ‘-‘ character around a path link specifies that this path link is actually a key inside a Dictionary for the Bind markup extension. Also SourceMode=DataContext means
that we are binding to the DataContext property (by default Bind extension binds to
the object on which it is defined, not to its DataContext).

There are two buttons at the bottom of the application that allow to modify the original Organization object. The very simple for modifying the original Organization is located in MainWindow.xaml.cs code behind file. You can add an employee or you can replace its People collection with another collection. These changes will cause changes in Data Hierarchy representation and those in turn will cause the visual representation to change.

After running the application (and pressing a button to add an employee) you’ll see the following picture:

Non-WPF Data Template Test App

Conclusion

We’ve shown implementing XAML data templates for non-WPF (and even non-Visual) objects.

Advertisement

Attached and Routed Events outside of WPF

December 1, 2013

Code Location

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

Introduction

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

In Attached Properties outside of WPF I introduced
a notion of AProperty – attached property implementation
outside of WPF. Unlike WPF attached property,
such property can be attached to any object –
not only to DependencyObject.

Just like AProperty can be added to an object
without modifying the object’s code, we can come up with the
REvent concept
similar to WPF’s attached event in order add an event to an
object without modifying the object’s code.

In Tree Structures and Navigation we were talking
about navigating a Tree from
node to node. The REvents can also be propagating
from node to node on a tree in a manner similar to that of
WPF’s RoutedEvents propagating on a visual tree.

Attached and Routed Events in WPF

Each event has 4 important actions associated with it:

  1. Defining an event
  2. Adding handlers to an Event
  3. Removing handlers from an Event
  4. Raising or Firing an Event from an object

In WPF and Silverlight one can use Attached Events
events defined outside of an object in which they are being
raised. These Attached Events are
also called Routed Events for the
reason that we are going to explain shortly.

Here is how we define those 4 action above for attached WPF events.

  1. Unlike plain C# events, the Attached Events should
    be defined outside of an object in a static class:

    public static RoutedEvent MyEvent=EventManager.RegisterRoutedEvent(...)

    The Routed Event is associated with an object when it is being raised
    from it.

  2. In order to add a handler to a Routed Event to an object,
    the following code is employed:

            myObject.AddHandler(MyRoutedEvent, eventHandlerFunction, ...)
          

    The myObject should always be a FrameworkElement in order to be able to
    detect and handle an Routed Event.

  3. Removing a Routed Event is done in a similar fashion:

            myObject.RemoveHandler(MyRoutedEvent, eventHandlerFunction)
          
  4. We can raise a Routed Event on a FrameworkElement
    object by using its RaiseEvent method:

            myObject.RaiseEvent(routedEventArgs)
          

    routedEventArgs should contain a reference to the
    static Routed Event object defined (registered)
    as MyEvent, above.

These WPF Attached Events are also called Routed Events because they the handler for such event does not have to be defined on the same object on which
the event is raised or not even on an object that has a reference to an object on which such event is raised.
In fact Routed Event can propagate through the anscestor of object that raised such event within the Visual Tree that the object belongs to.

The Routed Events propagating up the Visual Tree (from the raising object to its anscestors) are called Bubbling events.
The Routed Events can also visit the anscestors first, starting from the
root node of the Visual Tree and ending the propagation at the
node that raised the Routed Event. Such events are called Tunneling events. Routed Events can also be neither
Bubbling nor Tunneling – in that case
they can only be handled on the object that raised them. Such events are called Direct event.

The routing behavior of an event (whether it is Bubbling, Tunneling or Direct is determined at the stage when the event is defined (registerd).

What we are Trying to Achieve

Here we are implementing Routed Event WPF concept outside of WPF.
Such event can Bubble and Tunnel and
also can propagate to Tree Node‘s descendants on any
Tree defined by its up and down propagation functions,
not only the Visual Tree. Such events can also be attached to any
objects, not only to FrameworkElements. The routing behavior of such an event is determined at the
time when it is raised, not at the time when it is defined. The event can have up to 4 arguments
specified by generic types.

Usage Example

We are going to show how the API is being used first, and only after that describe the implementation.

The test code is located within Program.cs file under AttachedRoutedEventTest project. We build the Tree in exactly the same fashion as it was done in Tree Structures and Navigation:

#region Start building tree out of TestTreeNodes objects
TestTreeNode topNode = new TestTreeNode { NodeInfo = "TopNode" };

TestTreeNode level2Node1 = topNode.AddChild("Level2Node_1");
TestTreeNode level2Node2 = topNode.AddChild("Level2Node_2");

TestTreeNode level3Node1 = level2Node1.AddChild("Level3Node_1");
TestTreeNode level3Node2 = level2Node1.AddChild("Level3Node_2");

TestTreeNode level3Node3 = level2Node2.AddChild("Level3Node_3");
TestTreeNode level3Node4 = level2Node2.AddChild("Level3Node_4");
#endregion End tree building
  

Here is how we define the toParentFunction and toChildrenFunction for the tree:

// to parent function
Func toParentFn =
    (treeNode) => treeNode.Parent;

// to children function
Func<TestTreeNode, IEnumerable> toChildrenFn =
    (treeNode) => treeNode.Children; 

First we print all the nodes of the tree shifted to the right in proportion to their distance from the top node:

IEnumerable<TreeChildInfo<TestTreeNode>> allTreeNodes =
    topNode.SelfAndDescendantsWithLevelInfo(toChildrenTreeFunction);

// print all the tree nodes
Console.WriteLine("\nPrint all nodes");
foreach (TreeChildInfo<TestTreeNode> treeNode in allTreeNodes)
{
    string shiftToRight = new string('\t', treeNode.Level + 1);
    Console.WriteLine(shiftToRight + treeNode.TheNode.NodeInfo);
}
  

Here is the result of printing:

TopNode
    Level2Node_1
        Level3Node_1
        Level3Node_2
    Level2Node_2
        Level3Node_3
        Level3Node_4

Here is how we create REvent:

REvent<TestTreeNode, string> aTestEvent = new REvent();  

By the type arguments we specify that this REvent will act on objects
of the type TestTreeNode and will be accepting objects of type
string as arguments – overall we can specify from 0 to 4 arguments
of different types for the REvent objects.

Now we can set our REvent‘s handlers for all the nodes of the tree:

// assign handlers for each of the 
foreach (TreeChildInfo<TestTreeNode> treeNodeWithLevelInfo in allTreeNodes)
{
    TestTreeNode currentNode = treeNodeWithLevelInfo.TheNode;

    aTestEvent.AddHander
    (
        currentNode,
        (str) =>
        {
            Console.WriteLine("Target Node: " + currentNode.NodeInfo + "\t\t\tSource Node: " + str);
        }
    );
}  

The handler would print the current node’s name and the string passed to the handler as
the source node’s name (it is assumed that the RaiseEvent function has the
name of the raising tree node passed as an argument).

Now we raise different events (bubbling, tunneling, direct and propagating to children) and observe the results

Bubbling Event

Console.WriteLine("\nTesting event bubbling:");
aTestEvent.RaiseBubbleEvent(level3Node3, toParentTreeFunction, level3Node3.NodeInfo);    
  

Bubbling event raised from the bottom level node level3Node3 will print the node itself and
all its ancestors printing first those who are closer to the originating node level3Node3:

Testing event bubbling:
Target Node: Level3Node_3			Source Node: Level3Node_3
Target Node: Level2Node_2			Source Node: Level3Node_3
Target Node: TopNode			        Source Node: Level3Node_3    
  

Tunneling Event

Console.WriteLine("\nTesting event tunneling:");
aTestEvent.RaiseTunnelEvent(level3Node3, toParentTreeFunction, level3Node3.NodeInfo);

Tunneling event will print the same nodes in the opposite order – starting from the top node and
ending with the originating node:

Testing event tunneling:
Target Node: TopNode			        Source Node: Level3Node_3
Target Node: Level2Node_2			Source Node: Level3Node_3
Target Node: Level3Node_3			Source Node: Level3Node_3  

Direct Event

Console.WriteLine("\nTesting event Direct Event (without bubbling and tunneling):");
aTestEvent.RaiseEvent(level3Node3, level3Node3.NodeInfo);  

Direct event will only print on the invoking node:

Testing event Direct Event (without bubbling and tunneling):
Target Node: Level3Node_3			Source Node: Level3Node_3  

Event Propagating to Descendents

Console.WriteLine("\nTesting event propagation to descendents:");
aTestEvent.RaiseEventPropagateToDescendents(level2Node1, toChildrenTreeFunction, level2Node1.NodeInfo);  

Event propagating to descendents fired from level2Node1 node located at the middle level,
will print the node itself and its two descendents:

Testing event propagation to descendents:
Target Node: Level2Node_1			Source Node: Level2Node_1
Target Node: Level3Node_1			Source Node: Level2Node_1
Target Node: Level3Node_2			Source Node: Level2Node_1 

Terminating Event Propagation

One can pass a Func instead of na Action to become an event
handler for the REvent. In that case, returning false from that function
would terminate the REvent propagation – analogous to setting e.Cancel=true
for WPF’s routed event.

Below we clear the event handler at level2Node2 node and reset to to
a Func that always returns false:

// stopping propagation by returning false from a handler
aTestEvent.RemoveAllHandlers(level2Node2);

aTestEvent.AddHander
(
    level2Node2, 
    () => 
    {
        Console.WriteLine("Terminating event propagation at node " + level2Node2.NodeInfo); 
        return false;
    }); // terminate event propagation at this node

After this we re-run the bubbling, tunneling and propagating to children events:

Console.WriteLine("\nTesting event bubbling with event propagation termination:");
aTestEvent.RaiseBubbleEvent(level3Node3, toParentTreeFunction, level3Node3.NodeInfo);


Console.WriteLine("\nTesting event tunneling with event propagation termination:");
aTestEvent.RaiseTunnelEvent(level3Node3, toParentTreeFunction, level3Node3.NodeInfo);


Console.WriteLine("\nTesting event propagation to descendents with event propagation termination:");
aTestEvent.RaiseEventPropagateToDescendents(topNode, toChildrenTreeFunction, topNode.NodeInfo);    
  

The results of these are shown below:

Testing event bubbling with event propagation termination:
Target Node: Level3Node_3			Source Node: Level3Node_3
Terminating event propagation at node Level2Node_2

Testing event tunneling with event propagation termination:
Target Node: TopNode			Source Node: Level3Node_3
Terminating event propagation at node Level2Node_2

Testing event propagation from the TopNode to its descendents with event propagation termination:
Target Node: TopNode			    Source Node: TopNode
Target Node: Level2Node_1			Source Node: TopNode
Target Node: Level3Node_1			Source Node: TopNode
Target Node: Level3Node_2			Source Node: TopNode
Terminating event propagation at node Level2Node_2 

You can see that the event propagation stops indeed at level2Node2 node.

Notes on Implementation

NP.Paradigms.REvent implementation code is located within REvent.cs file
under NP.Paradigms project.

REvent class defines AProperty _aProperty. Its purpose is to provide
a mapping between the objects on which some REvent handlers were set and objects of type
REventWrapper that actually saves the REvent handlers.

REventWrapper has _event member of List<Func<T1,T2,T3,T4,bool>>
type. It accumulates all of the event handlers associated with its object. It also has a bunch of functions
that help to convert Actions and Funcs with smaller amount of generic
type arguments into Func<T1,T2,T3,T4, bool>. There is also a map:
Dictionary<object, Func> _delegateToFuncMap that stores the mapping between
the original Action or Func with smaller number of generic type arguments and
the final Func<T1,T2,T3,T4>. This is needed if we want to remove a handler – we’ll need to find
the correct Func<T1,T2,T3,T4> and remove if from the _event list.

REvent class has various functions for adding the event handlers to an object. It also has functions
for raising event on an object so that it would propagate in a required fashion: bubbling, tunneling, direct or
propagation to children – as they were presented in the usage example section.

Tree Structures and Navigation

November 29, 2013

Code Location

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

Introduction

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

This post talks about generic Tree structures in C#. The relationship with WPF will become
clearer once we start talking about Routed Events outside of WPF (hopefully in the next post).

In his great LINQ TO VISUAL TREE
and LINQ to Tree – A Generic Technique for Querying Tree-like Structures articles, Colin Eberhardt talks about queries various
Tree
structures using LINQ. In order to fit the Tree structure into his framework the user of the code should either build an
adaptor satisfying ILinqToTree interface for the tree nodes, or generate such adaptor and the corresponding
LINQ functions using VisualStudion T4 templates.

Here I am defining a Tree structure without resorting to adapter interface
and using delegates instead. This
makes it more generic and makes it possible to apply the concept to a very wide class of objects without T4 template
generation.

What is a Tree?

A Tree is a set of objects called the Tree Nodes.
From any Tree Node one should be able to find its unique parent
Tree Node
(if it exists) or its collection of child Tree Nodes (if they exist). The above
Tree definition allows to find all the Tree Nodes
of a Tree recursively, the following information is given:

  • A Tree Node to start navigation.
  • A function that for any Tree Node
    returns its parent Tree Node or null
    (if it has no parent).
  • A function that for any Tree Node returns a collection of its children
    (it might be null or empty collection if no such children exist).

Translating the above into C# (or any other object oriented language that allows delegates or lambdas) we can write that
the Tree can be defined by one Tree Node
object or a generic type TreeNode and two delegates:

Func<TreeNode, TreeNode> ToParentFunction

and

Func<TreeNode, IEnumerable<TreeNode>> ToChildrenFunction

Note, also, that for navigating up the Tree only ToParentFunction is
required while for navigating down the Tree – only ToChildrenFuncion.

The Tree API

Based on the discussion above I created a generic API for navigating up and down the Tree
using C# extension functions.
The API is located within NP.Paradigms.TreeUtils static class under NP.Paradigms project.
The available functions are very similar to those from Colin Eberhardt’s articles, the difference is that one extra
argument is required – the function for navigation up or down a Tree:

/// Returns a collection of all ancestors of a node.
public static IEnumerable<NodeType> Ancestors<NodeType>
(
this NodeType node,
Func<NodeType, NodeType> toParentFunction
)

/// Returns the node itself and all its ancestors a part of a collection.
public static IEnumerable<NodeType> Ancestors<NodeType>
(
this NodeType node,
Func<NodeType, NodeType> toParentFunction
)

/// returns itself and all its descendants as part of a collection
/// of TreeChildInfo object that contain the node itself and the 
/// distance from to original node (called Level). 
/// Original node passed as an agument to this function 
/// has its level specified by the level argument (the default is 0)
/// its children will have Level property set to 1, grandchildren - to 2 etc.
public static IEnumerable<TreeChildInfo<NodeType>> SelfAndDescendantsWithLevelInfo<NodeType>
(
this NodeType node,
Func<NodeType, IEnumerable<NodeType>> toChildrenFunction,
int level = 0
)

/// Returns the descendants nodes with level info (just like SelfAndDescendantsWithLevelInfo)
/// only within the original node itself. 
public static IEnumerable<TreeChildInfo<NodeType>> DescendantsWithLevelInfo<NodeType>
(
this NodeType node,
Func<NodeType, IEnumerable<NodeType>> toChildrenFunction
)

/// Returns the original node and its descendants as part of a collection
public static IEnumerable<NodeType> SelfAndDescendants<NodeType>
(
this NodeType node,
Func<NodeType, IEnumerable<NodeType>> toChildrenFunction
)

/// Returns the descendants of an original node as a collection
public static IEnumerable<NodeType> Descendants<NodeType>
(
this NodeType node,
Func<NodeType, IEnumerable<NodeType>> toChildrenFunction
)
{
return node.DescendantsWithLevelInfo(toChildrenFunction).Select((treeChildInfo) => treeChildInfo.TheNode);
}

/// Returns the anscestors of the current node (starting from the Root node) 
/// and the current node's descendants. Level specifies the 
/// distance from the Root Node (top node)
public static IEnumerable<TreeChildInfo<NodeType>> AncestorsAndDescendants<NodeType>
(
this NodeType node,
Func<NodeType, NodeType> toParentFunction,
Func<NodeType, IEnumerable<NodeType>> toChildrenFunction
)

/// returns all the nodes of the tree except for the
/// original node itself, its descendents and ancestors (the top node is still returned
/// even thought it is an ascestor).
public static IEnumerable<TreeChildInfo<NodeType>> AllButAncestorsAndDescendants<NodeType>
(
this NodeType node, 
Func<NodeType, NodeType> toParentFunction,
Func<NodeType, IEnumerable<NodeType>> toChildrenFunction
)

The last two functions AncestorsAndDescendants and AllButDescendantsAndAncestors
do not have analogues in Colin Eberhardt’s articles but are still pretty useful sometimes.

Non-Visual Tree Usage Example

The usage example can be found under project TreeTests (do not forget to make this project
a start up project within the solution).

In the Main function of this project (located within Program.cs file,
we build a tree out of TestTreeNode objects. Each TestTreeNode object
contains a Parent property specifying the parent of the node, Children
collection specifying the children of the node and NodeInfo property – which is
simply a string that should uniquely identify the node. Function AddChild(string childNodeInfo)
fascilitates building the tree. It adds a child node setting its NodeInfo property to the
passed string parameter and setting its Parent property to the current node.

Here is how we build the tree:

#region Start building tree out of TestTreeNodes objects
TestTreeNode topNode = new TestTreeNode { NodeInfo = "TopNode" };

TestTreeNode level2Node1 = topNode.AddChild("Level2Node_1");
TestTreeNode level2Node2 = topNode.AddChild("Level2Node_2");

TestTreeNode level3Node1 = level2Node1.AddChild("Level3Node_1");
TestTreeNode level3Node2 = level2Node1.AddChild("Level3Node_2");

TestTreeNode level3Node3 = level2Node2.AddChild("Level3Node_3");
TestTreeNode level3Node4 = level2Node2.AddChild("Level3Node_4");
#endregion End tree building

The functions to go up and down the tree are specified in the following way:

// to parent function
Func<TestTreeNode, TestTreeNode> toParentFn =
(treeNode) => treeNode.Parent;

// to children function
Func<TestTreeNode, IEnumerable<TestTreeNode>> toChildrenFn =
(treeNode) => treeNode.Children;

Finally we print anscestors and descendents of the nodes:

Console.WriteLine("Print ancestors of node level3Node3");

foreach (var treeNode in level3Node3.Ancestors(toParentFn))
Console.WriteLine("\t" + treeNode.NodeInfo);

Console.WriteLine("\n");

Console.WriteLine("Print self and ancestors of node level3Node3");
foreach (var treeNode in level3Node3.SelfAndAncestors(toParentFn))
Console.WriteLine("\t" + treeNode.NodeInfo);

Console.WriteLine("\nPrint whole tree");

foreach (var treeNodeInfo in topNode.SelfAndDescendantsWithLevelInfo(toChildrenFn))
{
// shift the string by the level number plus 1 tabs
string tabs = new string('\t', treeNodeInfo.Level + 1);

Console.WriteLine(tabs + treeNodeInfo.TheNode.NodeInfo);
}

Here are the printed results:

Print ancestors of node level3Node3
Level2Node_2
TopNode

Print self and ancestors of node level3Node3
Level3Node_3
Level2Node_2
TopNode

Print whole tree
TopNode
Level2Node_1
Level3Node_1
Level3Node_2
Level2Node_2
Level3Node_3
Level3Node_4

Note, that when we print the top node of the tree and its descendents (the last print out)
we shift the descendents to the right by placing Tab characters in front of the strings.
The number of those tab characters equals to the Level property of the
corresponding TreeNodeInfo object so that the farther the nodes are
from the top node, the farther to the right they will appear.

WPF Visual and Logical Trees Usage Examples

WPF VisualTreeHelper and LogicalTreeHelper classes can furnish us
with delegates to go up and down visual and logical trees correspondingly. Project
NP.Paradigms.Windows contains VisualTreeUtils and LogicalTreeUtils
static classes providing LINQ functions for Visual an Logical trees correspondingly. They are
simply wrappers around NP.Paradigms.TreeUtils class described above.

VisualTreeHelper operates on objects of FrameworkElement class. Because of this,
all the VisualTreeUtils functions operate on FrameworkElement objects.
Here is how we define the ToParentFunction and ToChildFunction for the
VisualTreeUtils class:

static Func<FrameworkElement, FrameworkElement> toParentFunction =
(obj) => VisualTreeHelper.GetParent(obj) as FrameworkElement;

static Func<FrameworkElement, IEnumerable<FrameworkElement>> toChildrenFunction =
(parentObj) =>
{
int childCount = VisualTreeHelper.GetChildrenCount(parentObj);

List<FrameworkElement> result = new List<FrameworkElement>();
for (int i = 0; i < childCount; i++)
{
result.Add(VisualTreeHelper.GetChild(parentObj, i) as FrameworkElement);
}

return result;
};

The extension method of VisualTreeUtility class are self explanotary and
correspond to the TreeUtils class methods one to one except that they start
with prefix Visual to avoid the name clashes.

When it come to LogicalTreeHelper, some of the children, that it returns
might not be of FrameworkElement type. If fact contents of the Buttons or
of TextBlock or other objects can be simply strings. Because of that we define all of our
extension methods on plain objects. Here is how the ToParentFunction and ToChildFunction
are defined for the logical tree:

static Func<object, object> toParentFunction =
(obj) =>
{
if ( !(obj is DependencyObject) )
{
return null;
}

return LogicalTreeHelper.GetParent(obj as DependencyObject);
};

static Func<object, IEnumerable<object>> toChildrenFunction =
(parentObj) =>
{
if (!(parentObj is DependencyObject))
{
return null;
}

return LogicalTreeHelper.GetChildren(parentObj as DependencyObject).Cast<object>();
};

The extension methods of the LogicalTreeUtils class are also self explanotary and have
preffix Logical to avoid the name clashes.

The usage example for VisualTreeHelper and LogicalTreeHelper methods
is located under VisualTreeTests project. The function MainWindow_Loaded
gets the tree nodes for the visual and logical trees of ElementToDisplay grid that
contains a TextBlock and a Button. The collections of tree nodes
are converted into collections of TreeNodeDisplayer objects that transform the
tree nodes into indented strings: FrameworkElements are displayed by their type name
in parentheses followed by name and other objects are simply converted to strings using
ToString() method. The indentation is related to their level within the tree
(how far they are from the root node of the tree). The visual and logical trees are displayed
under the ElementToDisplay:

Bind Markup Extension

November 25, 2013

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

Even though, the purpose of these articles is to show how to implement
and use WPF concepts outside of WPF, WPF and XAML application are still the major beneficiaries of
this new approach which will allow to e.g. create bindings between properties on the non-visual View Models
or extend the non-visual View Models (by using AProperties) without modifying the View Model code.
Because of this, it makes sense to create a XAML markup extension for the non-WFP binding
described in Composite Path Bindings outside of WPF. This article talks about creating and using such markup extension.

The source code for this blog post is located under
BindMarkupExtensionCode.zip link.

Bind Extension

To distinguish the new markup extension from WPF’s Binding markup extension, we’ll call it Bind
or BindExtension.

BindExtension class is located under NP.Paradigms.Windows project. It extends
System.Windows.Markup.MarkupExtension class. It has the following public properties that can be
set in XAML:

  1. Source – allows to specify the binding source object. If Source property is not
    specified, we are trying to figure out the source object from other properties e.g.
    SourceElementName described below. If nothing helps, the source object is assumed to be the same
    as the target object (we still have no notion similar to the DataContext in WPF bindings).
  2. SourceElementName – is similar to ElementName of WPF binding. It allows to specify a
    named XAML element to serve as the Binding‘s source.
  3. SourcePath – a string that specifies the path of the binding relative to the binding’s
    Source object.
    The path links are separated by periods (‘.’). The plain properties are specified as strings. The WPF attached
    or dependency properties are placed within parentheses. The AProperties are placed within two
    asterisks. Here is a composite path sample: MyPlainProp.(this:MyAttachedProps.MyTestAttachedProp).*this:MyTestAProps.MyTestAProp*. This path is looks for AProperty MyTestAProps.MyTestAProp within
    an object defined by an attached property MyAttachedProps.MyTestAttachedProp within an object
    define by a plain property MyPlainProp of the source object of the binding. Both attached property
    and AProperty are defined within the current project specified by XAML prefix “this:”.
  4. TargetPath – a string that specifies the path to the target of the binding
    with respect to the target binding object and the target property. Unlike the WPF binding
    our composite path binding allows to specify a composite target path (see Composite Path Bindings outside of WPF). The first link or the
    target path will always be the target property defined within XAML. The subsequent links can be
    defined by TargetPath string. Here is a XAML example
    <Grid DataContext={Bind TargetPath="MyProp"...}. This example will not set the
    DataContext property on the grid. Instead it will use DataContext property as the first link
    in the target binding and will modify DataContext.MyProp property instead (if it exists, of course).
    If TargetPath is not specified, the XAML target property will be modified.
  5. TheBindType – similar to WPF binding’s Mode. Here are the possible values
    • OneWay – binding from source to target property
    • OneWayReverse – binding from target to source property (similar to WPF’s OneWayToSource)
    • TwoWay – binds source and target properties together so that when one of them changes, the other changes also. The initial value is set from source to target.
    • TwoWayReverseInit – binds source and target properties together so that when one of them changes, the other changes also. The initial value is set from target to source.

Usage Samples

Project XamlBindingTests shows how to use the BindExtension in XAML. The relevant XAML code is located within
MainWindow.xaml file. Here is how the test application looks:

TestApp

Test1 demonstrates attaching plain property to dependency property using Bind extension.
Text property of a TextBlock is bound to MyTestProp property
of a resource object MyTestDataObj_Test1:

<TextBlock Text="{winparadigms:Bind Source={StaticResource MyTestDataObj_Test1},
                                    SourcePath=MyTestProp}"
           Grid.Column="1"/>

When a button “Add Value to Plain Prop” is clicked the property of the resource object is added “_hi” at the end and the binding
transfers the corresponding change to the Text property of the TextBlock object.

Test2 shows how to set the binding in both directions – from a Text property on
TextBox to a resource object and
from the resource object to the Text property on a TextBlock:

<TextBox Width="100"
          Height="25"
          Text="{winparadigms:Bind Source={StaticResource MyTestDataObj_Test2},
                                 SourcePath=MyTestProp,
                                 TheBindType=OneWayReverse}"/>

<TextBlock Text="{winparadigms:Bind Source={StaticResource MyTestDataObj_Test2},
                                    SourcePath=MyTestProp}"
           Grid.Column="1" />

When you start typing
in the TextBox the TextBlock text shows next to it.

Test3 demos a two TwoWay bindings – one from a TextBox to a resource object and
the other from the same resource object back to a different text box.
The two text boxes are thus bound in both directions via a resource object:

<TextBox Width="100"
            Height="25"
            Text="{winparadigms:Bind Source={StaticResource MyTestDataObj_Test3},
                                    SourcePath=MyTestProp,
                                    TheBindType=TwoWayReverseInit}" />

<TextBox Width="100"
          Height="25"
          Text="{winparadigms:Bind Source={StaticResource MyTestDataObj_Test3},
                                 SourcePath=MyTestProp,
                                 TheBindType=TwoWay}"
          Grid.Column="1" />

Test4 shows how to use SourceElementName to bind Text properties in
two TextBox objects:

<TextBox Width="100"
            Height="25"
            Text="{winparadigms:Bind SourceElementName=TextBoxToMatch,
                                    SourcePath=(TextBox.Text),
                                    TheBindType=TwoWay}" />
<TextBox Width="100"
          Height="25"
          x:Name="TextBoxToMatch"
          Text="Text to match"
          Grid.Column="1" />

Finally Test5 shows how to bind an AProperty. The AProperty
this:MyAProps.MyTestAProp is defined on the
resource object MyTestDataObj_Test5. It is bound to its own plain property MyTestProp:

<this:MyTestData x:Key="MyTestDataObj_Test5"
                  this:MyAProps.MyTestAProp="{winparadigms:Bind SourcePath=MyTestProp, TheBindType=TwoWay}"
                  MyTestProp="InitialValue" />

Also one TextBox of Test5 binds its Text to the plain MyTestProp
of the resource object MyTestDataObj_Test5, while the other TextBox of the test
binds to the AProperty:

<TextBox Width="100"
         Height="25"
         Text="{winparadigms:Bind Source={StaticResource MyTestDataObj_Test5},
                                  SourcePath=MyTestProp,
                                  TheBindType=TwoWay}" />
<TextBox Width="100"
         Height="25"
         Text="{winparadigms:Bind Source={StaticResource MyTestDataObj_Test5},
                                  SourcePath=*this:MyAProps.MyTestAProp*,
                                  TheBindType=TwoWay}"
         Grid.Column="2" />

Thus the two TextBoxes are bound together via a plain property and an AProperty on a resource object.

AProperties and Bindings outside of WPF Revisited

May 21, 2013

AProperties and Bindings outside of WPF Revisited

In the past I had a series of blog posts about re-implementing WPF concepts outside of WPF (see Codeproject: Binding without WPF, Codeproject: Attached Properties outside of WPF and Codeproject: Expression based Property Getters and Setters).

This post continues talking about non-WPF Attached Properties (AProperties) and Bindings (as well as the LINQ Expression property getters and setters) fixing problems left from the previous posts and preparing the readers for other interesting concepts that will to be expained the future articles.

Rearranging the Code

The new source code is located under BindingParadigmsCode.zip file. I rearranged the all the code related to the 3 blog posts mentioned above under the same project (namespace) NP.Paradigms. Some utility code I placed under NP.Paradigms.Extensions sub-namespace (sub-folder). Directory BindingParadigmsCode\TESTS contains the usage samples for
the functionality.

AProperties without Memory Leaks

AProperties (attached properties implemented outside of WPF)
were introduced in Codeproject: Attached Properties outside of WPF.
In fact as described at the link above, the AProperties are, in many respects, more powerful than the regular WPF Attached Properties.

As a brief refresher, AProperties maps an object to some value by the object’s reference, so that the value can be retrieved given the object reference. Unlike the usual C# properties (and like the WPF’s Attached Properties), the AProperties do not need
to be defined on the object itself, instead, they are kind of externally attached to the object. Each AProperty has an internal map _objectToPropValueMap that maps the object’s reference to the corresponding AProperty value.

As one reader noticed, the AProperties might introduce a memory leak, in a sense that
when all the outside references to the object that has some non-default AProperty value are removed, the _objectToPropValueMap dictionary within the corresponding AProperty might still hold a reference to the original object, so that the object is not garbage collected and the corresponding cell also stays within the _objectToPropValueMap dictionary. In fact the key of the map is the object itself, while the value (of type APropertyValueWrapper) has a reference Obj to the object.

In order to fix the memory leak, I replaced the value’s reference to the object by a WeakReference and replaced the Dictionary with ConditionalWeakTable class located within System.Runtime.CompilerServices namespace. ConditionalWeakTable class provides an implementation of Dictionary or Map with weak key references, allowing the garbage collector to collect the object and once the object is collected, it automatically removes it from the Map.

I tested performance of ConditionalWeakTable vs. usual C# Dictionary performance and found that the search and the insertion is approximately 1.4-1.6 times slower (which I deemed acceptable).

The code containing the AProperty garbage collection tests is located under CollectableAPropsTest project. Here is the body of the Main function with detailed comments:

 // create an object of MyClass class
MyClass myObj = new MyClass();

// create AProperty that assigns string to MyClass objects
AProperty<MyClass, string> myAProp = new AProperty<MyClass, string>(null);

myAProp.SetProperty(myObj, "Hello World");

// try to do garbage collection, 
// the myObj should not be collected at this point
// since the main program has a strong reference to it.
GC.Collect();

// the property should not be collected at this point
// since the reference to the object still exists in the 
// Main program.
string thePropValue = myAProp.GetProperty(myObj);

Console.WriteLine("The AProp Value is " + thePropValue);

// set the only 'strong' reference to myObj to null
myObj = null; 

// after the only 'strong' reference to myObj 
// was set to null, the call to 'GC.Collect()' should
// collect the object not-withstanding the fact
// that it is still weakly refenced from within myAProp object.
GC.Collect();
// destructor should be called before sleep or in the beginning of sleep;
Console.WriteLine("before sleep");
Thread.Sleep(3000);

GC.Collect();

// if you put a break point at the next line, 
// and expand the internals of myAProp object, 
// you'll see that it has no objects within it
// (the weak reference key has been removed)
Console.WriteLine("After sleep");

If you put a breakpoint at the last line and expand myAProp
object, you will see that its _objectToPropValueMap
does not contain any entries (its key and value counts are zero),
meaning as the object had been collected, the corresponding map entry was
removed also:
ConditionalWeakTableInside

New Expression Based Property Getters and Setters

A blog post Codeproject: Expression based Property Getters and Setters talked about creating precompiled LINQ Expression based property getters and setters. They required the a-priory knowledge of the object and property types since they were returning Func<ObjectType, PropertyType> – for a getter and Action<ObjectType, PropertyType> – for a setter, with the requirement that the ObjectType and PropertyType should match the types of the object and property to which they are applied. Here I provided some extra methods where this requirement is relaxed – Func<object, object> is returned for a getter and Action<object, object> is returned for setter. This incurs an extra cast operation for a getter and two extra cast operations for a setter (the one for the object and for the property), but the expressions are still precompiled and the performance of the untyped lambdas is still very close to that of their strongly typed counterparts and greatly exceeds that of the reflection based functionality. The actual types of the untyped getters and setters can be inferred from the object and the property itself.

I placed this functionality under NP.Paradigms.Extensions namespace so that its extension methods will not pollute the main namespace.

To underscore that this functionality deals only with plain C# properties, I inserted CS within the function names.

The testing project for the functionality is called ExpressionCSPropertyGettersAndSettersTests and is located under TESTS folder. Here is the body of its Main method with the comments:

MyClass myTestObj = new MyClass();

// strongly typed property getter
Func<MyClass, string> stronglyTypedPropertyGetter =
    CompiledExpressionUtils.GetCSPropertyGetter<MyClass, string>("MyProperty");

// test strongly typed property getter (should return "Hello World")
Console.WriteLine("\nTesting strongly typed property getter");
Console.WriteLine(stronglyTypedPropertyGetter(myTestObj));

// get the untyped but compiled property getter (should be a little slower
// due to an extra cast operation, but still pretty close in perfromance
Func<object, object> untypedPropertyGetter = myTestObj.GetUntypedCSPropertyGetter("MyProperty");

// test the untyped property getter ( should return "Hello World")\\
Console.WriteLine("\nTesting untyped property getter");
Console.WriteLine(untypedPropertyGetter(myTestObj));

// strongly typed property setter
Action<MyClass, string> stronglyTypedPropertySetter =
    CompiledExpressionUtils.GetCSPropertySetter("MyProperty");

// set the property using strongly typed property setter
stronglyTypedPropertySetter(myTestObj, "Hi World");
Console.WriteLine("\nTesting strongly typed property setter");
Console.WriteLine(myTestObj.MyProperty);

// get the untyped by compiled property setter
Action<object, object> untypedPropertySetter = myTestObj.GetUntypedCSPropertySetter("MyProperty");

// use the untyped property setter to changed the property back to "Hello World"
untypedPropertySetter(myTestObj, "Hello World");
Console.WriteLine("\nTesting untyped property setter");
Console.WriteLine(myTestObj.MyProperty);

and here is the code for MyClass class:

public class MyClass
{
    public string MyProperty { get; set; }

    public MyClass()
    {
        MyProperty = "Hello World";
    }
}

New Property Binding Functionality

Non-WPF property and collection bindings is described at
Codeproject: Binding without WPF blog post. The only properties we dealt with there, were plain C# properties that fire INotifyPropertyChanged.PropertyChanged event when modified. Now we also have AProperty concept and we want to bind them too. Moreover, sometimes we might want to bind a plain C# source property to an AProperty target and vice versa. Eventually we might also want to bind in a similar ways to WPF Attached Properties. Because of this new complexity, we have to take a different look at the property bindings.

As was shown at the previous binding blog post, the binding should implement IBinding interface:

public interface IBinding
{
    void InitialSync();
    void Bind(bool doInitialSync = true);
    void UnBind();
}

Let us take a look at the property binding from a different angle. A binding should be able to detect when the bound source property changes on the source object, get its value, possibly convert it to the type appropriate for the target property and set it on the target property of the target object. On top of this, when the binding is set, it would be logical to propagate the source property to the target property even though the source property did not change. It is logical to assume that the binding consists of 3 parts – property getter, property setter and property value converter. Property getter is an object of IPropGetter<PropertyType> interface that fires an event when the property changes that has the new property value as an argument. Also to cover the case of setting the target property value at the time when the binding is set (without the source property change) it has to have a method that would trigger the property propagation whenever the binding implementation needs it:

public interface IPropGetter<PropertyType>
{
    // fires when the property changes
    // its argument is new property value
    event Action PropertyChangedEvent;

    // forces PropertyChangedEvent to fire
    // (it is needed e.g. when when two properties
    // are bound - the source property should 
    // trigger the target property change even
    // if the source property does not change)
    void TriggerPropertyChanged();
}

The target property setter can be represented by an even simpler interface that has only one method Set:

public interface IPropSetter<PropertyType>
{
    // sets the target property
    void Set(PropertyType property);
}

The converter is represented by IValConverter interface unchanged from the previous article:

public interface IValConverter<InputType, OutputType>
{
    OutputType Convert(InputType sourceObj);
}

OneWayProperytBindingBase class combines the property getter, setter and converter. Its Bind function binds the source property getter and target property setter. Note, that the property getter and setter within OneWayPropertyBindingBase class do not specify any particular implementation – they are interfaces that can be implemented for plain C# properties or AProperties.

The property getter and setter for plain C# properties are located under PlainPropGetterAndSetter.cs file and they are expression based, while AProperty getters and setters are defined under APropsGetterAndSetter.cs file. By combining the correct getter and setter types, one can bind plain C# property to another plain C# property or to an AProperty or vice versa – an AProperty to another AProperty or to a plain C# property. There is a utility class BindingPath (named like that after WPF’s PropertyPath) that facilitates resolving the getter and setter types.

OneWayPropertyBinding class extends OneWayPropertyBindingBase class and utilizes the BindingPath objects to figure out its
property getter and setter.

BindingTests project illustrates using the binding functionality connecting any combinations of plain C# properties and AProperties. The source and target objects are both of class MyTestDataClass that implements INotifyPropertyChanged interface and contains MyStringProp string property that fires the PropertyChanged event when it changes. The Main function’s code shows how to bind plain to plain, plain to AProperty, AProperty to plain and AProperty to AProperty. In each of these 4 cases, the binding sets the target property to be the same as the source property (“Hello World”) and then when the source property changes to “Hi World” the target property changes too. Here is the console output of the test run:

Testing binding from plain property to another plain property

Testing target property change after binding operation: Hello World
Testing target property change after the source property change: Hi World

Testing binding from plain property to another plain property

Testing target property change after binding operation: Hello World
Testing target property change after the source property change: Hi World

Testing binding from plain property to AProp

Testing target property change after binding operation: Hello World
Testing target property change after the source property change: Hi World

Testing binding from AProp to plain property

Testing target property change after binding operation: Hello World
Testing target property change after the source property change: Hi World
Press any key to continue . . .

Here is the Main method code:

#region Plain C# to Plain C# property binding 
Console.WriteLine("\n\nTesting binding from plain property to another plain property\n");

// initialize test objects
MyTestDataClass sourceObj = new MyTestDataClass
{
    MyStringProp = "Hello World"
};

MyTestDataClass targetObj = new MyTestDataClass();

OneWayPropertyBinding<string, string> plainToPlainPropBinding = 
    new OneWayPropertyBinding<string, string>();

plainToPlainPropBinding.SourceObj = sourceObj;
plainToPlainPropBinding.SourcePPath = new BindingPath<string>("MyStringProp");
plainToPlainPropBinding.TargetObj = targetObj;
plainToPlainPropBinding.TargetPPath = new BindingPath<string>("MyStringProp");

// bind the two properties. 
plainToPlainPropBinding.Bind();

// verify that the binding changed the target property 
// to be the same as the source property
Console.Write("Testing target property change after binding operation: ");
Console.WriteLine(targetObj.MyStringProp); // should print Hello World;

// let us change the source property and verify that target property also changes
sourceObj.MyStringProp = "Hi World";
Console.Write("Testing target property change after the source property change: ");
Console.WriteLine(targetObj.MyStringProp); // should print Hi World;

#endregion Plain C# to Plain C# property binding 

#region AProperty to AProperty binding
Console.WriteLine("\n\nTesting binding from plain property to another plain property\n");

AProperty<object, string> myAProperty = new AProperty<object, string>();

// reinitialize test objects
sourceObj = new MyTestDataClass();
targetObj = new MyTestDataClass();

// set AProperty on the source object before the binding 
myAProperty.SetProperty(sourceObj, "Hello World"); 

OneWayPropertyBinding<string, string> aPropToAPropBinding = new OneWayPropertyBinding<string, string>();

aPropToAPropBinding.SourceObj = sourceObj;
aPropToAPropBinding.SourcePPath = new BindingPath<string>(myAProperty);
aPropToAPropBinding.TargetObj = targetObj;
aPropToAPropBinding.TargetPPath = new BindingPath<string>(myAProperty);

aPropToAPropBinding.Bind();

Console.Write("Testing target property change after binding operation: ");
Console.WriteLine(myAProperty.GetProperty(targetObj));

// change the source property 
myAProperty.SetProperty(sourceObj, "Hi World");

Console.Write("Testing target property change after the source property change: ");
Console.WriteLine(myAProperty.GetProperty(targetObj));

#endregion AProperty to AProperty binding

#region plain property to AProperty binding

Console.WriteLine("\n\nTesting binding from plain property to AProp\n");

// reinitialize test objects
sourceObj = new MyTestDataClass
{
    MyStringProp = "Hello World"
};

targetObj = new MyTestDataClass();

OneWayPropertyBinding<string, string> plainToAPropBinding = new OneWayPropertyBinding<string, string>();

plainToAPropBinding.SourceObj = sourceObj;
plainToAPropBinding.SourcePPath = new BindingPath<string>("MyStringProp");
plainToAPropBinding.TargetObj = targetObj;
plainToAPropBinding.TargetPPath = new BindingPath<string>(myAProperty);

plainToAPropBinding.Bind();

Console.Write("Testing target property change after binding operation: ");
Console.WriteLine(myAProperty.GetProperty(targetObj));

sourceObj.MyStringProp = "Hi World";
Console.Write("Testing target property change after the source property change: ");
Console.WriteLine(myAProperty.GetProperty(targetObj));

#endregion plain property to AProperty binding

#region AProperty to plain property binding

Console.WriteLine("\n\nTesting binding from AProp to plain property\n");

// reinitialize test objects
sourceObj = new MyTestDataClass();
targetObj = new MyTestDataClass();

myAProperty.SetProperty(sourceObj, "Hello World");

OneWayPropertyBinding<string, string> aPropToPlainBinding = new OneWayPropertyBinding<string, string>();
aPropToPlainBinding.SourceObj = sourceObj;
aPropToPlainBinding.SourcePPath = new BindingPath<string>(myAProperty);
aPropToPlainBinding.TargetObj = targetObj;
aPropToPlainBinding.TargetPPath = new BindingPath<string>("MyStringProp");

aPropToPlainBinding.Bind();

Console.Write("Testing target property change after binding operation: ");
Console.WriteLine(targetObj.MyStringProp);

myAProperty.SetProperty(sourceObj, "Hi World");

Console.Write("Testing target property change after the source property change: ");
Console.WriteLine(targetObj.MyStringProp);

#endregion AProperty to plain property binding

You can see that our binding functionality is, in some respect, more generic than that of WPF – indeed in WPF only Attached (or Dependency) Property can be a target of a binding, while, in our case, it can be either plain C# property or AProperty. It the future I plan to generalize it even further, allowing binding to and from WPF Attached Properties.

Binding without WPF

March 31, 2013


This article is originally published at nickssoftwareblog.com

I was saying before that WPF introduced a lot of concepts that are actually bigger than WPF and can be applied to purely non-visual objects.

Here we are going to talk about the binding concept and how it can be re-implemented outside of the WPF without being tied to the visual libraries or the UI threads. We are going to talk about property and collection bindings.

Property bindings are quite similar to the usual WPF bindings – a change of a property on one object can trigger a change of a different property on a different object.

Collection bindings are also present in WPF but only implicitly. You’ve come across them  if you dealt with various descendants of the ItemsControl class. ItemsControl has ItemsSource property that should be set to a collection of (usually) non-visual objects. When you supply an ItemTemplate or an ItemTemplateSelector, you essentially specify how to turn those non-visual objects into the visual ones. The resulting visual objects can be e.g. of ListBoxItem or ListViewItem type etc. The ItemsSource collection is bound with the resulting collection of visual objects so that when you add or remove the items from the one of them, the corresponding items are also added or removed from the other. Here we discuss creating a similar binding between non-visual collections.

Why would someone need a binding without WPF? Actually there are a lot of situations where you want different parts of your application (visual or not) to change in sync. Here are just a few examples:

  1.  Assume that you use an MVVM pattern. Your view model has a collection that consists of different items. Each item is similar to corresponding items from the model, but have some view specific properties added (e.g. IsVisible, IsEnabled etc). You want you view model to be totally in sync with the model without much extra code. Actually you can use the non-visual binding to achieve that.
  2. Using bindings you can can easily create an observer pattern, with one a bunch of objects having two way bindings to a single (observable) object, so that when one of them changes, the rest are updated via the observable object.
  3. When you do not have access to WPF functionality e.g. if you are programming Objective-C or some other language for a different platform, you can use the generic binding to bind visual parts of the application to the non-visual code, similar to the way it is done in WPF.

The library containing the binding code can be downloaded from NP.Binding.Utils.zip.
Its capabilities are better shown by the samples which can be downloaded from BindingSamples.zip.

The simplest sample showing how to bind two properties together is located under PropToPropBindingTest solution. The main program of the solution, shows how to create two objects with and bind them so that if the property on the first object changes, the property on the second object changes too. Here is the source code of the Main function:

static void Main(string[] args)
{
    AClassWithBindindableProperty a1 = new AClassWithBindindableProperty();

    AClassWithBindindableProperty a2 = new AClassWithBindindableProperty();

    a2.OneWayBind("ABindingProperty", a1, "ABindingProperty");

    a1.ABindingProperty = "1234";

    Console.WriteLine(a2.ABindingProperty);
}

The code above creates two objects a1 and a2 of AClassWithBindindableProperty type and uses OneWayBind() utility function to bind their ABindingProperty properties together. The source object is a1 and the target object is a2. AClassWithBindindableProperty class implements INotifyPropertyChanged interface and ensures that its PropertyChanged event fires when the corresponding property changes. Note that unlike in WPF, the target property does not have to be a dependency property on a dependency object. Also note, that in order to prevent the circular updates, the implementation of the property setter ensures that the PropertyChanged event does not fire if the new property value is the same as the old one.

The binding method OneWayBind is a static extension method defined within BindingUtils static class within NP.Binding.Utils library. It creates a OneWayPropertyBinding object, sets its parameters and calls its Bind method. The OneWayPropertyBinding uses reflection to bind the source property to the target property. If, at some point, you want to remove the binding, you have to save the OneWayPropertyBinding object and later call UnBind() method on it.

Note that classes representing different types of bindings (with OneWayPropertyBinding among them) implement IBinding interface that has 3 methods:

  1. Bind(bool doInitialSync=true) – creates a binding within an option to skip initial synchronization of the bound objects (or properties).
  2. UnBind() – removes a previously created binding.
  3. InitialSync() – Synchronizes the bound objects after the binding has been created (e.g. in case of property binding, it usually means setting the target property to equal the source property when the binding is established (even if the source property did not change at that time)

Note, that OneWayPropertyBinding class TheConverter property allowing to set the binding’s converter ensuring that the target property can be different from the source one.

The next sample to consider is located under OneWayCollectionBindingTest solution. It shows how to use OneWayCollectionBinding class to bind two different collections, so that when the source collection changes (i.e. has elements added or removed or moved) the target collection undergoes similar changes.

Here is the code from the sample’s Main function:

static void Main(string[] args)
{
    // create source collection elements to be integers from 1 to 20
    ObservableCollection source =
        new ObservableCollection(Enumerable.Range(1, 20));

    List target = new List();

    // create the binding
    OneWayCollectionBinding myBinding =
        new OneWayCollectionBinding
        {
            SourceCollection = source,
            TargetCollection = target,
            SourceToTargetDelegate = (i) => i + 100 //set each target element to be 
                                                    // 100 + corresponding source element
        };

    // bind
    myBinding.Bind();

    // remove 5th element from the source
    source.RemoveAt(5);

    // move source element at position 1 to position 4
    source.Move(1, 4);
    Console.WriteLine("\n\nSOURCE");
    source.ForEach(Console.WriteLine); // print the resulting source elements

    Console.WriteLine("\n\nTARGET");
    target.ForEach(Console.WriteLine); // print the resulting target elements
}

Running this code will result in source and target elements being in sync in spite of the source collection manipulations (we removed the element from position 5 in it and moved the element at position 1 to position 4). SourceToTargetDelegate of the OneWayCollectionBinding class allows to specify conversion between the source and target collection elements (in our sample we simply add 100 to the source element in order to obtain the target one). We use OneWayCollectionBinding with one generic argument – int (meaning that the source and target collection elements are of the same time int. In fact we can use OneWayCollectionBinding with two different generic arguments e.g. OneWayCollectionBinding<int, string> allowing the source and target elements to be of different types. In that case SourceToTargetDelegate will produce an object of the target type out of the source type object.

In case of a property-to-property binding we used comparison of the new and older property values in order to make sure that we avoid an infinite updating loop. Unfortunately we cannot resort to a similar check in can of the collection bindings. The full solution for preventing the infinite loops for circular bindings is beyond this article and will be presented later. Here, however, we can make sure that the binding action is only called once by using _doNotReact field and DoNotReact property. We can also pass the information that the binding is acting at this point in time to an external entity by using OnDoNotReactChangedEvent event. This is important for create two way bindings. Note that the source collection for collection binding should always be an ObservableCollection.

The final sample (TwoWayCollectionBindingTest) demonstrates a two way collection binding when the source and target collections are in perfect sync, i.e. changes to any of them will result in the corresponding changes in the other. Here is the Main for the sample:

static void Main(string[] args)
{
    ObservableCollection<int> sourceCollection =
        new ObservableCollection<int> { 1, 2, 3 };

    ObservableCollection<string> targetCollection =
        new ObservableCollection<string>();

    TwoWayCollectionBinding<int, string> twoWayBinding = 
        new TwoWayCollectionBinding<int, string>
        {
            SourceCollection = sourceCollection,
            TargetCollection = targetCollection,
            SourceToTargetDelegate = (i) => i.ToString(),// specifies how to create target 
                                                            // elements out of source ones
            TargetToSourceDelegate = (str) => Int32.Parse(str) // specifies how to create source 
                                                                  // elements out of target ones
        };

    twoWayBinding.Bind();

    Console.WriteLine("After removing element at index 1");
    sourceCollection.RemoveAt(1); // remove element at index 1 from source collection
    targetCollection.ForEach((str) => Console.WriteLine(str)); // print target collection

    Console.WriteLine("After adding 4");
    targetCollection.Add("4"); // append string "4" to the end of the target collection
    sourceCollection.ForEach((i) => Console.WriteLine(i)); // print the source collection

    Console.WriteLine("After inserting 0");
    targetCollection.Insert(0, "0"); // insert string "0" at index 0 for the target collection
    sourceCollection.ForEach((i) => Console.WriteLine(i)); // print the source collection

    Console.WriteLine("After inserting 2");
    sourceCollection.Insert(2, 2); // insert number 2 at index 2 for the source collection
    targetCollection.ForEach((str) => Console.WriteLine(str)); // print the target collection
}

Both source and target collections have to be of ObservableCollection type (both should fire
CollectionChanged event when the collection content changes). Note that the source and target elements are of different types within this sample: the source elements are of type int while the target elements are of type string. SourceToTargetDelegate and TargetToSourceDelegate specify how to create a target element from a source element and vice versa.

There were a couple of challenges in creating TwoWayCollectionBinding:

  1. What to do about initial synchronization of the two collection. To resolve this challenge, in our implementation we assume that the target collection is empty before the binding and is populated by the elements corresponding to all the elements of the source collection during the binding.
  2. Avoiding a loop when updating the collection. We implement TwoWayCollectionBinding as two one way bindings (_forwardBinding and _reverseBinding). When one of them fires, the other should not be triggered in within the same update. We use OnDoNotReactChangedEvent to achieve that.

There are many binding related issues that were left open in the article and in the current implementation:

  1. Our binding updates are all done in the same thread – current implementation does not have a way to control the thread. 
  2. Complex collection binding connections can lead to the undetected binding loops.
  3. In WPF, bindings can be very elegantly expressed in XAML. Our bindings so far cannot do the same.
  4. WPF bindings can be specified by a path or a name of an element within XAML or an ancestor element within the visual tree. Our bindings, so far cannot do it.

I plan to address all these issues in the future publications.

A great WPF localization package

March 17, 2013


Several months ago I needed to localize a WPF application (it had to have English and German versions). I found an excellent localization package for WPF on the internet and used it for my project. The package was created by Tomer Shamam  and was described at WPF Localization – On-the-fly Language Selection (though the link is no longer available). I published the code for the package (kindly sent to me by Tomer) on github at WPFLocalizationPackage.

It proved to be a great solution allowing to create a German version very fast.

The package is open source, allows switching the locales at run time and also allows localizing any Dependency or Attached properties – not only strings. It provides “Translate” markup extension that can be used from within XAML.

In order to localize an application with the help of this package, you need to create XML catalogs for each of the locales you want your application to support. Here is an excerpt from such catalog that comes with the demo that comes together with the source:

<Dictionary EnglishName="English" CultureName="English" Culture="en-US">
<Value Id="0" FlowDirection="LeftToRight" 
             Title="Demo Window" 
             Width="700" Height="340" />
<Value Id="1" Content="This is a simple text" />
...
<Dictionary>

Each Value tag has an Id attribute used for matching values from the catalogs into XAML or C# code. The rest of the attributes specify WPF object properties and values that those properties should get under the locale.

Here is an example of referring to a catalog value from XAML code:

<Window ...
Title="{loc:Translate Title, Uid=0}"
...
>

Translate markup extension refers to attribute title under Value tag with Id=0.

Mapping between the different cultures and catalogs is done with the help of LanguageDictionary.RegisterDictionary method, e.g.:

LanguageDictionary.RegisterDictionary(
CultureInfo.GetCultureInfo("en-US"),
new XmlLanguageDictionary("Languages/en-US.xml"));

LanguageDictionary.RegisterDictionary(
CultureInfo.GetCultureInfo("he-IL"),
new XmlLanguageDictionary("Languages/he-IL.xml"));

maps culture “en-US” into en-US.xml catalog file under Languages folder while culture “he-IL” is mapped into he-IL.xml file

Here is the code to change localization catalog at run time:

if (LanguageContext.Instance.Culture == CultureInfo.GetCultureInfo("he-IL"))
{
LanguageContext.Instance.Culture = CultureInfo.GetCultureInfo("en-US");
}
else
{
LanguageContext.Instance.Culture = CultureInfo.GetCultureInfo("he-IL");
}

The demo contains an application that can switch between English and Hebrew locales. Here is how the English version looks:

LocaleAppEnglish

And here is its Hebrew counterpart:

LocaleAppHebrew

You can switch between English and Hebrew by pressing the button with the corresponding flag. As you can see not only strings, but also sizes and (even more impressively) the FlowDirection changes when the locale is switched.

Please find more info at the WPF Localization – On-the-fly Language Selection and by browsing the demo code.