How to Create an Attached Properties in WPF

By | October 12, 2013

Well, attached properties, just like normal properties are an object of Dependency Property, but with a very special point embedded into it. Even though the attached properties can only be added to a class which inherits from DependencyObject and also the property where it is attached to should also be a dependency property itself, an Attached property in WPF stays out of the actual object where it is attached to. For example, Canvas has two attached property that we can use while defining the Left and Right of the controls inside it. We can use Canvas.Left and Canvas.Right, both being an attached property. An attached property extends the the object behavior in boundaries outside it.

Let us try to create an attached property and place it in as a behavior to another object. Let us say we use Attached Property to implement the RotateTransform behavior of a control. Let us take a look on what we are talking about.

<Button Content="MyRotatedButton">
    <Button.RenderTransform>
        <RotateTransform Angle="30" />
    </Button.RenderTransform>
</Button>

The Button hence created will rotate by 30 degrees.

Button with RotateTransform applied

Button with RotateTransform applied

Now to create the same effect using an Attached property would be a fun. Let us create a class and inherit the same from a DependencyObject, we call it as RenderTransformManager. Now to add the Rotation to this class, we need to add a few things :

  1. A Static method for Getter.
  2. A static method for Setter.
  3. A DependencyProperty registered as attached.

Just like I said, the code would look like :

public class RenderTransformManager : DependencyObject {
public static double GetAngle(DependencyObject obj) {
       return (double)obj.GetValue(AngleProperty);
}
public static void SetAngle(DependencyObject obj, double value) {
       obj.SetValue(AngleProperty, value);
}

public static readonly DependencyProperty AngleProperty = DependencyProperty.RegisterAttached("Angle",
                 typeof(double), typeof(RenderTransformManager), new UIPropertyMetadata(0.0));
}

Now in the code above, the public static Setter and Getter is needed, such that we can access the property from code. Remember, the PropertyValue is actually associated and/or resolved directly from inside of the object where it is attached to. So we need to pass the object where it is attached to and call GetValue or SetValue from inside the static getter or setter to do the needful.

The DependencyProperty.RegisteredAttached will allow this double value to be added to the RenderTransformManager.

Now to fix the code with the new property Angle, we can use the below code:

   <Button Content="MyRotatedButton" local:RenderTransformManager.Angle="30" />

Wait, well, if you run the code above, nothing will happen, because we didnt added the behavoir to the actual object. So lets redefine the attached property again with OnAngleChanged event.

public static readonly DependencyProperty AngleProperty = DependencyProperty.RegisterAttached("Angle",
           typeof(double), typeof(RenderTransformManager), new UIPropertyMetadata(0.0, <strong>OnAngleChanged</strong>));

Now when OnAngleChanged is called we need to add a RotateTransform to the object. Just like the code below :

private static void OnAngleChanged(DependencyObject obj,  DependencyPropertyChangedEventArgs e) 
{
    var element = obj as UIElement;
    if(element != null) {
    element.RenderTransformOrigin = new Point(.5, .5);
    element.RenderTransform = new RotateTransform((double)e.NewValue);
}

Voila!! It did the job. This looks the same. :)

Now you can use local:RenderTransformManager.Angle=”200″ on any control that inherits from DependencyObject.

I hope you can now define and use Attached properties yourself in code.

Happy programming.