This post is in continuation to the last post.
In this Post I’ll be exploring the Dependency Properties
Dependency properties are similar to CLR properties with more advanced and complex features. The main difference between the CLR properties and dependency properties is, that the value of a normal .NET property is read directly from a private member in your class, whereas the value of a DependencyProperty is resolved dynamically when calling the GetValue() method that is inherited from DependencyObject. In case this description did not make sense, no need to worry, It will become clear by the time you reach end of this article.
How the Value is Resolved in Dependency properties
Every time a dependency property is accessed, it internally resolves the value by following the precedence from high to low. It checks if a local value is available, if not, check if a custom style trigger is active and I the similar manner continues until it finds a value. At last the default value is always available.
The Following Figure depicts this searching.
Each WPF control registers a set of DependencyProperties to the static DependencyProperty class. Each of them consists of a key - that must be unique per type - and a metadata that contain callbacks and a default value.
All types that want to use DependencyProperties must derive from DependencyObject. This base class defines a key, value dictionary that contains local values of dependency properties. The key of an entry is the key defined with the dependency property.
When a dependency property is accessed over its .NET property wrapper, it internally calls GetValue (DependencyProperty) to access the value.
This method resolves the value by using a value resolution strategy described here. If a local value is available, it reads it directly from the dictionary. If no value is set if goes up the logical tree and searches for an inherited value. If no value is found it takes the default value defined in the property metadata
How to create a DependencyProperty
To create a DependencyProperty, a static field of type DepdencyProperty is added to the type (that is being created) and DependencyProperty. Register() is called to create an instance of a dependency property.
Naming Convention: The name of the DependendyProperty must always end with Property.
Dependency property can be accessed as a normal .net property by adding a property wrapper. This wrapper internally gets and sets the value by using the GetValue () and SetValue () Methods inherited from DependencyObject and passing the DependencyProperty as key.
Important: No logic should be added to these properties, because they are only called when the property is set from code. If the property is set from XAML, the SetValue () method is called directly.
Let us consider creating a dependency property in a control named WPFClockControl, giving the Current Time.
// Dependency Property
public static readonly DependencyProperty CurrentTimeProperty =
DependencyProperty. Register ( "CurrentTime", typeof(DateTime),
typeof(MyClockControl), new FrameworkPropertyMetadata(DateTime.Now));
Now the following code creates the wrapper.
// .NET Property wrapper
public DateTime CurrentTime
{
get { return (DateTime)GetValue(CurrentTimeProperty); }
set { SetValue(CurrentTimeProperty, value); }
}
Why Use Dependency properties:
Each DependencyProperty provides callbacks for change notification, value coercion (The coerce callback allows to adjust the value if its value is lies outside the boundaries without throwing an exception) and validation (if the set value is valid). These callbacks are registered on the dependency property. In simple words, triggers (as above) can’t be set on normal .NET properties.
Readonly DependencyProperties
Creating a read only property is similar to creating a regular DependencyProperty. Instead of calling DependencyProperty. Register(),call to DependencyProperty.RegisterReadonly() is made.
This returns a DependencyPropertyKey. This key should be stored in a private or protected static readonly field of the class. The key gives the access to set the value from within the class and use it like a normal dependency property.
Second thing to do is registering a public dependency property that is assigned to DependencyPropertyKey.DependencyProperty. This property is the readonly property that can be accessed from external.
// Register the private key to set the value
private static readonly DependencyPropertyKey IsMouseOutPropertyKey =
DependencyProperty.RegisterReadOnly("IsMouseOut",
typeof(bool), typeof(MyClass),
new FrameworkPropertyMetadata(false));
// Register the public property to get the value
public static readonly DependencyProperty IsMouseOutProperty =
IsMouseOutPropertyKey.DependencyProperty;
// .NET Property wrapper
public int IsMouseOut
{
get { return (bool)GetValue(IsMouseOutProperty); }
private set { SetValue(IsMouseOutPropertyKey, value); }
}
Attached Properties
Attached properties are a special kind of DependencyProperties. They allow a value to be attached to an object that does not know anything about this value. Attached property does not have the conventional property "wrapper".
More details about the Attached properties can be found here
Next article in the series will explore the remaining topics mentioned in the first article.
Hope this was helpful.
Till Next we Connect……………….
Happy Learning.
In this Post I’ll be exploring the Dependency Properties
Dependency properties are similar to CLR properties with more advanced and complex features. The main difference between the CLR properties and dependency properties is, that the value of a normal .NET property is read directly from a private member in your class, whereas the value of a DependencyProperty is resolved dynamically when calling the GetValue() method that is inherited from DependencyObject. In case this description did not make sense, no need to worry, It will become clear by the time you reach end of this article.
How the Value is Resolved in Dependency properties
Every time a dependency property is accessed, it internally resolves the value by following the precedence from high to low. It checks if a local value is available, if not, check if a custom style trigger is active and I the similar manner continues until it finds a value. At last the default value is always available.
The Following Figure depicts this searching.
Each WPF control registers a set of DependencyProperties to the static DependencyProperty class. Each of them consists of a key - that must be unique per type - and a metadata that contain callbacks and a default value.
All types that want to use DependencyProperties must derive from DependencyObject. This base class defines a key, value dictionary that contains local values of dependency properties. The key of an entry is the key defined with the dependency property.
When a dependency property is accessed over its .NET property wrapper, it internally calls GetValue (DependencyProperty) to access the value.
This method resolves the value by using a value resolution strategy described here. If a local value is available, it reads it directly from the dictionary. If no value is set if goes up the logical tree and searches for an inherited value. If no value is found it takes the default value defined in the property metadata
How to create a DependencyProperty
To create a DependencyProperty, a static field of type DepdencyProperty is added to the type (that is being created) and DependencyProperty. Register() is called to create an instance of a dependency property.
Naming Convention: The name of the DependendyProperty must always end with Property.
Dependency property can be accessed as a normal .net property by adding a property wrapper. This wrapper internally gets and sets the value by using the GetValue () and SetValue () Methods inherited from DependencyObject and passing the DependencyProperty as key.
Important: No logic should be added to these properties, because they are only called when the property is set from code. If the property is set from XAML, the SetValue () method is called directly.
Let us consider creating a dependency property in a control named WPFClockControl, giving the Current Time.
// Dependency Property
public static readonly DependencyProperty CurrentTimeProperty =
DependencyProperty. Register ( "CurrentTime", typeof(DateTime),
typeof(MyClockControl), new FrameworkPropertyMetadata(DateTime.Now));
Now the following code creates the wrapper.
// .NET Property wrapper
public DateTime CurrentTime
{
get { return (DateTime)GetValue(CurrentTimeProperty); }
set { SetValue(CurrentTimeProperty, value); }
}
Why Use Dependency properties:
Each DependencyProperty provides callbacks for change notification, value coercion (The coerce callback allows to adjust the value if its value is lies outside the boundaries without throwing an exception) and validation (if the set value is valid). These callbacks are registered on the dependency property. In simple words, triggers (as above) can’t be set on normal .NET properties.
Readonly DependencyProperties
Creating a read only property is similar to creating a regular DependencyProperty. Instead of calling DependencyProperty. Register(),call to DependencyProperty.RegisterReadonly() is made.
This returns a DependencyPropertyKey. This key should be stored in a private or protected static readonly field of the class. The key gives the access to set the value from within the class and use it like a normal dependency property.
Second thing to do is registering a public dependency property that is assigned to DependencyPropertyKey.DependencyProperty. This property is the readonly property that can be accessed from external.
// Register the private key to set the value
private static readonly DependencyPropertyKey IsMouseOutPropertyKey =
DependencyProperty.RegisterReadOnly("IsMouseOut",
typeof(bool), typeof(MyClass),
new FrameworkPropertyMetadata(false));
// Register the public property to get the value
public static readonly DependencyProperty IsMouseOutProperty =
IsMouseOutPropertyKey.DependencyProperty;
// .NET Property wrapper
public int IsMouseOut
{
get { return (bool)GetValue(IsMouseOutProperty); }
private set { SetValue(IsMouseOutPropertyKey, value); }
}
Attached Properties
Attached properties are a special kind of DependencyProperties. They allow a value to be attached to an object that does not know anything about this value. Attached property does not have the conventional property "wrapper".
More details about the Attached properties can be found here
Next article in the series will explore the remaining topics mentioned in the first article.
Hope this was helpful.
Till Next we Connect……………….
Happy Learning.
Comments
Post a Comment