다음을 통해 공유


Creating Attached Properties And Services

One cool thing about DependencyProperties is the ability to have AttachedDependencyProperties (or Attached Property for short). Regular properties are defined on a type and exist for instances of that type and sub-classes. An Attached Property is defined in one type, but can be applied to any instance of DependencyObject.

So how does this work? Well the simplistic model is that DependencyObject defines a dictionary to hold property values. The key in the dictionary is the DependencyProperty instance and the value is the current value for that property. Adding an attached property simply adds a new entry into the dictionary for a given object.

To define an attached property one typically writes code that looks like this:

public static readonly DependencyProperty IsTextTrimmedMonitoringEnabledProperty =

DependencyProperty.RegisterAttached(

"IsTextTrimmedMonitoringEnabled",

typeof(bool),

typeof(TextBlockService),

new PropertyMetadata( false, IsTextTrimmedMonitoringEnabledProperty_PropertyChanged) );

       

static public bool GetIsTextTrimmedMonitoringEnabled(DependencyObject element)

{

return (bool) element.GetValue(IsTextTrimmedMonitoringEnabledProperty);

}

       

static public void SetIsTextTrimmedMonitoringEnabled(DependencyObject element, bool value)

{

element.SetValue(IsTextTrimmedMonitoringEnabledProperty, value);

}

       

static private void IsTextTrimmedMonitoringEnabledProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)

{

// handle the property being changed for "o"

}

 

The DependencyProperty field holds the DP instance, which as we discussed is essentially the key to the value.

The Get/Set methods are a best practice to encapsulate the details of how to get/set the value. Like any dependency property there are scenarios where the value can be changed/retrieved directly from the dictionary – so don’t put any logic in there, beyond calling GetValue/SetValue.

Attached properties are common used to implement something called Attached Services (or Attached Behavior), which is logic which you want to associate with a given object. The PropertyChanged method is the entry point to get that logic executing. John Gossman has a good example for an attached service.

When writing an attached service often you’ll find that you need to keep some additional state for each object. One way to do that is to define a ReadOnlyAttachedService. When doing this if the read only attached property should be read outside the class implementing the property (say to be used in XAML to drive a trigger) then the DependencyProperty field and Get method are public, but the Set method is private. If the value contains state which is internal to the workings of the attached service, then make everything private.

If you find your state extends beyond a few simple fields then you might find it handy to define a single read only attached property which holds a value which is an instance of a data class you defined to hold all your state.

Comments