Dependency properties aren’t type-safe and aren’t generic. That’s because when they were designed, generics weren’t commonly used in c# (remember that WPF was first designed around the release of .Net 2.0 which presented the generics).

For this reason, the API of dependency properties is based on the Object class, which is a reference type. When using dependency properties for value types, we encounter a lot of boxing and unboxing.

According to Microsoft (in the link), the performance impact of boxing and unboxing is fairly big (more information can be found here). What Microsoft did in WPF, was creating (sadly internal) predefined boxed versions of commonly used value-types like Boolean, Size struct, Visibility enum and FillRule enum.

I recommend using the same mechanism, at least for Booleans, as this type is used for a lot of developers’ dependency properties.

The basic idea used for Booleans (and also the Visibility and FillRule enums; The Size struct is implemented slightly different) is to create a static BooleanBoxes class that has the following public static members:

  • A field for a predefined boxed "false" value.
  • A field for a predefined boxed "true" value.
  • A method named Box(boolean) that receives a regular Boolean, and returns its boxed representation.

The reason the fields are public, is to use them for registering the default value of the dependency properties, which is of type Object as well.

The Box method will be mainly used in the setter of your wrapping .Net property, inside the DependencyObject.SetValue method. The getter of the property will not use an "unbox" method because we can’t really know if two boxed Booleans are equal without unboxing them, and we can’t prevent someone from setting the property’s value directly from the DependencyObject.SetValue instead of our setter.

You can see these boxing classes with Reflector or IL Spy under MS.Internal.KnownBoxes (inside WindowsBase, PresentationCore and PresentationFramework).

Here is the code of the class:

/// <summary>
/// Helps boxing Booolean values.
/// </summary>
public static class BooleanBoxes
{
    /// <summary>
    /// Gets a boxed representation for Boolean's "true" value.
    /// </summary>
    public static readonly object TrueBox;

    /// <summary>
    /// Gets a boxed representation for Boolean's "false" value.
    /// </summary>
    public static readonly object FalseBox;

    /// <summary>
    /// Initializes the <see cref="BooleanBoxes"/> class.
    /// </summary>
    static BooleanBoxes()
    {
        TrueBox = true;
        FalseBox = false;
    }

    /// <summary>
    /// Returns a boxed representation for the specified Boolean value.
    /// </summary>
    /// <param name="value">The value to box.</param>
    /// <returns></returns>
    public static object Box(bool value)
    {
        if (value)
        {
            return TrueBox;
        }

        return FalseBox;
    }
}

And here is how I might use it:

public bool ValidateNames
{
    get { return (bool)GetValue(ValidateNamesProperty); }
    set { SetValue(ValidateNamesProperty, BooleanBoxes.Box(value)); }
}

public static readonly DependencyProperty ValidateNamesProperty =
    DependencyProperty.Register("ValidateNames", typeof(bool), typeof(MyClass), new UIPropertyMetadata(BooleanBoxes.TrueBox));
Advertisements