Vous êtes sur la page 1sur 4

Each DependencyProperty provides callbacks for change notification, value coercion and

validation. These callbacks are registered on the dependency property.


new FrameworkPropertyMetadata( DateTime.Now,
OnCurrentTimePropertyChanged,
OnCoerceCurrentTimeProperty ),
OnValidateCurrentTimeProperty );

Value Changed Callback


The change notification callback is a static method, that is called everytime when the value of
the TimeProperty changes. The new value is passed in the EventArgs, the object on which the
value changed is passed as the source.
private static void OnCurrentTimePropertyChanged(DependencyObject source,
DependencyPropertyChangedEventArgs e)
{
MyClockControl control = source as MyClockControl;
DateTime time = (DateTime)e.NewValue;
// Put some update logic here...
}

Coerce Value Callback


The coerce callback allows you to adjust the value if its outside the boundaries without
throwing an exception. A good example is a progress bar with a Value set below the
Minimum or above the Maximum. In this case we can coerce the value within the allowed
boundaries. In the following example we limit the time to be in the past.
private static object OnCoerceTimeProperty( DependencyObject sender, object
data )
{
if ((DateTime)data > DateTime.Now )
{
data = DateTime.Now;
}
return data;
}

Validation Callback
In the validate callback you check if the set value is valid. If you return false, an
ArgumentException will be thrown. In our example demand, that the data is an instance of a
DateTime.

private static bool OnValidateTimeProperty(object data)


{
return data is DateTime;
}

Readonly DependencyProperties
Some dependency property of WPF controls are readonly. They are often used to report the
state of a control, like the IsMouseOver property. Is does not make sense to provide a setter
for this value.
Maybe you ask yourself, why not just use a normal .NET property? One important reason is
that you cannot set triggers on normal .NET propeties.
Creating a read only property is similar to creating a regular DependencyProperty. Instead of
calling DependencyProperty.Register() you call
DependencyProperty.RegisterReadonly(). This returns you a DependencyPropertyKey.
This key should be stored in a private or protected static readonly field of your class. The key
gives you access to set the value from within your 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 IsMouseOverPropertyKey =
DependencyProperty.RegisterReadOnly("IsMouseOver",
typeof(bool), typeof(MyClass),
new FrameworkPropertyMetadata(false));
// Register the public property to get the value
public static readonly DependencyProperty IsMouseoverProperty =
IsMouseOverPropertyKey.DependencyProperty;
// .NET Property wrapper
public int IsMouseOver
{
get { return (bool)GetValue(IsMouseoverProperty); }
private set { SetValue(IsMouseOverPropertyKey, value); }
}

Attached Properties
Attached properties are a special kind of DependencyProperties. They allow you to attach a
value to an object that does not know anything about this value.

A good example for this concept are layout panels. Each layout panel needs different data to
align its child elements. The Canvas needs Top and Left, The DockPanel needs Dock, etc.
Since you can write your own layout panel, the list is infinite. So you see, it's not possible to
have all those properties on all WPF controls.
The solution are attached properties. They are defined by the control that needs the data from
another control in a specific context. For example an element that is aligned by a parent
layout panel.
To set the value of an attached property, add an attribute in XAML with a prefix of the
element that provides the attached property. To set the the Canvas.Top and Canvas.Left
property of a button aligned within a Canvas panel, you write it like this:
<Canvas>
<Button Canvas.Top="20" Canvas.Left="20" Content="Click me!"/>
</Canvas>
public static readonly DependencyProperty TopProperty =
DependencyProperty.RegisterAttached("Top",
typeof(double), typeof(Canvas),
new FrameworkPropertyMetadata(0d,
FrameworkPropertyMetadataOptions.Inherits));
public static void SetTop(UIElement element, double value)
{
element.SetValue(TopProperty, value);
}
public static double GetTop(UIElement element)
{
return (double)element.GetValue(TopProperty);
}

Listen to dependency property changes


If you want to listen to changes of a dependency property, you can subclass the type that
defines the property and override the property metadata and pass an
PropertyChangedCallback. But an much easier way is to get the
DependencyPropertyDescriptor and hookup a callback by calling AddValueChanged()
DependencyPropertyDescriptor textDescr = DependencyPropertyDescriptor.
FromProperty(TextBox.TextProperty, typeof(TextBox));
if (textDescr!= null)
{
textDescr.AddValueChanged(myTextBox, delegate
{
// Add your propery changed logic here...
});
}

How to clear a local value


Because null is also a valid local value, there is the constant
DependencyProperty.UnsetValue that describes an unset value.
button1.ClearValue( Button.ContentProperty );

Vous aimerez peut-être aussi