Wednesday, April 18, 2007

Attached Properties

Attached properties are a special form of dependency property. a child element can store a value associated with a property defined on an ancestor element. This is commonly used in the interaction between elements and the WPF layout infrastructure, such as an element informing a DockPanel that it should be docked to a particular side of the panel.

Reason for Attached properties:

When dealing with out Layout system, we want to provide the ability for anybody to build new Panels. Inside of those panels you should be able to put normal elements:

<my:RobPanel>
<Button />
<Button />
</my:RobPanel>

Often, the new panel will need to define a property that the user can place on the children of that panel to control how the panel arranges the children.

<my:RobPanel>
<Button RotationsPerMinute="60" />
<Button RotationsPerMinute="3"/>
</my:RobPanel>

Unfortunately that won't work. RotationsPerMinute is a newly invented property. The Button class shipped before the RobPanel was ever built and the Button class designers forgot to include this important property!

So WPF has the concept of attached properties. One class defines the property. You attach it to instances of other objects.

<my:RobPanel>
<Button Name="b1" my:RobPanel.RotationsPerMinute="60" />
<Button Name="b2" my:RobPanel.RotationsPerMinute="3" />
</my:RobPanel>

In C#.
RobPanel.SetRotatationsPerMinute(b1, 30);
int currentRotationsPerMinute = RobPanel.GetRotationsPerMinute(b1);

So if you buy the need for this extensibility, then you need to ask why is Canvas.Top and Canvas.Left modeled as an attached property, but Height and Width are modeled as normal properties.

Top and Left are modeled as attached properties because they are only respected inside of a Canvas. If I set Top or Left on a Button inside a StackPanel or DockPanel, it would have no effect.

Lets we will see an example for attached properties !

In this example i am creating new control named as MyControl with derived from Button. In which i am creating one attached property named as MyAttack.The attached property registration is like dependency property registration and for setting value we need to implement method with signature of SetPropertyName. This method should set the value for attached property using Dependencyobject.SetValue(value) method.

Code For UserControl

public class MyControl : Button
{
public static readonly DependencyProperty MyAttackProperty = DependencyProperty.RegisterAttached("MyAttack", typeof(bool), typeof(MyControl),
new FrameworkPropertyMetadata(new PropertyChangedCallback(OnMyAttackInvalidated)));
public MyControl()
{
}
public static void SetMyAttack(DependencyObject dependencyObject, bool enabled)
{
dependencyObject.SetValue(MyAttackProperty, enabled);
}
private static void OnMyAttackInvalidated(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
Button b = dependencyObject as Button;
if (b != null)
{
if ((bool)e.NewValue)
{
MyControl m = new MyControl();
m.CallClick();
}
}
}
public void CallClick()
{
MessageBox.Show("Clicked");
}
}

For Accessing Attached Property :

We can simply call the created attached property using classname.propertyname from any control attributes area. Like follow's.

<Window x:Class="AttachedProp.Window1" xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=
http://schemas.microsoft.com/winfx/2006/xaml xmlns:mn="clr-namespace:AttachedProp" Title="AttachedProp" Height="300" Width="300" >
<Grid>
<Button mn:MyControl.MyAttack="true" >Click</Button>
</Grid>
</Window>

Output of this example should display messagebox with "Clicked" message after loading the button in window.

Enjoy!!!!!!

No comments:

Post a Comment