(I am totally new to this concept so I may be asking very basic questions.)
A dependency property is registered with the code below:
public static DependencyProperty Register(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata);
Logically, it did nothing but associate a property name with the owner type.
So if I have multiple instances of the owner type, and each instance set the DP to different values.
How could these values be stored?
Update 1 - 10:04 AM 10/30/2013
I read about the Attached Property from here: http://wpftutorial.net/DependencyProperties.html
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.
So in the following code snippet:
<Canvas>
<Button Canvas.Top="20" Canvas.Left="20" Content="Click me!"/>
<Button Canvas.Top="40" Canvas.Left="20" Content="Click me!"/>
</Canvas>
Apparently we cannot give all the align properties such as Top, Left to Button. So Canvas defines such properties and they are "attached" to Button control.
When Canvas.Top is specified as an "attribute" of the Button in XAML, it will invoke the SetTop() method which is defined in the Canvas type. And the Button is passed in as the element argument. I think that's how Canvas knows which Button use which Top value.
public static void SetTop(UIElement element, double length);
But I don't see why the Attached Property has to be a Dependency Property? What's the connection between them?
Thanks!
Usually when we define a DependencyProperty
, we also define a CLR 'wrapper' that enables us to use the DependencyProperty
in code:
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
"Items", typeof(ObservableCollection<string>), typeof(MainWindow),
new UIPropertyMetadata(new ObservableCollection<string>()));
public ObservableCollection<string> Items
{
get { return (ObservableCollection<string>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
Here you can see the GetValue
and SetValue
methods that @Clemens was talking about. We get access to these methods in a Window
and/or UserControl
because they both extend the DependencyObject
class. You can also see that the Items
property here is not static
... it is just the definition of the DependencyProperty
that is static
.
UPDATE >>>
There's not really much point in asking why does an Attached Property have to be a DependencyProperty
? because in .NET, they just are... they were just designed like that. A better question might be, what benefit does an Attached Property get from being a DependencyProperty
?
The answer to that would be the same as if asked what benefit does a property get from being a DependencyProperty
? The main benefits being that these properties can be used in Binding
s, Style
s, Animation
s and Resources
among other things. More details can be found from the (already linked to in the comments) two very important pages on MSDN for any WPF developers:
To answer your question I need to start from the very basics of Dependency system (you already know most of these things below, but I think after reading it your question might answer itself)
DependencyProperty
should be defined within a class that is derived from DependencyObject
because DependencyObject
implements some methods and members (which most of them are private and developers can't see them). These implementations provide the DependencyObject
with the abilities to store and retrieve data with static reference to the class (instead of reference to an instance of the class)
The way we store and retrive data is either through the DependencyProperty
's wrapper or directly by GetValue and SetValue (which are DependencyObject
's methods) or through bindings. Either way the static DependencyProperty
is the "key" to find the proper value.
When you register a DependencyProperty
, the Dependency system is informed that a new DependencyProperty
is added to its resources (something like a list, filled with DependencyProperties that you've registerd). Now if you store something as [this.]SetValue(MyProperty, value)
, you're essentially updating a resource of object this
(which you can imagine as this.Resources[MyProperty]
).
This works just like a normal property on the outside, but considering the UIPropertyMetadata
and other Dependency
stuff, your DependencyProperty
is equipped with a handful of unique abilities to Coerce, participate in animations, notify when changed and etc and can do much more than a simple property.
remember extension?
public static void MyExtension(this MyType target, string parameter, ...)
{
target.MyFunction(parameter, ...);
}
var t = new MyType();
t.MyExtension("test");
AttachedProperty
is somehow the combination of DependencyProperty
and extension, with some differences:
Wrappers of
AttachedProperty
are static and take a class reference as input to know where are they attached. The target of aDependencyProperty
is usuallythis
(unless you change GetValue and SetValue to something likeotherObject.SetValue(MyProperty, value)
). but unlikeDependencyProperty
, The target of anAttachedProperty
(which have to be aDependencyObject
itself) is being passed to it as a parameter. and again the reason it has to be aDependencyObject
is that only aDependencyObject
is capable of having a set of resources to store aDependencyProperty
in.unlike
DependencyProperty
which usesRegister
,AttachedProperty
usesRegisterAttached
method which tells the Dependency System that otherDependencyObject
s can have this property but still the actual static property is stored inDependencyObject
which has theAttachedProperty
.in Extension,
this
before its first parameter is used to "extend" the type next to it. inAttachedProperty
there's nothis
, in fact it's always theDependencyObject
class which is extended.Unlike
AttachedProperty
, an extension can't store data by itself unless you write a few lines of code similar to the implementation of theAttachedProperty
. e.g. implementing a static list ofKeyValuePairs
(Value for the actual data and Key for knowing to whom do they belong)
Edit:
After Clemens's comment I need to add that AttachedProperty
is not actually an extension. the reason I brought up extension is that by comparing these two, you can see the reason why a normal property can't be attached to a DependencyObject
because in order to store data in other objects, some collection like a Resource is needed (which DependencyObject
has).
I've always viewed DependencyProperties
as a property definition, which is different from a normal property.
The property definition contains the property type, name, default value, etc and includes a pointer showing where to find the property value. But it doesn't contain the value itself.
This allows you to use DependencyProperties
in Bindings, since you can set the property up to get its value from a bound expression instead of from the object itself.
This is important for AttachedProperties
because their value doesn't reside on the object they are attached to. They need the ability to look up their value in a different location than the object itself, and DependencyProperties
allow this.
You can't do this with a regular property because a normal property's value is meant to be found on the object itself, but an AttachedProperty
doesn't exist on the object it's attached to.
That's the simple version. :)
来源:https://stackoverflow.com/questions/19662525/how-dependency-property-tell-the-object-to-apply-to