Dependency properties are the standard form that properties in WPF take. They support change notification, animation, property value inheritance, and data binding, and they support multiple property value providers.
Note from MSDN
"The purpose of dependency
properties is to provide a way to compute the value of a property based on the
value of other inputs. These other inputs might include system properties such
as themes and user preference, just-in-time property determination mechanisms
such as data binding and animations/storyboards, multiple-use templates such as
resources and styles, or values known through parent-child relationships with
other elements in the element tree. In addition, a dependency property can be
implemented to provide self-contained validation, default values, callbacks
that monitor changes to other properties, and a system that can coerce property
values based on potentially runtime information."
Dependency properties can be implemented only on objects that derive from the DependencyObject class. All WPF elements derive from DependencyObject. If you want to implement dependency properties on a custom class, the class must inherit from DependencyObject. Dependency properties are implemented as normal .NET properties with some extra WPF infrastructure. The dependency property must be registered with the run time in a static constructor, and then it can be set using a standard .NET property wrapper.
To implement and register a dependency property:
1. In a class that inherits from DependencyObject, declare a public, static, read-only variable of the type DependencyProperty. By convention, the name of this variable should be your desired name for the property with the suffix “Property” added to it. Look at the following example:
public static readonly DependencyProperty FlavorProperty;
2. Create a static constructor for the class that registers the dependency property. The DependencyProperty.Register method requires you to provide the name of the .NET property wrapper, the type of the property, the type that owns that property, and an instance of FrameworkPropertyMetadata, which can be used to add optional features to your dependency property. The following example shows a static constructor that registers the dependency property and assumes that your class is named PieClass:
static PieClass()
{
FrameworkPropertyMetadata md = new FrameworkPropertyMetadata();
PieClass.FlavorProperty = DependencyProperty.Register("Flavor",
typeof(string), typeof(PieClass), md);
}
3. Finally, create a .NET property wrapper (also called CLR wrapper) to allow the dependency property to be accessed in code, as shown here:
public string Flavor
{
get { return (string)GetValue(PieClass.FlavorProperty);
set { SetValue(PieClass.FlavorProperty, value); }
}
It is important to note that when dependency properties are set by the run time, they are set directly through the GetValue and SetValue methods, not through the .NET property wrapper. Thus, you should not put any additional code in the wrapper because it does not run unless the property is set directly in code. Also, the name of the field is always the name of the property, with the suffix Property appended.
You can provide a static callback method that executes when the property value is changed by specifying a delegate in FrameworkPropertyMetadata, as shown here:
static PieClass()
{
FrameworkPropertyMetadata md = new FrameworkPropertyMetadata(new
PropertyChangedCallback(FlavorPropertyChanged));
PieClass.FlavorProperty = DependencyProperty.Register("Flavor", typeof(string), typeof(PieClass), md);
}
private static void FlavorPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
// Implementation omitted
}
Example from my project:
To create a generic button: “Accept button” which will turn Red
when any update is made on page using it.
It has two additional dependency properties apart from WPF button properties -
IsPageChanged
AcceptContent
It has two additional dependency properties apart from WPF button properties -
IsPageChanged
AcceptContent
public partial
class AcceptButton
: Button
{
public bool IsPageChanged
{
get { return
(bool)GetValue(IsPageChangedProperty); }
set { SetValue(IsPageChangedProperty, value); }
}
// Using a DependencyProperty as the backing
store for IsPageChanged. This enables
animation, styling, binding, etc...
public static
readonly DependencyProperty
IsPageChangedProperty =
DependencyProperty.Register("IsPageChanged", typeof(bool), typeof(AcceptButton),
new UIPropertyMetadata(false));
public object AcceptContent
{
get { return
(object)GetValue(AcceptContentProperty); }
set { SetValue(AcceptContentProperty, value); }
}
// Using a DependencyProperty as the backing
store for AcceptContent. This enables
animation, styling, binding, etc...
public static
readonly DependencyProperty
AcceptContentProperty =
DependencyProperty.Register("AcceptContent", typeof(object), typeof(AcceptButton),
new UIPropertyMetadata(null));
public
AcceptButton()
{
InitializeComponent();
}
}
XAML
<AcceptButton x:Name="Accept" Grid.Row="2" AcceptContent="Save" Width="59" Height="27" Command="{StaticResource SaveCurrentPage}" />
In code behind,
// Page is no longer changed.
Accept.IsPageChanged
= false;For more example see my posts
Note: This is not my original work. Have blogged it here just for my future reference and of course if someone wants to use it.
thanks. good job
ReplyDelete