Archive for category WPF

Fluent Design System in Windows 10: Aesthetics over Usability?

At the Build 2017 conference, Microsoft revealed upcoming changes to the way applications will be (and can be) designed, introducing their Fluent Design System in the Windows 10 Fall Creators Update. This update focuses on the role which light, depth, motion, material, and scale can play in the design of user interfaces (UIs): really nice and impressive stuff which can certainly be used to improve user experiences. However, given that it has been a recurring theme in UI design to prioritize aesthetics over usability, I want to take a critical look at one of the newly introduced features—reveal highlight.

Reveal uses light to make interactive elements stand out. Light illuminates the interactive element the user can interact with, revealing hidden borders. The light also gently illuminates other interactive elements that are nearby.

… The Reveal behavior does this by revealing the clickable content’s container when the pointer is nearby.

For example, see the difference between the calculator application in Windows 10 and the same calculator using ‘reveal’.

reveal

Certainly an improvement, but at this point I feel it is worthwhile to take a couple more steps back to compare this with what the calculator looked like in Windows 7.

win7-calc

Less pretty, to be sure, but notice in particular how there is no need to hover over the memory buttons to perceive that they can be clicked and where to do so. To me, the UI modifications introduced as part of Windows 8 and 10 are two steps back and ‘reveal’ is one step forward, mitigating some of the earlier mistakes: the power of perceived affordances took a backseat to ‘flat design’, effectively stripping many UI elements of their clarity in how they can be used: where to click, can they be clicked, and what type of element it is. The question I would like to ask is: Should buttons ever look like ordinary labels in the first place?

While it is awesome to have additional development tools available to create more pleasing ‘on hover’ effects, conceptually this is nothing new. From a design perspective, it would still not make sense to require a user to hover over important UI elements to only then be able to interpret what they are. Therefore, at this point I would merely like to highlight that ‘reveal’ with the purpose of revealing functionality should likely be used sparingly, only for non-essential user interface elements. Whether or not the memory buttons in the calculator are ‘important’ (and potential alternate ways of visualizing them) is a different discussion to be had.

As researchers in user interface design know, perceived affordances improve usability. Conversely, I blogged about how the lack of affordances in the window manager of Windows 10 complicates resizing and moving windows around. Ironically, this was demonstrated perfectly by Ashish during his presentation on how to use the Fluent Design System features in XAML, as he spent 32 seconds on resizing a window to its desired size while narrating “Sorry. If this machine cooperates.” and Tim helpfully instructing him that he is “anchoring [the window] too high …”.

The (literal) bottom line of this post: great new stuff in Windows (and XAML), but I hope this post serves as a warning to think of usability first when using the new Fluent Design System features, aesthetics only second.

Advertisements

Leave a comment

Generic TypeConverter for XAML

TypeConverter‘s in WPF are part of the underlying mechanism which allow you to assign values to attributes of complex types within XAML using plain strings. For example, whenever you specify Point‘s.

<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">

Typically, you specify a TypeConverter for a certain type by applying the TypeConverterAttribute to it.

[TypeConverterAttribute( typeof( PointConverter ) )]
public struct Point : IFormattable

Since attribute arguments cannot use type parameters, this prevents you from specifying a generic TypeConverter for a generic class. I came across this issue while implementing a type converter to support specifying instances of my generic Interval class from XAML. The following is not possible.

// attribute argument cannot use type parameters
[TypeConverter( typeof( IntervalTypeConverter<T, TSize> ) )]
public class Interval<T, TSize>

However, you can write a non-generic TypeConverter which is capable of converting strings to several different target types. When using XAML you can obtain a IDestinationTypeProvider service through the context which is passed to the ConvertFrom method. From here you can retrieve the fully specified target type, including generic type parameters. Through reflection you can then call a Parse method on the specific type to take care of initializing an instance of the desired type. An example for Interval can be found in my library.

public override object ConvertFrom(
    ITypeDescriptorContext context,
    CultureInfo culture,
    object value )
{
    var typeProvider =
      (IDestinationTypeProvider)context.GetService( typeof( IDestinationTypeProvider ) );
    Type targetType = typeProvider.GetDestinationType();

    // ... convert to desired target type using a parsing method

    return base.ConvertFrom( context, culture, value );
}

However, it is important to note that this type provider will only work for XAML, since the IDestinationTypeProvider service is only provided by XAML’s ServiceProviderContext. It is thus not desirable to add this TypeProvider to types which work independent from XAML, like my Interval class. In addition this would require referencing the System.Xaml assembly.

How then to make XAML use this type provider without applying the attribute to the type definition? One option is applying the TypeConverter attribute on a per-property basis.

The per-property type converter technique is particularly useful if you choose to use a property type from Microsoft .NET Framework or from some other library where you cannot control the class definition and cannot apply a TypeConverterAttribute there.

However, this implies a lot of redundancy, having to apply the attribute to every property of that specific type. Using TypeDescriptor.AddAttributes() you can assign a TypeConverter at runtime.

TypeDescriptor.AddAttributes(
  typeof( Interval<,> ),
  new TypeConverterAttribute( typeof( IntervalTypeConverter ) ) );

Any subsequent TypeDescriptor.GetConverter() call will then return the converter for the specified type. Unfortunately this does not work for XAML, since XAML does not seem to take component modifications at runtime into account. Therefore, in order for this to work, we need to implement this runtime behavior ourselves. Recall that XAML does load TypeConverter‘s specified in TypeConverterAttribute‘s. We can thus use a special type converter which redirects its implementation to a converter loaded through TypeDescriptor to hook into XAML’s type conversion runtime. I implemented a RedirectTypeConverter which can be used as a base class for this exact purpose. Each of its methods first ensures the converter is initialized using TypeDescriptor, and then redirects the call to this converter. When TypeDescriptor.GetConverter( _type ) returns the redirecting type converter itself, this means no converter was specified using TypeDescriptor, hence no conversion is supported for this type.

protected RedirectTypeConverter( Type type )
{
	_type = type;
}

public override object ConvertFrom(
	ITypeDescriptorContext context,
	CultureInfo culture,
	object value )
{
	InitializeConverter();
	return _converter.ConvertFrom( context, culture, value );
}

public void InitializeConverter()
{
	if ( _converter != null )
	{
		return;
	}

	_converter = TypeDescriptor.GetConverter( _type );
	if ( _converter.GetType() == GetType() )
	{
		string message = string.Format(
		  "Conversion failed. Converter for {0} is missing in TypeDescriptor.", _type );
		throw new InvalidOperationException( message );
	}
}
class RedirectIntervalTypeConverter : RedirectTypeConverter
{
	public RedirectIntervalTypeConverter()
		: base( typeof( Interval<,> ) )
	{
	}
}

Applying this converter using TypeConverterAttribute to generic types thus allows redirecting type conversion to a converter which supports multiple target types in environments which provide information about the target type (like XAML using IDestinationTypeProvider). You only need to add the converter once, and it will be supported for all of your dependency properties using them.

TypeDescriptor.AddAttributes(
  typeof( Interval<,> ),
  new TypeConverterAttribute( typeof( IntervalTypeConverter ) ) );

2 Comments

Aspect powered WPF

In some of my first posts – as it turns out I can almost celebrate one year of blogging! – I wrote about a factory approach to solve the complexities and overhead of creating dependency properties (DPs) for a WPF control; and notify properties and commands for a viewmodel. Both are essential parts when using WPF and following the MVVM pattern. To summarize: the approach was basically to delegate the creation of these complex components to a factory contained within the class which uses annotations on fields (attributes) to clarify what should be created. To create DPs, this looked as follows:

public class HelloWorldControl : UserControl
{
    [Flags]
    public enum Properties
    {
        Hello,
        World
    {

    static readonly DependencyPropertyFactory<Properties> PropertyFactory
        = new DependencyPropertyFactory<Properties>( false );

    [DependencyProperty( Properties.Hello )]
    public string Hello
    {
        get { return (string)PropertyFactory.GetValue( this, Properties.Hello ); }
        set { PropertyFactory.SetValue( this, Properties.Hello, value ); }
    }

    [DependencyProperty( Properties.World )]
    public string World
    {
        get { return (string)PropertyFactory.GetValue( this, Properties.World); }
        set { PropertyFactory.SetValue( this, Properties.World, value ); }
    }
}

Nice and concise, but as mentioned in my conclusion there is still room for improvement:

  • Requirement of an enum.
  • Having to manually add the factory to the class.
  • Every property has almost the exact same implementation.

As it turns out, PostSharp is the perfect candidate to leverage the concept of Aspect Oriented Programming (AOP) to solve the last two problems, resulting in the following solution:

[WpfControl( typeof( Properties ) )]
public class HelloWorldControl : UserControl
{
    [Flags]
    public enum Properties
    {
        Hello,
        World
    {

    [DependencyProperty( Properties.Hello )]
    public string Hello { get; set; }

    [DependencyProperty( Properties.World )]
    public string World { get; set; }
}

Where does the magic happen?

Simply put, PostSharp does a post-compilation step, inserting the required code where needed. Which code needs to be inserted where is determined by applying aspects (exposed as attributes) to the relevant elements. The WpfControlAttribute in the example above applies an aspect to HelloWorldControl. PostSharp makes it relatively easy by allowing you to implement these aspects by using plain C# classes. It’s a mature framework with an extensive feature set as will become evident from the following more in-depth description.

A core used feature in the implementation is the ability to dynamically ‘provide’ aspects to the elements of your choice. The solution actually is composed of 2 aspects, WpfControlAspect and DependencyPropertyAspect, being applied to the user control and the dependency properties respectively.

  1. The WpfControlAttribute is actually an IAspectProvider, creating a WpfControlAspect and applying it to its target (HelloWorldControl in the example). This extra step is only required for generic aspects as a workaround since C# doesn’t support generic attributes. The generic type arguments are passed as an argument to the attribute, and reflection is used to instantiate the actual generic aspect.
  2. The WpfControlAspect introduces the factory into the user control, and in its turn provides a DependencyPropertyAspect to all members which have the DependencyPropertyAttribute applied to them.
  3. The aspects applied to the properties create the correct call to the DependencyPropertyFactory, where the actual logic is implemented.

This solution represents a personal guideline I prefer to follow when writing aspects.

Only resort to using aspects after applying encapsulation to its fullest extent.

It’s a gut feeling I have, and I can’t quite formulate thorough arguments for it yet. When I can, I’ll be sure to write about it! Perhaps the main advantage is you are less dependant on aspects, and let’s face it, minimizing dependencies is almost always a good thing. Basically I prefer to rely on .NET and its excellent debugging and testing tools as much as possible, and only use PostSharp where .NET fails to satisfy my DRY needs.

Why still use enums?

As explained before, they are a necessary replacement to identify the associated element which is created. They aren’t all that bad. As I will demonstrate in a next post, the enums can even be put to use in some interesting use cases. If you can’t wait, all source code and a particularly interesting unit test is already available for you to try out. If you haven’t installed PostSharp 2.1 RC2 or higher yet, you will need it! Actually I already discussed another use case in a previous post: binding from XAML to a command in the viewmodel by using a custom ‘CommandBinding‘ markup extension and passing the enum as a parameter.

It could be worthwhile to investigate an opt-in approach where only those elements which need to be identified from elsewhere need to be assigned an ID. At first sight it looks like the limitations for attribute arguments are a big deal breaker.

You’re breaking the conventions!

The only convention I am still breaking is that I’m not adding the DependencyProperty fields. As discussed before, I see no need why these are required. The sole stated problem is that tools could rely on this convention to access the properties. Opening a simple user control enhanced with aspect goodiness shows that both Blend and the Visual Studio designer work as expected. That’s good enough for me!

3 Comments

ViewModel Property and Command Factory

If you are familiar with the MVVM pattern, often used in WPF/XAML, you probably know what a viewmodel should look like. These classes get quite big pretty quickly. Considering that they are mainly just an adapter on your model, to be accessed by your view, they contain a lot of duplicate code. Wherever you read “duplicate”, there most likely exists a cleaner solution, so I’ll cut to the chase. What follows are two code samples with the same behavior. In the second sample I use a factory to minimize the required code. This approach has additional advantages as well as I’ll explain later.

Let’s make a ViewModel to edit this rubber duck! (This might sound familiar to you if you have read Head First’s great book on design patterns.)

Traditional implementation:

public class DuckViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private Duck m_duck;

    private bool m_canQuack;
    public bool CanQuack
    {
        get { return m_canQuack; }
        set
        {
            m_canQuack = value;
            RaisePropertyChanged("CanQuack");
        }
    }

    private Color m_color;
    public Color Color
    {
        get { return m_color; }
        set
        {
            m_color = value;
            RaisePropertyChanged("Color");
        }
    }

    private RelayCommand m_quackCommand;
    public ICommand QuackCommand
    {
        get { return m_quackCommand; }
    }

    private RelayCommand m_saveCommand;
    public ICommand SaveCommand
    {
        get { return m_saveCommand; }
    }

    public DuckViewModel(Duck duck)
    {
        m_duck = duck;
        CanQuack = duck.CanQuack;
        Color = duck.Color;

        m_quackCommand = new RelayCommand(() => Quack(), () => CanQuack());
        m_saveCommand = new RelayCommand(() => Save());
    }

    public void RaisePropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyEventArgs(property));
        }
    }

    public void Quack()
    {
        m_duck.Quack();
    }

    public void CanQuack()
    {
        return m_duck.CanQuack;
    }

    public void Save()
    {
        m_duck.CanQuack = CanQuack;
        m_duck.Color = Color;
    }
}

Phew, that’s a whole lot to write just for two properties and two commands isn’t it? Let’s try improving this.

Factory approach:

public enum Properties { CanQuack, Color }
public enum Commands { Save, Quack }

public class DuckViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private readonly NotifyPropertyFactory<Properties> m_properties;
    private readonly CommandFactory<Commands> m_commands;

    private Duck m_duck;

    [NotifyProperty(Properties.CanQuack)]
    public bool CanQuack
    {
        get { return (bool)m_properties.GetValue(Properties.CanQuack); }
        set { m_properties.SetValue(Properties.CanQuack, value); }
    }

    [NotifyProperty(Properties.Color)]
    public Color Color
    {
        get { return m_properties.GetValue(Properties.Color) as Color; }
        set { m_properties.SetValue(Properties.Color, value); }
    }

    public DuckViewModel(Duck duck)
    {
        m_duck = duck;
        CanQuack = duck.CanQuack;
        Color = duck.Color;

        m_properties = new NotifyPropertyFactory<Properties>(this, PropertyChanged);
        m_commands = new CommandFactory<Commands>(this);
    }

    [CommandExecute(Commands.Quack)]
    public void Quack()
    {
        m_duck.Quack();
    }

    [CommandCanExecute(Commands.Quack)]
    public bool CanQuack()
    {
        return m_duck.CanQuack;
    }

    [CommandExecute(Commands.Save)]
    public void Save()
    {
        m_duck.CanQuack = CanQuack;
        m_duck.Color = Color;
    }
}

There already exist dozens of other solutions to simplify (and improve) implementing INotifyPropertyChanged. One approach is to use a base class. I prefer the factory approach, following the design principle.

Favor composition over inheritance.

To remove the literals from the PropertyChanged call lambda’s can be used. Because my approach uses reflection, the literal isn’t a problem anymore, and is traded for an enum value.

Besides solving the previously mentioned problems, the factory approach has additional advantages:

  • No more private field members required for the properties, just one for the factory.
  • As an advantage of the factory design, the view model doesn’t need to know about concrete implementations. Behavior can be added/changed inside the factory.
  • As you might have noticed, no more command members! All the commands are contained within the command factory. Yes, you can still magically bind to them, which I’ll explain in a bit!

How it works:

You might notice the similarity with my previously posted dependency property factory. I refactored the latter, and all three factories (commands, notify property and dependency property) use the same abstract base class AbstractEnumSpecifiedFactory<T>, which already handles a lot of the required behavior by using reflection. It links MemberInfo objects to the desired attributes. Concrete implementation decide which attributes it needs, and what to do with them.

To be able to still bind to the commands I created a custom Markup Extension for XAML, allowing me to do the following.

<Button Command="{m:CommandBinding {x:Static Binding:Commands.Quack}}" Content="Quack" />

This has another additional advantage that binding is done in a safe way. The CommandBinding extension uses -you guessed it- reflection to get the correct command out of the CommandFactory in the data context.

While creating the CommandBinding extension I prepared myself to optionally create a custom general Binding extension, so that the naming conventions for dependency properties can safely be ignored, and the useless property fields can be removed.

Source code can be found in my FCL Extension library in the Whathecode.PresentationFramework assembly. The NotifyPropertyFactory is located in Whathecode.System.ComponentModel.NotifyPropertyFactory and the CommandFactory is located in Whathecode.System.Windows.Input.CommandFactory.

1 Comment

Dependency Property Factory – Part 3

This post is a second follow-up to an earlier attempt to simplify creating dependency properties. In the previous follow-up I discussed unanswered questions about the WPF dependency property system which prevented me from continuing the implementation.

First of all, I would like to thank Einar Ingebrigtsen for helping me out on some of the following issues. He has a solution of his own inside the open source Balder project.

The answers to the questions:

“Does anyone know concrete examples of problems caused by not following the convention of naming the CLR property wrapper the same as the dependency property, or in other words, why is it of any importance?”

External tools may use this convention to access the dependency properties. I would argue these tools could be made smart enough to solve this without the convention, but since my proposed solution doesn’t require passing this name anymore at all, this is not an issue anymore.

“Why can I still use the dependency properties through XAML, without adding the field identifiers that end with the suffix ‘Property’?”

The XAML processor doesn’t use these identifiers directly, as the documentation on msdn might make you believe. However, again external tools, or future versions may follow this convention, so let’s assume it is required. Since I don’t own/use any of these tools I can’t verify this. Of real importance is the necessity for the properties to be registered in a static context. Luckily this makes the factory approach still a viable option.

The solution!

Taking all this new information into consideration, this is the best I could come up with:

public class FactoryExample : DependencyObject
{
        public enum Property
        {
            Standard,
            ReadOnly,   // This becomes a readonly property.
            Callback    // This property has callbacks assigned to it.
        }
        private static readonly DependencyPropertyFactory<Property> m_properties =
            new DependencyPropertyFactory<Property>();

        public static readonly DependencyProperty StandardProperty =
            m_properties[Property.Standard];
        public static readonly DependencyProperty ReadOnlyProperty =
            m_properties[Property.ReadOnly];
        public static readonly DependencyProperty CallbackProperty =
            m_properties[Property.Callback];

        [DependencyProperty(Property.Standard, DefaultValue="foo")]
        public string Standard
        {
            get { return m_properties.GetValue(this, Property.Standard) as string; }
            set { m_properties.SetValue(this, Property.Standard, value); }
        }

        [DependencyProperty(Property.ReadOnly)]
        public bool ReadOnly
        {
            get { return (bool)m_properties.GetValue(this, Property.ReadOnly); }
            private set { m_properties.SetValue(this, Property.ReadOnly, value); }
        }

        [DependencyProperty(Property.Callback)]
        public int Callback
        {
            get { return (int)m_properties.GetValue(this, Property.Callback); }
            set { m_properties.SetValue(this, Property.Callback, value); }
        }

        [DependencyPropertyChanged(Property.Callback)]
        public static void OnChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
        {
            ...
        }

        [DependencyPropertyCoerce(Property.Callback)]
        public static object OnCoerce( DependencyObject d, object value )
        {
            ...
        }
}

As you might notice, not too many things have changed since the first post, but besides the advantages mentioned earlier, there are a couple of new features.

  • The owner type for the factory is automatically set to the outer class of the passed template parameter. You can still pass the type manually.
  • Exceptions are (optionally) thrown when the conventions aren’t followed. Thanks to the exceptions I actually found out one of my CLR property wrappers was set to protected (public is required), indicating a design flaw.
  • Behaviour of get and set is encapsulated inside the factory. (E.g. No need to know whether a dependency property is read only when using a private setter.)
  • Safe for obfuscation. (Before ID.ToString() was used, where ID was the enum value. Now the property name is used and the enum value is solely used to link things together.)

If you are anything like me, looking at the code you might think “This can still be improved!“. Unfortunately it looks like we reached the limitations of C#. What follows are some failed ideas I considered.

Requirement for an enum:

Why specify an enum, right? We already have the properties, why not use those as ID’s? In Einar’s implementation an expression tree is used as a way to represent the property by using a lambda expression, returning the property itself. (E.g. o => o.Standard) Unfortunately, expression trees can’t be passed as an argument to Attributes, required by the factory. Why? My guess is, “No particular reason.

AbstractDependencyObject:

Why not have an abstract class implement the factory by default? A default GetValue() and SetValue() method could be added, so “m_properties.GetValue(this, Property.Standard)” would be reduced to “GetValue(Property.Standard)”. Such an implementation would quickly turn out unusable as multiple inheritance isn’t supported.

Every property has almost the exact same implementation!:

Although macros can be nasty, I’d argue this would be a correct usage for them. But, ofcourse C# doesn’t support macros. The duplicate code was there before, at least it’s reduced and grouped together now.

So it looks like this is the end, …. or is it? Enter, Aspect Oriented Programming!

At first, a strangely unfamiliar name to me. Now, I can only dream of the following implementation.

[DependencyObject]
public class FactoryExample
{
        [DependencyProperty(DefaultValue="foo")]
        public string Standard { get; set; }

        [DependencyProperty]
        public bool ReadOnly { get; private set; }

        [DependencyProperty]
        public int Callback { get; set; }

        ...
}

By acquiring a license for PostSharp, or with a lot of free time on your hands by implementing it yourself, you could attempt an implementation just like that! If it whet your appetite, be sure to check it out, but for me, the road ends here.

Dependency Property Factory source code

For the latest version of this code, you can download my FCL Extension library. It’s located in the Whathecode.PresentationFramework assembly under the namespace Whathecode.System.Windows.DependencyPropertyFactory.

public class FactoryExample
{
        public enum Property
        {
            Standard,
            ReadOnly,   // This becomes a readonly property.
            Callback    // This property has callbacks assigned to it.
        }
        private static readonly DependencyPropertyFactory m_properties =
            new DependencyPropertyFactory();

        public static readonly DependencyProperty StandardProperty =
            m_properties[Property.Standard];
        public static readonly DependencyProperty ReadOnlyProperty =
            m_properties[Property.ReadOnly];
        public static readonly DependencyProperty CallbackProperty =
            m_properties[Property.Callback];

        [DependencyProperty(Property.Standard, DefaultValue="foo")]
        public string Standard
        {
            get { return m_properties.GetValue(this, Property.Standard) as string; }
            set { m_properties.SetValue(this, Property.Standard, value); }
        }

        [DependencyProperty(Property.ReadOnly)]
        public bool ReadOnly
        {
            get { return (bool)m_properties.GetValue(this, Property.ReadOnly); }
            private set { m_properties.SetValue(this, Property.ReadOnly, value); }
        }

        [DependencyProperty(Property.Callback)]
        public int Callback
        {
            get { return (int)m_properties.GetValue(this, Property.Callback); }
            set { m_properties.SetValue(this, Property.Callback, value); }
        }

        [DependencyPropertyChanged(Property.Callback)]
        public static void OnChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
        {
            ...
        }

        [DependencyPropertyCoerce(Property.Callback)]
        public static object OnCoerce( DependencyObject d, object value )
        {
            ...
        }
}

1 Comment

Dependency Property Factory – Part 2

This post is a follow-up to an earlier attempt to simplify creating dependency properties.

I didn’t notice a possible problem with the approach of the previous post since it doesn’t cause any problems in the project I use it in. WPF is quite strict when it comes to creating custom dependency properties. There are several ways in which you can do it wrong, and the code in the last post does admittedly, exactly that. “There are established naming conventions regarding dependency properties that you must follow in all but exceptional circumstances.” In my opinion, the ability to misuse an interface, and additionally not even being able to notice it, indicates a design flaw. To quote someone with a lot more experience:

Make interfaces easy to use correctly and hard to use incorrectly. The best way to prevent incorrect use is to make such use impossible. – Scott Meyers

…, and that’s exactly what I’ll try to do.

Convention 1: “The name of the field is always the name of the property, with the suffix Property appended.”

public static readonly DependencyProperty IsSpinningProperty =
    DependencyProperty.Register(
    "IsSpinning", typeof(Boolean), typeof(OwnerType));

Convention 2: “Define a CLR “wrapper” property whose name matches the name of the dependency property.”

public bool IsSpinning
{
    get { return (bool)GetValue(IsSpinningProperty); }
    set { SetValue(IsSpinningProperty, value); }
}

Convention 3: “In all but exceptional circumstances, your wrapper implementations should perform only the GetValue and SetValue actions, respectively.”

First I want to determine why ignoring these conventions causes problems. I was already aware that XAML bypasses property wrappers, resulting in convention 3, and proposed a solution in the previous post. An exception could be thrown in the factory class to prevent a wrong CLR property wrapper. Apparently XAML bypasses the wrappers by calling GetValue() and SetValue() directly (for performance reasons), using the property name with “Property” suffixed to it as a parameter. E.g. the property with the name “ABC” gets called as GetValue(ABCProperty). This causes convention 1. Convention 2 is a bit vague and not mentioned explicitly why it is necessary. Other problems when not following these conventions are according to msdn:

  • Certain aspects of styles and templates will not work.
  • Most tools and designers must rely on the naming conventions to properly serialize XAML, or to provide designer environment assistance at a per-property level.

Does anyone know concrete examples of problems caused by not following convention 2, or in other words, why is it of any importance?

The factory class mentioned in the previous post doesn’t follow convention 1 at all. Why can I still use the dependency properties through XAML? The setter and binding in the following sample work perfectly. It seems like all XAML really needs is the name of the dependency property as passed with the DependencyProperty.Register() method. This would also make a lot more sense, since the name would be redundant otherwise.

<DependencyPropertyTestControl
XamlSetTest="100"
Margin="{Binding RelativeSource={RelativeSource Self}, Path=XamlSetTest}" />
    public class DependencyPropertyTestControl : Label
    {
        public enum Property
        {
            XamlSetTest
        }
        private static readonly DependencyPropertyFactory<Property> m_properties =
            new DependencyPropertyFactory<Property>( typeof( DependencyPropertyTestControl ) );

        public static readonly Dictionary<Property, DependencyProperty> Properties =
            m_properties.Properties;

        [DependencyPropertyAttribute( Property.XamlSetTest )]
        public string XamlSetTest
        {
            get { return GetValue( Properties[ Property.XamlSetTest ] ) as string; }
            set { SetValue( Properties[ Property.XamlSetTest ], value ); }
        }

        [DependencyPropertyChangedAttribute( Property.XamlSetTest )]
        public static void OnSourceChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
        {
            var control = d as DependencyPropertyTestControl;

            if ( control != null )
            {
                control.Content = e.NewValue;
            }
        }
    }

UPDATE:
I posted these questions on the msdn forum to see whether somebody could answer them. The answer seems to confirm my suspicions that the property system only uses the name passed to Register() and not the field identifier. I’m guessing it can access the dictionary of DependencyObject directly and uses the dependency property name as the key to find the property in this dictionary. Still it is not wise to break conventions, so I’ll attempt to adjust the factory so that it enforces them instead. I’m afraid this will make a lot of its code superfluous. Perhaps a helper class is a better approach. Recently I discovered exactly such an implementation, and will check it out.

Make Interfaces Easy to Use Correctly and Hard to Use Incorrectly

2 Comments

Dependency Property Factory

If you have ever developed an application using WPF, you most likely came across dependency properties. At first you love the flexibility of them and what it allows you to do, as they are great! However, after a while you might feel like you are writing a lot of duplicate code, and are filling up entire classes with it. This for me was a strong indication to encapsulate the behaviour and creation of dependency properties as good software design calls for.

To get a quick idea of my proposed solution I’ll simply post two code segments. One taken from an excellent tutorial on dependency properties by Christian Mosers. The other adjusts the code segment using the new approach.

Most common usage:

// Dependency Property
public static readonly DependencyProperty CurrentTimeProperty =
    DependencyProperty.Register(
        "CurrentTime",
        typeof(DateTime),
        typeof(MyClockControl),
        new FrameworkPropertyMetadata(
            DateTime.Now, OnCurrentTimePropertyChanged, OnCoerceTimeProperty
        ));

// .NET Property wrapper
public DateTime CurrentTime
{
    get { return (DateTime)GetValue(CurrentTimeProperty); }
    set { SetValue(CurrentTimeProperty, value); }
}

private static void OnCurrentTimePropertyChanged(
    DependencyObject source,
    DependencyPropertyChangedEventArgs e)
{
    MyClockControl control = source as MyClockControl;
    DateTime time = (DateTime)e.NewValue;
    // Put some update logic here...
}

private static object OnCoerceTimeProperty(DependencyObject sender, object data)
{
    if ((DateTime)data > DateTime.Now)
    {
        data = DateTime.Now;
    }
    return data;
}

// Register the private key to set the value
private static readonly DependencyPropertyKey IsMouseOverPropertyKey =
    DependencyProperty.RegisterReadOnly(
        "IsMouseOver",
        typeof(bool),
        typeof(MyClass),
        new FrameworkPropertyMetadata(false));

// Register the public property to get the value
public static readonly DependencyProperty IsMouseoverProperty =
    IsMouseOverPropertyKey.DependencyProperty;

// .NET Property wrapper
public int IsMouseOver
{
   get { return (bool)GetValue(IsMouseOverProperty); }
   private set { SetValue(IsMouseOverProperty, value); }
}

My proposed solution:

// Enum declaring all the dependency properties present.
public enum Property
{
    CurrentTime,
    IsMouseOver
}

// A factory class used to create and manage the dependency properties.
private static readonly DependencyPropertyFactory<Property> m_properties =
    new DependencyPropertyFactory<Property>(typeof(MyClockControl));

// Public dictionary used to access the dependency properties.
public static readonly Dictionary<Property, DependencyProperty> Properties =
    m_properties.Properties;

[DependencyPropertyAttribute(Property.CurrentTime, DefaultValue=DateTime.Now)]
public DateTime CurrentTime
{
    get { return (DateTime)GetValue(Properties[Property.CurrentTime]); }
    set { SetValue(Properties[Property.CurrentTime], value); }
}

[DependencyPropertyChangedAttribute(Property.CurrentTime)]
private static void OnCurrentTimePropertyChanged(
    DependencyObject source,
    DependencyPropertyChangedEventArgs e)
{
    MyClockControl control = source as MyClockControl;
    DateTime time = (DateTime)e.NewValue;
    // Put some update logic here...
}

[DependencyPropertyCoerceAttribute(Property.DateTime)]
private static object OnCoerceTimeProperty(DependencyObject sender, object data)
{
    if ((DateTime)data > DateTime.Now)
    {
        data = DateTime.Now;
    }
    return data;
}

[DependencyPropertyAttribute(Property.IsMouseOver)]
public bool IsMouseOver
{
   get { return (bool)GetValue(Properties[Property.IsMouseOver]); }
   private set {
       m_properties.SetReadOnlyProperty(this, Properties[Property.IsMouseOver], value);
   }
}

As you might notice, the last code sample has a few advantages.

  • To identify the dependency property an enum is used, still allowing for strong typed identification of the properties.
  • By passing the owner type for the dependency property to the factory class, it is specified in just one place.
  • The settings for a dependency property are placed right above the property which is used in code internally. Parameters you had to pass manually to the DependencyProperty.Register() method before are deduced automatically. You can still specify them manually as well.
  • Although not really visible through this short code sample, adding more properties is really easy and requires a lot less code.
  • Centralized code. In the unlikely event that the Register() method changes, you only have to adjust the code of the factory class.

How it works:
The factory uses reflection to analyse the code to which the attributes are applied. This way it knows the property type and whether the dependency property should be readonly or not. As a name for the property, the ToString() method is used by default.

To be fair I’ll also mention the problems I see with this approach:

  • There is a small overhead to retrieve the dependency property through the Dictionary every time. I do believe this will have a minor impact.
  • Since DependencyObject internally already works with a dictionary, it’s kind of a double effort.
  • The enum value needs to be defined three times for every property. I don’t know an immediate solution for this, but it is relevant for a future post where I’ll discuss data model generation.

Possible expansions:

  • Right now the Dictionary used to make the properties available for public use isn’t read only. Since this class isn’t available by default this might be a subject I’ll address at a later time. Googling for a short amount of time already indicated this is a known problem. Perhaps a custom implementation of Collection can be created to break all references to DependencyProperty.
  • Because the factory controls the creation of the dependency properties, exceptions can be thrown when invalid usage is detected. E.g. When the .NET properties contain more statements than the GetValue() and SetValue().

All things considered I don’t see any major disadvantages, but I’m no WPF expert. I’d love to have some input from people more experienced with WPF.

Factory source code

UPDATE:

Possible problems due to WPF’s naming conventions are discussed in a new post.
For the most recent version, go to my last post for information. For the source code, you can download my FCL Extension library. The DependencyPropertyFactory is located in the Whathecode.PresentationFramework assembly under the namespace Whathecode.System.Windows.DependencyPropertyFactory.

1 Comment