Windows 8, Microsoft and the Start Button

May 26, 2013

Windows 8, Microsoft and the Start Button

I’ll start with a pre-school joke which suddenly seems very relevant:

An old timer patient of a mental hospital is showing the facilities to the newcomers – here is our pool – and they see a pool without any water, people jumping into it and getting hurt. They told us, if we behave, they’ll even put in some water – he continues.

According to With Windows Blue, Microsoft may (finally) do the right thing article, at the next major Build conference Microsoft will unveil Windows Blue (a Windows 8 upgrade) which will (according to unconfirmed rumors) restore the start button and menu for the desktop. Apparently Microsoft finally decided that its users behaved well and it is time to put the water back into the pool.

Here I created a list of other things I’d recommend Microsoft to restore in order to regain its dominant position in industry and confidence with its users and developers.

  • Return the dominance to your .NET managed development technology. There was a lot of talk in recent years that Microsoft switched its priority to JavaScrip+HTML on one side and the native C++ development on the other. The thing is that C#+WPF+XAML technology is considerably more robust and powerful than JavaScrip+HTML. And regarding C++, even though it is now very powerful with new Lambda expressions, super-templates and multiple inheritance (yes, I like multiple inheritance), it is very slow to compile. .NET is the best of both worlds with tremendous power and fast compilation.
  • Microsoft made a very big error in underestimating the potential of the smart phones and tablets and getting to the market too late. .NET and Silverlight are not to blame for this – they were actually the best that Microsoft came up with.
  • In order to catch up with its competitors in mobile markets, Microsoft has to come up with better products and lower prices. At this point, however, Microsoft’s mobile products are as expensive as iOS and more expensive than Android based products. As for the quality of products, Microsoft platform needs more applications. At this point, Apple and Android are far ahead in terms of the number of applications available for them.
  • Microsoft’s new RT platform has a lot of restrictions on building the re-usable components (analogous to dll files). In order to force JavaScript compatibility, they do not allow to declare public custom classes or types within such components. From my viewpoint this is a very bad restriction that makes it much more difficult to create good code. My advice is to drop them allowing the developers to produce the code not necessarily callable from JavaScript.
  • Allow to build Windows RT desktop applications (at this point, only a few built-in applications can run in Desktop mode on Windows RT, and no desktop applications can be built for it by the developers).
  • Remove restrictions of the Windows Store, allow people to download whatever application they want on their mobile device. What worked for an industry leader (Apple) might not work for those who are catching up. Google understood it, perhaps Microsoft should follow Android model.

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.

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);
}

Expression based Property Getters and Setters

April 28, 2013


Many times I need to get or set properties on a class dynamically, i.e.
not knowing their exact names at the compile times. Usually I was doing it
using System.Reflection API’s PropertyInfo
class. This class provides GetValue() and
SetValue methods that allow extrating or setting
a value of a C# property based on the the propertie’s name.
The problem with this approach is that accessing a property dynamically
using reflection API is very slow in comparison to accessing it
via usual static API – in my tests the difference was more than 60-fold.

I thought about using LINQ’s expression trees, instead. Nice thing about the
expression trees is that they can be compiled in a way very similar to
static compilation. It turned out that there are already examples of
Expression getters and setters available on the internet e.g. from
Using expression trees to get property getter and setters and Creating a property setter delegate.

Based on the code described at the above URL, I built my own little
Expression based getter and setter library:

// returns property getter
public static Func<TObject, TProperty> GetPropGetter<TObject, TProperty>(string propertyName)
{
    ParameterExpression paramExpression = Expression.Parameter(typeof(TObject), "value");

    Expression propertyGetterExpression = Expression.Property(paramExpression, propertyName);

    Func<TObject, TProperty> result =
        Expression.Lambda<Func<TObject, TProperty>>(propertyGetterExpression, paramExpression).Compile();

    return result;
}

// returns property setter:
public static Action<TObject, TProperty> GetPropSetter<TObject, TProperty>(string propertyName)
{            
    ParameterExpression paramExpression = Expression.Parameter(typeof(TObject));

    ParameterExpression paramExpression2 = Expression.Parameter(typeof(TProperty), propertyName);

    MemberExpression propertyGetterExpression = Expression.Property(paramExpression, propertyName);

    Action<TObject, TProperty> result = Expression.Lambda<Action<TObject, TProperty>>
    (
        Expression.Assign(propertyGetterExpression, paramExpression2), paramExpression, paramExpression2
    ).Compile();

    return result;
}

I also did some benchmarking comparing the speed of these getters and setters to those of

  1. Direct statically compiled code setting and getting the properties
  2. Statically compiled lambdas
  3. Reflection based property getting and setting

Here are the results of running the getters and setters on 100000000 different objects with
string properies:

Getters

Time (seconds) Getter Type
0.4 Direct Statically Compiled
0.64 Statically Compiled Lambda
2.0 Compiled Expression based Getter
36.5 Reflection based Getter

Setters

Time (seconds) Setter Type
0.7 Direct Statically Compiled
1.0 Statically Compiled Lambda
2.4 Compiled Expression based Setter
50.6 Reflection based Setter

You can see, that even though the dynamically compiled expressions are 3-5 times slower than
statically compiled direct methods and 2-3 times slower than statically compiled lambdas,
they are 18-20 times faster than Reflection based approach.

The code for the demo is located under CompiledExpressionTests.zip

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 is described at WPF Localization – On-the-fly Language Selection

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.

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

Silverlight 2.0 In Examples: Part ? Drag and Drop Inside Out

October 7, 2008

Introduction

This is a continuation of a tutorial, see Silverlight 2.0 In Examples: Part 0. Introduction” and “Silverlight 2.0 In Examples: Part 1. Silverlight Elements: Panels and Controls.

Since recently I’ve been working on Silverlight Drag and Drop, I decided to break the continuity of this tutorial and skip several parts, writing right away about how to implement Drag and Drop in Silverlight. In addition to information from the previous sections of the tutorial, this part requires some knowledge of DataTemplates and binding (I will give brief explanations of both).

The article that started me on Silverlight 2.0 Drag and Drop can be accessed via the following link: Drag and Drop in Silverlight. At the bottom of the article you can find a link to download the source code.

Here, however, I go over Drag and Drop with more details and examples. A special feature of this article is a Drag and Drop custom control designed to absorb most of the Drag and Drop complexity. Based on this control, I created an example functionally similar to the one described in Drag and Drop in Silverlight.

Silverlight demos, including those corresponding to the samples presented here can be found at AWebPros Demos.

Simple Silverlight Drag and Drop Example

Here is the screen capture of the first example:

One can drag and drop the red circle anywhere within the Silverlight application area.
The source code for this sample can be downloaded from simpledragdropzip.doc. As always, please remove .doc extension, rename the file to simpledragdrop.zip and then open it as a zip file.
Below the code of the sample is explained in detail.
Here are the contents of Page.xaml file:

<UserControl

    x:Class=”SimpleDragDrop.Page”

    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;

    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;

    Background=”Yellow”

    Width=”400″

    Height=”300″>

    <UserControl.Resources>

        <DataTemplate x:Key=”Circle”>

            <Ellipse Width=”20″ Height=”20″ Fill=”Red”></Ellipse>

        </DataTemplate>

    </UserControl.Resources>

    <Grid x:Name=”LayoutRoot” Background=”White”>

        <Popup x:Name=”MyPopup”IsOpen=”False”>

            <ContentControl

   ContentTemplate=”{StaticResource Circle}”

   Opacity=”0.5″/>

        </Popup>

        <ContentControl

            ContentTemplate=”{StaticResource Circle}”

            x:Name=”MyControlToMove”>

        </ContentControl>

    </Grid>

</UserControl>
The object that we are dragging and dropping is ContentControl at the very bottom of the XAML file. Its name is “MyControlToMove”.

ContentControl is a control that has two major properties: Content (which contains some data) and ContentTemplate (which specifies how to present this data).

In our case the presentation of MyControlToMove is not data dependent (Content property does not play any role). This presentation is determined only by the DataTemplate which is defined as a resource called “Circle” within UserControl.Resources section. In this example this ContentControl is always displayed as a red circle.
Another control is used as a drag cursor to show where the circle is dragged. It is represented by a similar red circle with its opacity property set to 0.5, making it semitransparent. This control is of Popup type.

Now, let us deconstruct the C# code. While XAML contains mostly design and static information, C# carries information about actions. There are 3 main actions within the Drag and Drop process:

  • Drag beginning – occurs when the left mouse button is pressed on a draggable object.
  • Drag process – occurs when the mouse pointer is moved with the left mouse button still pressed.
  • Drop – occurs when the left mouse button is released.
  • Correspondingly, we have 3 event handlers for 3 events:

  • MouseLeftButtonDown – to handle start of the drag process
  • MouseMove – to handle visual moving of the dragged item
  • MouseLeftButtonUp – to handle drop operation
  • All of the events are registered with the top level panel “LayoutRoot”. This is possible because of the event “Bubbling”. Even if a child of “LayoutRoot” panel is clicked, the event eventually “bubbles” up to it, unless it is handled before.
    Here is how we set the event handlers within the application:

    LayoutRoot.MouseLeftButtonDown +=

        new MouseButtonEventHandler(LayoutRoot_MouseLeftButtonDown);

    LayoutRoot.MouseMove +=

        new MouseEventHandler(LayoutRoot_MouseMove);

    LayoutRoot.MouseLeftButtonUp +=

        new MouseButtonEventHandler(LayoutRoot_MouseLeftButtonUp);

     

    Now let us describe these 3 operations in detail.

    Starting the Drag Operation

    Starting the drag operation is handled by the function LayoutRoot_MouseLeftButtonDown which in turn calls StartDragDrop.

    Here is the code for LayoutRoot_MouseLeftButtonDown function:

    void

    LayoutRoot_MouseLeftButtonDown(object sender,

                                                   MouseButtonEventArgs e)

    {

        // obtain all UI elements at the

        // current mouse pointer location

        List<UIElement> elements =

           (List<UIElement>)this.HitTest(e.GetPosition(null));

     

        // get the first element of type Ellipse and

        // start drag operation on it.

        foreach (UIElement element in elements)

        {

            if (element is Ellipse)

            {

                StartDragDrop(element, e);

                break;

            }

        }

    }

    First HitTest gets all the elements “pierced” by the current mouse pointer. Then we iterate over each of of the elements, find the “Ellipse” (this is our circle we want to move) and start drag operation on it by calling StartDragDrop function.

    Here is the StartDragDrop function code:

    private void

    StartDragDrop(UIElement element,

                  MouseButtonEventArgs e)

    {

        // make the popup visible

        MyPopup.IsOpen = true;

     

        // make the mouse events connected to

        // the popup

        MyPopup.CaptureMouse();

     

        // figure out the mouse coordinates at the onset

        // of Drag operation.

        _horisontalOffset = e.GetPosition(null).X;

        _verticalOffset = e.GetPosition(null).Y;

     

        // set _captured flag to true

        // (this is to check later if drag drop

        //  operation is in progress)

        _captured = true;

     

        // move the popup to the current mouse location.

        MyPopup.HorizontalOffset = _horisontalOffset;

        MyPopup.VerticalOffset = _verticalOffset;

    }

    The StartDragDrop functionality is explained in the comments within its code.

    Drag Operation During the Mouse Move

    Here is how we implemented Drag operation when mouse moves:

    void

    LayoutRoot_MouseMove(object sender,

                         MouseEventArgs e)

    {

        // if no drag and drop started,

        // we do not need to do anything.

        if (!_captured)

            return;

     

        // update the popup location to the

        // current mouse pointer location.

        MyPopup.HorizontalOffset = e.GetPosition(null).X;

        MyPopup.VerticalOffset = e.GetPosition(null).Y;

    }

    All we need to do is to move the Drag popup to the current location of the mouse pointer. 

    Drop Operation

    Finally, here is the function in charge of Drop operation:

    void

    LayoutRoot_MouseLeftButtonUp(object sender,

                                 MouseButtonEventArgs e)

    {

        // if drag is not started we do not need

        // any drop functionality to execute

        if (!_captured)

            return;

     

        // mouse capture is released

        MyPopup.ReleaseMouseCapture();

     

        // popup becomes invisible

        MyPopup.IsOpen = false;

     

        // set captured flag to false

        // (no drag operation in progress)

        _captured = false;

     

        // the rest of the code just moves

        // our content control to the new location

        // using TranslateTransform

        GeneralTransform gt =

            this.TransformToVisual(MyControlToMove);

     

        PointstartPoint = gt.Transform(new Point(0, 0));

     

        Pointp = e.GetPosition(null);

     

        TranslateTransformtt = new TranslateTransform();

     

        tt.X = p.X – _horisontalOffset – startPoint.X;

        tt.Y = p.Y – _verticalOffset – startPoint.Y;

     

        MyControlToMove.RenderTransform = tt;

    }

    As you can see, we stop the DragDrop operation by releasing the mouse capture, making the Drag popup invisible and setting _captured flag to false. Then we do the actual drop operation by moving the original dragged control to the new location using TranslateTransform.

    Drag and Drop with Forbidden Area

    Now, let us consider a more complicated example.
    In addition to the previously discussed functionality it has the following:

  • Area in which it is forbidden to drop.
  • A special template for the Drag popup to appear when the mouse pointer is in the area in which it is forbidden to drop.
  • The drag operation does not start right away, but only when the mouse is far enough from the origin.
  • Here is the screen capture for the example:

    The yellow circle signifies the area where the drop is allowed. Outside of it, the drop is forbidden.
    Here is the code for the example: dragdropwithforbiddenareazip.doc.
    As one can see from the code, the capture process now begins during MouseMove action and only when the distance between the original and current locations of the mouse is greater than _captureRadius:

    private void BeginCapture(MouseEventArgs e)

    {

        // check if the mouse pointer position

        // within _captureRadius

        double diffX =

            e.GetPosition(null).X – _horisontalOffset;

        double diffY =

            e.GetPosition(null).Y – _verticalOffset;

     

        // if it is within _captureRadion,

        // do not start capture

        if ((diffX * diffX + diffY * diffY) <

            _captureRaduis * _captureRaduis)

        {

            return;

        }

     

        // make popup visible

        MyPopup.IsOpen = true;

     

        // capture mouse

        MyPopup.CaptureMouse();

     

        // set _captured flag to true.

        _captured = true;

    }

    There is also a function InAllowedArea that returns true if the mouse pointer is within an area in which we are allowed to drop and false otherwise:

    // checks if drop is allowed

    // at the current location of the

    // mouse pointer.

    bool InAllowedArea(MouseEventArgs e)

    {

        Point p = e.GetPosition(null);

        IEnumerable<UIElement> hitTestResult =

      AllowedArea.HitTest(p);

     

        // see if mouse pointer hits AllowedArea

        // if yes, return true,

        // if no, return false.

        return(hitTestResult.Count() != 0);

    }

    Then, during the Drag process, we check if we are within the area in which we are allowed to drop and set the ContentTemplate of the PopupControl correspondingly:

    if(InAllowedArea(e))

    {

        // if we are in an area

        // in which we are

        // allowed to drop

        // set the template accordingly

        // to our Circle

        PopupControl.ContentTemplate = CircleTemplate;

    }

    else

    {

        // if we are in an area in which it

        // is forbidden to drop, set

        PopupControl.ContentTemplate = DropForbidden;

    }

     

    Generic Drag and Drop Control

    Based on the above examples and also taking into account that the Drag popup display can be data driven (as will be shown later) I came up with a generic Drag/Drop control implementation. While it is still rather complex to use, since drag and drop is a complex operation, it also absorbs a lot of complexity into itself, eliminating the need to implement and debug a large chunk of the Drag/Drop functionality over and over again.

    Here is the code for generic Drag/Drop control together with a couple of samples showing how to use it: genericdragdropzip.doc.

    DragDrop control is defined within GenericDragDropLib project within DragDropControl.cs file. The generic.xaml file contains default control template for DragDropControl.
    DragDropControl contains a number of properties and events that allow customization of the Drag/Drop functionality. Here is the list of these properties and events with the explanations as to why they are needed.

    // mouse is captured and the popup

    // indicating the beginning of Drag

    // operation to the user becomes

    // visible on when the distance between

    // the mouse pointer and the original

    // point when the mouse button was pressed

    // during the Drag operation is

    // greater than CaptureRadius.

    public doubleCaptureRadius { get; set; }

     

    // the popup to show during Drag operation

    public Popup DragDropPopup { get; set; }

     

    // The content control within the DragDropPopup

    // that can assume any shape defined by

    // its data template and date content.

    public ContentControl PopupContentControl { get; set; }

     

    // default data template for areas in

    // which drop is allowed

    public DataTemplate DropAllowedTemplate { get; set; }

     

    // data template for areas in which

    // drop is forbidden

    public DataTemplate DropForbiddenTemplate { get; set; }

     

    // element to be dragged

    public UIElementDraggedElement { get; set; }

     

    // dragged business logic object

    // (specified by Content property of DraggedElement)

    public objectDraggedObject { get; set; }

    // DragContainer property is used when DraggedElement is

    // one of the items within and ItemsControl e.g. a

    // ListBox this property contains the reference to this

    // container control of the dragged item

    public UIElementDragContainer {get; set;}

     

    // does the drop operation

    public event DoDropDelegateDoDrop = null;

     

    // used to filter in the element that can be

    // dragged

    public event IsDraggableDelegateIsDraggable = null;

     

    // used to filter in the container of the element

    // that can be dragged

    public event IsContainerDelegate IsDragContainer = null;

     

    // returns true if, during the drag operation,

    // the mouse pointer is inside the area

    // it which drops are allowed, false otherwise.

    public event IsInAllowedAreaDelegateIsInAllowedArea = null;

     

    // returns data template for the case when the drops are

    // allowed during the drag operation

    public event GetDataTemplateDelegate GetDataTemplate = null;

     

    //used to set the DraggedObject from the

    // DraggedElement.

    // Most of the times, this is just DraggedElement.Content

    public event GetBusinessLogicObjectDelegate

        GetBusinessLogicObject = null;

     

    // used to record the origin of the drag operation

    public Point StartDragPoint { get; set; }

    DragDropControl also contains three functions that need to be triggered by the Button Down, Mouse Move and Button Up events of the application that uses DragDropControl. These functions are

  • StartDragDrop
  • OnMove
  • OnButtonUp
  • Below we describe two examples using DragDropControl.

    Drag Drop with Forbidden Area Implemented Using DragDropControl

    The solution for this test is called GenericDragDropTest.sln and it is located under GenericDragDropTest within genericdragdrop.zip file. It produces exactly the same result as our Drag/Drop with forbidden area example above, but it uses DragDropControl. Below we show how DragDropControl is used.
    Here is the code showing how we connect the events of DragDropControl:

    MyDragDropControl.DoDrop +=

        new GenericDragDropLib.

            DoDropDelegate(MyDragDropControl_DoDrop);

     

    // we only drag ellipses!

    MyDragDropControl.IsDraggable +=

        delegate(UIElement element)

        {

            if (element is Ellipse)

                return true;

            return false;

        };

     

    // data template for the drag popup is

    // provided by CircleTemplate resource

    MyDragDropControl.GetDataTemplate +=

        delegate(UIElement element)

        {

            return (DataTemplate) this.Resources["CircleTemplate"];

        };

     

    // we are in an area in which are

    // are allowed to drop if the

    // mouse pointer is

    // inside AllowedArea circle.

    MyDragDropControl.IsInAllowedArea +=

        delegate(Point p)

        {

            IEnumerable<UIElement> hitTestResult =

                AllowedArea.HitTest(p);

            return(hitTestResult.Count() != 0);

        };

    And here is the code that connects the mouse button events to the DragDropControl functions:

    // connect the mouse button events to

    // the corresponding functions

    // of our DragDropControl.

    LayoutRoot.MouseLeftButtonDown +=

        delegate(object sender, MouseButtonEventArgs e)

        {

            MyDragDropControl.StartDragDrop(this, e);

        };

     

    LayoutRoot.MouseMove +=

        delegate(object sender, MouseEventArgs e)

        {

            MyDragDropControl.OnMove(e);

        };

     

    LayoutRoot.MouseLeftButtonUp +=

        delegate(object sender, MouseButtonEventArgs e)

        {

            MyDragDropControl.OnButtonUp(e);

        };

    Drag and Drop between Two ListBox Elements

    Here we show an implementation of Drag/Drop analogous to that of Drag and Drop in Silverlight. The ListBoxItem objects are dragged and dropped between two ListBoxes.

    The code for this sample can be found under ListBoxDragDropTest directory of genericdragdrop.zip file.
    Here is the screen capture for this sample:

    This sample also provides an example of having data driven visual presentation of the dragged item (the first and last names of the students provide the data that can change depending on the dragged item).
    Here is the code showing setting the event handlers for DragDropControl events:

    MyDragDropControl.DoDrop +=

        new GenericDragDropLib.DoDropDelegate(DoDrop);

     

    // we only Drag and Drop ListBoxItem objects!

    MyDragDropControl.IsDraggable +=

        delegate(UIElement element)

        {

            if (element is ListBoxItem)

                return true;

            return false;

        };

     

    // our drag container is ListBox

    MyDragDropControl.IsDragContainer +=

        delegate(UIElement element)

        {

            if (element is ListBox)

                return true;

            return false;

        };

     

    // we use the same DataTemplate

    // to display the drag popup as

    // we use to display the items in the list

    MyDragDropControl.GetDataTemplate +=

        delegate(UIElement element)

        {

            ListBoxItemlbi = MyDragDropControl.DraggedElement as ListBoxItem;

     

            if(lbi == null)

                return null;

     

            return (DataTemplate)lbi.ContentTemplate;

        };

     

    // we are in allowed area if and only if we are

    // inside a ListBox

    MyDragDropControl.IsInAllowedArea +=

        delegate(Point p)

        {

            ListBoxlb = GetListBox(p);

            if (lb == null)

                return false;

            return true;

        };

     

    // returns Content property of the ListBoxItem

    MyDragDropControl.GetBusinessLogicObject +=

        delegate(UIElement element)

        {

            ContentControl cc = element as ContentControl;

     

            if (cc == null)

                return null;

     

            return cc.Content;

        };

    One can see that the DoDrop function (called during the drop operation) checks if the target ListBox is not the same as the original ListBox from where the item was dragged and if true, removes the item from the original collection and adds it to the collection of the target ListBox.

    Conclusion

    This article describes the implementation of drag and drop functionality in Silverlight. It starts with a simple example and progresses to more complex ones. It features custom DragDropControl which is used to absorb a lot of complexity of Drag/Drop implementation.

    Silverlight Spy

    September 29, 2008

    By googling for “Silverlight Snoop” (Snoop is a tool for investigating WPF GUI) I came (via jimmangaly.blogspot.com across an interesting tool: Silverlight Spy.

    Make sure you have all prerequisites before installing it.

    Not only it allows you to disassemble and show the composition of your own Silverlight application, but it also allows you to do it to any Silverlight application accessible on the Internet. All you need to do is to type in the url of the page containing that Silverlight application: e.g. I did it for my AWebPros banner typing in “http://awebpros.com/AWebProsMain.aspx&#8221; URL. Then I go to the panel on the right and expand “Silverlight 2 Beta 2 Application (Xaml1)”. Here is the resulting layout:

    Silverlight Spy

    Silverlight Spy

    As you can see, the TextBlock at the top is selected by selecting “textBlock” in the right hand panel!. When I try to select other text blocks, however, they are not shown in the right place – possibly because of the animation. Still it is a very impressive tool.


    Follow

    Get every new post delivered to your Inbox.