Logo
programming4us
programming4us
programming4us
programming4us
Home
programming4us
XP
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server
programming4us
Windows Phone
 
Windows Phone

Dependency Properties - Attached Properties

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
3/20/2011 4:03:56 PM
Attached properties are at first very mysterious. As you know from this article, here’s how you might see them in XAML:
<Canvas>
. . .
<Ellipse Style="{StaticResource ellipseStyle}"
Canvas.Left="116" Canvas.Top="92" />
. . .
</Canvas>

That’s straight out of the EllipseChain program.

Canvas.Left and Canvas.Top are attached properties. They are properties defined by Canvas that you set on children of the Canvas.

As I discussed in this article, there is actually nothing in Canvas named Left or Top. When setting these attached properties in code, you use two static methods defined by the Canvas class:

Canvas.SetLeft(ellipse, 116);
Canvas.SetTop(ellipse, 92);

Or you can use the SetValue method defined by DependencyObject and inherited by the Ellipse class to reference the static dependency properties defined by Canvas:

ellipse.SetValue(Canvas.LeftProperty, 116.0);
ellipse.SetValue(Canvas.TopProperty, 92.0);

This is the same SetValue methods that a class calls in a CLR property to set a dependency property.

You now know almost everything you need to define your own attached properties. The project named CanvasCloneDemo contains a class named CanvasClone. The class defines two DependencyProperty fields named LeftProperty and TopProperty:

Example 1. Project: CanvasCloneDemo File: CanvasClone.cs (excerpt)
public class CanvasClone : Panel
{
public static readonly DependencyProperty LeftProperty =
DependencyProperty.RegisterAttached("Left",
typeof(double),
typeof(CanvasClone),
new PropertyMetadata(0.0, OnLeftOrTopPropertyChanged));

public static readonly DependencyProperty TopProperty =
DependencyProperty.RegisterAttached("Top",
typeof(double),
typeof(CanvasClone),
new PropertyMetadata(0.0, OnLeftOrTopPropertyChanged));
. . .
}

But notice the difference: Previously in this article, DependencyProperty objects were created with the static DependencyProperty.Register method. The DependencyObject fields in CanvasClone are created with the only other option, DependencyProperty.RegisterAttached. That makes them attached properties and allows them to be set on classes that did not define them.

Notice that the first argument to the PropertyMetadata constructor is explicitly a double so there won’t be a runtime error because the C# compiler assumes the value is an int.

After defining the DependencyProperty fields, you need static methods to access the attached properties. These method names begin with Set and Get followed by the attached property names, in this case, Left and Top,

Example 2. Project: CanvasCloneDemo File: CanvasClone.cs (excerpt)
public static void SetLeft(DependencyObject obj, double value)
{
obj.SetValue(LeftProperty, value);
}

public static double GetLeft(DependencyObject obj)
{
return (double)obj.GetValue(LeftProperty);
}

public static void SetTop(DependencyObject obj, double value)
{
obj.SetValue(TopProperty, value);
}

public static double GetTop(DependencyObject obj)
{
return (double)obj.GetValue(TopProperty);
}

These methods get called either explicitly from code or implicitly from the XAML parser. The first argument will be the object on which the attached property is being set—in other words, the first argument will probably be a child of CanvasClone. The body of the method uses that argument to call SetValue and GetValue on the child. These are the same methods defined by DependencyObject to set and get dependency properties.

When these properties change, there will be a call to the property-changed handler defined in the PropertyMetadata constructor. The signature of this method is the same as a normal property-changed handler for regular dependency properties:

static void OnLeftOrTopPropertyChanged(DependencyObject obj,
DependencyPropertyChangedEventArgs args)
{
. . .
}


Once again, the method is static. However, the first argument is not an object of type CanvasClone. It is a child of the CanvasClone. Or rather, it is probably a child of the CanvasClone. It’s possible to call CanvasClone.SetLeft for an element that isn’t actually a child of the panel, and it’s even possible for CanvasClone.SetLeftOnLeftOrTopPropertyChanged method to be called without any instance of CanvasClone in existence! and the

For this reason, the body of the method needs to use a little bit of caution. It calls the handy static VisualTreeHelper.GetParent method to obtain the parent of the DependencyObject argument and cast it to a CanvasClone:

Example 3. Project: CanvasCloneDemo File: CanvasClone.cs (excerpt)
static void OnLeftOrTopPropertyChanged(DependencyObject obj,
DependencyPropertyChangedEventArgs args)
{
CanvasClone parent = VisualTreeHelper.GetParent(obj) as CanvasClone;

if (parent != null)
parent.InvalidateArrange();
}


If the parent of the object that has called CanvasClone.SetLeft or CanvasClone.SetTop is truly a CanvasClone, then the method calls InvalidateArrange on the parent, which is the CanvasClone.

In the general case, when a panel handles a change in one of its attached properties, it will probably call InvalidateMeasure on the panel to initiate a complete recalculation of layout. However, as you can see in the following MeasureOverride method, the total size of CanvasClone doesn’t change with the location of its children:

Example 4. Project: CanvasCloneDemo File: CanvasClone.cs (excerpt)
protected override Size MeasureOverride(Size availableSize)
{
foreach (UIElement child in Children)
child.Measure(new Size(Double.PositiveInfinity,
Double.PositiveInfinity));

return Size.Empty;
}

It is part of the paradigm of a Canvas that it always returns zero from MeasureOverride regardless of its children, so CanvasClone does the same. MeasureOverrideMeasure on all its children, or the children will have no size, but it calls Measure with infinite dimensions, forcing the child to assume as small a size as possible. still needs to call

When the panel calls InvalidateArrange on itself, layout jumps right into the arrange pass with a call to ArrangeOverride: This method requires the panel to arrange the children on its surface. Essentially it gives each child a size and a location.

Example 5. Project: CanvasCloneDemo File: CanvasClone.cs (excerpt)
protected override Size ArrangeOverride(Size finalSize)
{
foreach (UIElement child in Children)
child.Arrange(new Rect(
new Point(GetLeft(child), GetTop(child)), child.DesiredSize));

return base.ArrangeOverride(finalSize);
}

ArrangeOverride calls its own static GetLeft and GetTop methods on each child to determine where the child should be positioned relative to itself. The size of each child is simply the DesiredSize the child originally calculated in the measure pass.

The XAML file in CanvasCloneDemo is the same as the one in the EllipseChain except that Canvas has been replaced with CanvasClone:

Example 6. Project: CanvasCloneDemo File: MainPage.xaml (excerpt)
<Grid x:Name="ContentPanel" Grid.Row="1">
<local:CanvasClone>
<local:CanvasClone.Resources>
<Style x:Key="ellipseStyle"
TargetType="Ellipse">
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="100" />
<Setter Property="Stroke" Value="{StaticResource PhoneAccentBrush}" />
<Setter Property="StrokeThickness" Value="10" />
</Style>
</local:CanvasClone.Resources>

<Ellipse Style="{StaticResource ellipseStyle}"
local:CanvasClone.Left="0" local:CanvasClone.Top="0" />

<Ellipse Style="{StaticResource ellipseStyle}"
local:CanvasClone.Left="52" local:CanvasClone.Top="53" />

<Ellipse Style="{StaticResource ellipseStyle}"
local:CanvasClone.Left="116" local:CanvasClone.Top="92" />

<Ellipse Style="{StaticResource ellipseStyle}"
local:CanvasClone.Left="190" local:CanvasClone.Top="107" />

<Ellipse Style="{StaticResource ellipseStyle}"
local:CanvasClone.Left="263" local:CanvasClone.Top="92" />

<Ellipse Style="{StaticResource ellipseStyle}"
local:CanvasClone.Left="326" local:CanvasClone.Top="53" />

<Ellipse Style="{StaticResource ellipseStyle}"
local:CanvasClone.Left="380" local:CanvasClone.Top="0" />
</local:CanvasClone>
</Grid>

With much elation, we discover that the display looks the same as the earlier program:



Other -----------------
- Dependency Properties - Panels with Properties
- Dependency Properties - A New Type of Toggle
- Dependency Properties - Deriving from UserControl
- Dependency Properties - The Dependency Property Difference
- Dependency Properties - The Problem Illustrated
- The App Bar and Controls - TextBox and Keyboard Input
- The App Bar and Controls - Buttons and Styles
- The App Bar and Controls - Toggling a Stopwatch
- The App Bar and Controls - The Button Hierarchy
- The App Bar and Controls - Theme Styles and Precedence
 
 
Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
 
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server