What's the difference between the two, when should RegisterAttached() be used instead of .Register()?
I assume you meant DependencyProperty.Register and DependencyProperty.RegisterAttached.
DependencyProperty.Register is used to register normal DependencyProperty. You can see those as just regular properties, with the added twist that they can take part in WPF's DataBinding, animations etc.
In fact, they are exposed as normal property (with the get and set accessors) on top of the untyped DependencyObject.SetValue / GetValue.
You declare those as part of your type.
Attached properties on the other hand are different. They are meant as an extensibility system. If you have ever used Extenders in Windows Forms, they are kind of similar.
You declare them as part of a type, to be used on another type.
They are used a lot for layout-related information. For example, Canvas needs Left/Top coordinates, Grid needs a Row and a Column, DockPanel needs a Dock information etc. It would be a mess if all of this had to be declared on every Control that can be layouted. So they are declared on the corresponding panel, but used on any Control.
You can use the same thing to attach any information to a DependencyObject if you need to. It can come in handy to just declare a piece of information that you can set in xaml just to be used later in a style for an existing class for example.
So those two kind of DependencyProperty serve a very different purpose. Regular properties (registered through Register() ) are used just like normal properties as part of the interface of your type. Attached properties (registered through RegisterAttached() ) are used as an extensibility point on existing classes.
Hope that clarifies it a bit.
The difference between DependencyProperty.Register() and DependencyProperty.RegisterAttached() is that .Register() is used to register a 'regular' dependency property on a DependencyObject, while .RegisterAttached() is used to set an 'attached' dependency property.
The difference between the two types of dependency properties is reasonably straightforward: regular dependency properties are set on a particular DependencyObject just like you would any other .NET property. Attached properties, on the other hand, are associated with a particular DependencyObject (e.g. Grid) but are set on a completely separate DependencyObject, often a child of the DependencyObject that defines the attached property (e.g. Grid.Row, an attached property, is set on the children of a parent Grid).
More details on attached properties are on MSDN.
A property registered with either Register or RegisterAttached can be attached to any DependencyObject with SetValue and GetValue. But if you attach a property registered with Register to an object of type other than the ownerType, its metadata will not be used (except for a default value). It means that attributes such as Inherits or AffectsMeasure will not work for these properties. You should use RegisterAttached if you are interested in metadata on attached properties.
For details, see my answer to a similar question: Difference between Attached and non-Attached Dependency Properties in Silverlight
In my case RegisterAttached only set the bound field once, while Register worked dynamically as intended.
Taken from a scenario, where a Button in a List needed to show a preview on MouseHover and CommandParam was taken, already.
public static DependencyProperty MouseCommandParamProperty = DependencyProperty.Register(
"MouseCommandParam",
typeof(object),
typeof(MouseBehaviour),
new PropertyMetadata(defaultValue:null, new PropertyChangedCallback(MouseCommandParamChanged)));
public static void SetMouseCommandParam(DependencyObject target, object value)
{
target.SetValue(MouseBehaviour.MouseCommandParamProperty, value);
}
public static object GetMouseCommandParam(DependencyObject target)
{
return (object)target.GetValue(MouseBehaviour.MouseCommandParamProperty);
}
private static void MouseCommandParamChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
UIElement element = target as UIElement;
if (element != null)
{
element.SetValue(MouseBehaviour.MouseCommandParamProperty, e.NewValue);
}
}
Related
What's the difference between a (custom) dependency property and an attached property in WPF? What are the uses for each? How do the implementations typically differ?
Attached properties are a type of dependency property. The difference is in how they're used.
With an attached property, the property is defined on a class that isn't the same class for which it's being used. This is usually used for layout. Good examples are Panel.ZIndex or Grid.Row - you apply this to a control (ie: Button), but it's actually defined in Panel or Grid. The property is "attached" to the button's instance.
This allows a container, for example, to create properties that can be used on any UIelement.
As for implementation differences - it's basically just a matter of using Register vs. RegisterAttached when you define the property.
Abstract
Since I found little to no documentation on the matter, it took some poking around the source code, but here's an answer.
There is a difference between registering a dependency property as a regular and as an attached property, other than a "philosophical" one (regular properties are intended to be used by the declaring type and its deriving types, attached properties are intended to be used as extensions on arbitrary DependencyObject instances). "Philosophical", because, as #MarqueIV noticed in his comment to #ReedCopsey's answer, regular properties can also be used with arbitrary DependencyObject instances.
Moreover, I have to disagree with other answers stating that attached property is "type of dependency property", because it's misleading - there aren't any "types" of dependency properties. The framework doesn't care if the property was registered as attached or not - it's not even possible to determine (in the sense that this information is not recorded, because it's irrelevant). In fact, all properties are registered as if they were attached properties, but in case of regular ones some additional things are done that slightly modify their behavior.
Code excerpt
To save you the trouble of going through the source code yourself, here's a boiled down version of what happens.
When registering a property without metadata specified, calling
DependencyProperty.Register(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass))
yields exactly the same result as calling
DependencyProperty.RegisterAttached(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass))
However, when specifying metadata, calling
DependencyProperty.Register(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass),
typeMetadata: new FrameworkPropertyMetadata
{
CoerceValueCallback = CoerceCallback,
DefaultValue = "default value",
PropertyChangedCallback = ChangedCallback
});
is equivalent to calling
var property = DependencyProperty.RegisterAttached(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass),
defaultMetadata: new PropertyMetadata
{
DefaultValue = "default value",
});
property.OverrideMetadata(
forType: typeof(MyClass),
typeMetadata: new FrameworkPropertyMetadata
{
CoerceValueCallback = CoerceCallback,
DefaultValue = "default value",
PropertyChangedCallback = ChangedCallback
});
Conclusions
The key (and only) difference between regular and attached dependency properties is the default metadata available through DependencyProperty.DefaultMetadata property. This is even mentioned in the Remarks section:
For nonattached properties, the metadata type returned by this property cannot be cast to derived types of PropertyMetadata type, even if the property was originally registered with a derived metadata type. If you want the originally registered metadata including its original possibly derived metadata type, call GetMetadata(Type) instead, passing the original registering type as a parameter.
For attached properties, the type of the metadata returned by this property will match the type given in the original RegisterAttached registration method.
This is clearly visible in the provided code. Little hints are also hidden in the registering methods, i.e. for RegisterAttached the metadata parameter is named defaultMetadata, whereas for Register it is named typeMetadata. For attached properties the provided metadata becomes the default metadata. In case of regular properties however, the default metadata is always a fresh instance of PropertyMetadata with only DefaultValue set (either from provided metadata or automatically). Only the subsequent call to OverrideMetadata actually uses the provided metadata.
Consequences
The main practical difference is that in case of regular properties the CoerceValueCallback and PropertyChangedCallback are applicable only for types derived from the type declared as the owner type, and for attached properties they're applicable for all types. E.g. in this scenario:
var d = new DependencyObject();
d.SetValue(SomeClass.SomeProperty, "some value");
the registered PropertyChangedCallback will be called if the property was registered as an attached property, but will not be called if it was registered as a regular property. Same goes to CoerceValueCallback.
A secondary difference stems from the fact that OverrideMetadata requires that supplied type derives from DependencyObject. In practice it means that the owner type for regular properties must derive from DependencyObject, whereas for attached properties in can be any type (including static classes, structs, enums, delegates, etc.).
Supplement
Besides #MarqueIV's suggestion, on several occasions I've come across opinions that regular and attached properties differ in the way they can be used in XAML. Namely, that regular properties require implicit name syntax as opposed to explicit name syntax required by attached properties. This is technically not true, although in practice it usually is the case. For clarity:
<!-- Implicit property name -->
<ns:SomeClass SomeProperty="some value" />
<!-- Explicit property name -->
<DependencyObject ns:SomeClass.SomeProperty="some value" />
In pure XAML, the only rules governing the usage of these syntaxes are the following:
Implicit name syntax can be used on an element if and only if the class that this element represents has a CLR property of that name
Explicit name syntax can be used on an element if and only if the class specified by the first part of the full name exposes appropriate static get/set methods (referred to as accessors) with names matching the second part of the full name
Satisfying these conditions enables you to use corresponding syntax regardless of whether the backing dependency property was registered as regular or attached.
Now the mentioned misconception is caused by the fact that vast majority of tutorials (together with stock Visual Studio code snippets) instruct you to use CLR property for regular dependency properties, and get/set accessors for attached ones. But there's nothing stopping you from using both at the same time, allowing you to use whichever syntax you prefer.
Attached properties are basically meant for the container elements.like if you have a grid and you have grid.row now this is considered to be an attached property of a grid element.also you can use this property in texbox,button etc to set its place in the grid.
Dependency property is like the property basically belongs to some other class and is used in other class.
eg: like you have a rectangle
here height and width are regular properties of rectangle,but left and top are the dependency property as it belongs to Canvass class.
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.
I think you can defined attached property in the class itself or you can define it in another class. We always could use attached property to extend standard microsoft controls. But dependency property, you define it in your own custom control. e.g. You can inherit your control from a standard control, and define a dependency property in your own control and use it. This is equivalent to define an attached property, and use this attached property in the standard control.
I just discovered than I can do the following:
var button = new Button();
button.SetValue(TextBlock.TextProperty, "text");
var text = (string)button.GetValue(TextBlock.TextProperty); // text is "text"
While the above example is a bit unrealistic, it does show that I can attach a regular dependency property onto another object. It doesn't have to be a an attached property (TextBlock.TextProperty is not registerd with DependencyProperty.RegisterAttached().
This bares the questions why are there attached properties in the first place? The only difference I can see for now ist that I can't attach regular dependency properties in XAML. But that's about it. Are there any other differences?
Update:
To make it more clear, the below code works and looks pretty close to an attached property from the end users perspective:
public static class AttachedPropertyDeclarer
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(Button),
new PropertyMetadata(default(string),OnTextChanged));
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// do something when text changed
}
}
...
button.SetValue(AttachedPropertyDeclarer.TextProperty, "text");
var text = (string)button.GetValue(AttachedPropertyDeclarer.TextProperty);
Compare this to the attached property way:
public static class AttachedPropertyDeclarer
{
public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached(
"Text",
typeof(string),
typeof(AttachedPropertyDeclarer),
new PropertyMetadata(default(string),OnTextChanged));
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// do something when text changed
}
}
The only effective differnce to an attached property here is that I have to declare the owner of type Button whereas in a attached property it would usually be AttachedPropertyDeclarer. But this only needs to be done if I need a changed event handler (i.e. OnTextChanged).
Regarding your example, you have not as you say, attached a regular dependency property onto another object. All your code has achieved is to store a string value in a Dictionary along with a reference to your object. That does not make it an Attached Property - importantly, you cannot access that string value from the Button directly, as there is no Text property on a Button.
What your code does is actually very similar to this:
Dictionary<object, object> values2 = new Dictionary<object, object>();
var button = new Button();
values2.Add(button, "text");
string text = values2[button].ToString();
Now to answer your question:
The main reason to declare an Attached Property is in order to add a property to a type that you didn't declare, thereby extending its functionality.
A great example of this would be to add a SelectedItems property to the ItemsControl or ListBox class. In doing so, we extend the current, or default functionality of the class. Another good example would be declaring an Attached Property that automatically brings added items into view (again in an ItemsControl or ListBox class).
UPDATE >>>
According to your comments, you seem to be refusing to accept the differences that I have outlined... you said:
There is literally no difference from the end users perspective except that I can't use it in XAML.
Firstly, do you not think that this is a huge difference?.. you won't be able to use it for data binding for a start. Furthermore, you keep saying that you can attach a property to a type that you haven't declared using a DependencyProperty, but you are 100% incorrect. You can reference an Attached Property directly in both code and XAML, while you can't reference what you are calling your attached property directly in either XAML or code.
All you are doing is storing a value in a Dictionary and you certainly don't need the overhead of a DependencyProperty to do that. There really is no comparison between doing that and declaring an Attached Property. From the Attached Properties Overview page on MSDN:
You might create an attached property when there is a reason to have a property setting mechanism available for classes other than the defining class.
Note the following part: a property setting mechanism
Adding values into a Dictionary is not a property setting mechanism. So again, you lose the ability to use your pretend Attached Property in Styles, Animations, Triggers, etc.
To clarify this situation for once and for all, you can develop a simple test project. Implement the IList SelectedItems Attached Property for a ListBox that I mentioned (you can find online tutorials for this) and then do the same using your pretend Attached Property (if it is even possible). The difference in the simplicity of development bewteen the two will clearly show you why you should use an Attached Property instead of a regular DependencyProperty.
If you look closely at dependency property identifier, all DP's are registered with class DependencyProperty and we pass the Owner class type and property name at time of registration.
Sample:
public static readonly DependencyProperty IsSpinningProperty =
DependencyProperty.Register(
"IsSpinning", typeof(Boolean), typeof(OwnerClass));
At time of registration it creates some unique hash code combining property name and owner class type to represent each DP uniquely.
So, when you set value for that DP on some object like in your case on Button, code flow is like this:
First it will get the unique value generated at time of registration of property and add the key value pair in private dictionary named _effectiveValues declared in class Dependency Object with Key set to unique hashcode at time of registration and value being the value set by user.
Note - No written documentation for this on MSDN but verified this by peeking into source code using reflector.
So, when you set the value from code behind it will work like I mentioned above because it does not validate before adding value in the dictionary if it belongs to that type or not and fetching value will get you the value from dictionary.
Not sure but might be constraint is there in XAML only where WPF guys enforced the type check. Sadly there is no written documentation for this on MSDN.
Attached properties are discovered, when you want to have control over an existing control, but dont want to extend it. A pretty good example is, there is no way to bind BlackOutDates property in XAML for WPF DatePicker. In that case you can use an Attached Property to attach a custom functionality to map the BlackOutDates. This suits good in MVVM, since attached properties provided way for binding in XAML.
public class BlackOutDatesAdapter
{
public static List<DateTime> GetBlackOutDates(DependencyObject obj)
{
return (List<DateTime>)obj.GetValue(BlackOutDatesProperty);
}
public static void SetBlackOutDates(DependencyObject obj, List<DateTime> value)
{
obj.SetValue(BlackOutDatesProperty, value);
}
// Using a DependencyProperty as the backing store for BlackOutDates. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BlackOutDatesProperty =
DependencyProperty.RegisterAttached("BlackOutDates", typeof(List<DateTime>), typeof(BlackOutDatesAdapter), new PropertyMetadata(null, OnBlackOutDatesChanged));
private static void OnBlackOutDatesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var control = sender as DatePicker;
var list = (List<DateTime>)e.NewValue;
foreach(var date in list)
{
control.BlackoutDates.Add(new CalendarDateRange(date));
}
}
}
Binding in XAML will look like this,
<DatePicker VerticalAlignment="Center"
Width="200"
local:BlackOutDatesAdapter.BlackOutDates="{Binding BlackOutDates}"
DisplayDate="{Binding DisplayDate}" />
In the callback of property, you can do your own mapping of adding the dates to DatePicker. For more information, please read this post.
What's the difference between a (custom) dependency property and an attached property in WPF? What are the uses for each? How do the implementations typically differ?
Attached properties are a type of dependency property. The difference is in how they're used.
With an attached property, the property is defined on a class that isn't the same class for which it's being used. This is usually used for layout. Good examples are Panel.ZIndex or Grid.Row - you apply this to a control (ie: Button), but it's actually defined in Panel or Grid. The property is "attached" to the button's instance.
This allows a container, for example, to create properties that can be used on any UIelement.
As for implementation differences - it's basically just a matter of using Register vs. RegisterAttached when you define the property.
Abstract
Since I found little to no documentation on the matter, it took some poking around the source code, but here's an answer.
There is a difference between registering a dependency property as a regular and as an attached property, other than a "philosophical" one (regular properties are intended to be used by the declaring type and its deriving types, attached properties are intended to be used as extensions on arbitrary DependencyObject instances). "Philosophical", because, as #MarqueIV noticed in his comment to #ReedCopsey's answer, regular properties can also be used with arbitrary DependencyObject instances.
Moreover, I have to disagree with other answers stating that attached property is "type of dependency property", because it's misleading - there aren't any "types" of dependency properties. The framework doesn't care if the property was registered as attached or not - it's not even possible to determine (in the sense that this information is not recorded, because it's irrelevant). In fact, all properties are registered as if they were attached properties, but in case of regular ones some additional things are done that slightly modify their behavior.
Code excerpt
To save you the trouble of going through the source code yourself, here's a boiled down version of what happens.
When registering a property without metadata specified, calling
DependencyProperty.Register(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass))
yields exactly the same result as calling
DependencyProperty.RegisterAttached(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass))
However, when specifying metadata, calling
DependencyProperty.Register(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass),
typeMetadata: new FrameworkPropertyMetadata
{
CoerceValueCallback = CoerceCallback,
DefaultValue = "default value",
PropertyChangedCallback = ChangedCallback
});
is equivalent to calling
var property = DependencyProperty.RegisterAttached(
name: "MyProperty",
propertyType: typeof(object),
ownerType: typeof(MyClass),
defaultMetadata: new PropertyMetadata
{
DefaultValue = "default value",
});
property.OverrideMetadata(
forType: typeof(MyClass),
typeMetadata: new FrameworkPropertyMetadata
{
CoerceValueCallback = CoerceCallback,
DefaultValue = "default value",
PropertyChangedCallback = ChangedCallback
});
Conclusions
The key (and only) difference between regular and attached dependency properties is the default metadata available through DependencyProperty.DefaultMetadata property. This is even mentioned in the Remarks section:
For nonattached properties, the metadata type returned by this property cannot be cast to derived types of PropertyMetadata type, even if the property was originally registered with a derived metadata type. If you want the originally registered metadata including its original possibly derived metadata type, call GetMetadata(Type) instead, passing the original registering type as a parameter.
For attached properties, the type of the metadata returned by this property will match the type given in the original RegisterAttached registration method.
This is clearly visible in the provided code. Little hints are also hidden in the registering methods, i.e. for RegisterAttached the metadata parameter is named defaultMetadata, whereas for Register it is named typeMetadata. For attached properties the provided metadata becomes the default metadata. In case of regular properties however, the default metadata is always a fresh instance of PropertyMetadata with only DefaultValue set (either from provided metadata or automatically). Only the subsequent call to OverrideMetadata actually uses the provided metadata.
Consequences
The main practical difference is that in case of regular properties the CoerceValueCallback and PropertyChangedCallback are applicable only for types derived from the type declared as the owner type, and for attached properties they're applicable for all types. E.g. in this scenario:
var d = new DependencyObject();
d.SetValue(SomeClass.SomeProperty, "some value");
the registered PropertyChangedCallback will be called if the property was registered as an attached property, but will not be called if it was registered as a regular property. Same goes to CoerceValueCallback.
A secondary difference stems from the fact that OverrideMetadata requires that supplied type derives from DependencyObject. In practice it means that the owner type for regular properties must derive from DependencyObject, whereas for attached properties in can be any type (including static classes, structs, enums, delegates, etc.).
Supplement
Besides #MarqueIV's suggestion, on several occasions I've come across opinions that regular and attached properties differ in the way they can be used in XAML. Namely, that regular properties require implicit name syntax as opposed to explicit name syntax required by attached properties. This is technically not true, although in practice it usually is the case. For clarity:
<!-- Implicit property name -->
<ns:SomeClass SomeProperty="some value" />
<!-- Explicit property name -->
<DependencyObject ns:SomeClass.SomeProperty="some value" />
In pure XAML, the only rules governing the usage of these syntaxes are the following:
Implicit name syntax can be used on an element if and only if the class that this element represents has a CLR property of that name
Explicit name syntax can be used on an element if and only if the class specified by the first part of the full name exposes appropriate static get/set methods (referred to as accessors) with names matching the second part of the full name
Satisfying these conditions enables you to use corresponding syntax regardless of whether the backing dependency property was registered as regular or attached.
Now the mentioned misconception is caused by the fact that vast majority of tutorials (together with stock Visual Studio code snippets) instruct you to use CLR property for regular dependency properties, and get/set accessors for attached ones. But there's nothing stopping you from using both at the same time, allowing you to use whichever syntax you prefer.
Attached properties are basically meant for the container elements.like if you have a grid and you have grid.row now this is considered to be an attached property of a grid element.also you can use this property in texbox,button etc to set its place in the grid.
Dependency property is like the property basically belongs to some other class and is used in other class.
eg: like you have a rectangle
here height and width are regular properties of rectangle,but left and top are the dependency property as it belongs to Canvass class.
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.
I think you can defined attached property in the class itself or you can define it in another class. We always could use attached property to extend standard microsoft controls. But dependency property, you define it in your own custom control. e.g. You can inherit your control from a standard control, and define a dependency property in your own control and use it. This is equivalent to define an attached property, and use this attached property in the standard control.
I'm a little bit unclear with all this magic.
As I understood dependency properties get inherited from the DependencyObject, so values are stored:
in the instance itself if value is assigned (in the local dictionary)
or taken from the link to a parent element if value is not specified.
protected object GetValue(string propertyName)
{
if (LocalValues.ContainsKey(propertyName))
{
return LocalValues[propertyName];
}
return Parent.GetValue(propertyName);
}
Am I correct in this?
I also don't understand where are values for attached properties stored?
Control.FontSizeProperty = TextElement.FontSizeProperty.AddOwner(
typeof(Control), new FrameworkPropertyMetadata(SystemFonts.MessageFontSize,
FrameworkPropertyMetadataOptions.Inherits));
Does AddOwner method call on Attached property assigns value to the instance field? When does this happen and where does the value go?
Thanks!
Values for dependency properties are stored inside the objects (derived from DependencyObject) which we apply a property value to.
Let's take your TextElement.FontSizeProperty attached property for example:
<StackPanel TextElement.FontSize="20" ... >
...
</StackPanel>
XAML parser translates it to the following:
...
TextElement.SetFontSize(stackPanel, 20);
...
which is internally:
public static void SetFontSize(DependencyObject element, double value)
{
element.SetValue(TextElement.FontSizeProperty, value);
}
So, setting TextElement.FontSize on a stackPanel object is the same as calling
stackPanel.SetValue(TextElement.FontSizeProperty, value)
SetValue() is a method defined in the DependencyObject class. Inside the method many complex things happen, but in the end the effective value of a dependency property is wrapped in a structure called EffectiveValueEntry and stored in the following instance field inside DependencyObject:
private EffectiveValueEntry[] _effectiveValues;
The property system in WPF is pretty complex. MSDN really has a lot of information, but it is often hard to find. While there are many ways a DependencyProperty can be set, I'm not sure that you need to care where the values are stored.
For local values, you can assume that it is stored on the DependencyObject (again you shouldn't care where it is stored), with the caveat that they are not stored based on strings. It truly is associated with an instance of DependencyProperty. This is why you would want to add an owner to the property. If somebody sets TextElement.FontSize on your control, it is just like setting your local FontSize property.
As far as inheriting values for a property from a parent, this only happens with attached properties. From the MSDN entry for FrameworkPropertyMetadataOptions:
Although property value inheritance might appear to work for
nonattached dependency properties, the inheritance behavior for a
nonattached property through certain element boundaries in the runtime
tree is undefined. Always use RegisterAttached to register properties
where you specify Inherits in the metadata.
Is there a way to know the first time a Dependency Property is accessed through XAML binding so I can actually "render" the value of the property when needed?
I have an object (class derived from Control) that has several PointCollection Dependency Properties that may contain 100's or 1000's of points. Each property may arrange the points differently for use in different types shapes (Polyline, Polygon, etc - its more complicated then this, but you get the idea). Via a Template different XAML objects use TemplateBinding to access these properties. Since my object uses a Template I never know what XAML shapes may be in use for my object - so I never know what Properties they may or may not bind to. I'd like to only fill-in these PointCollections when they are actually needed.
Normally in .NET I'd but some logic in the Property's getter, but these are bypassed by XAML data binding.
I need a WPF AND Silverlight compatible solution.
I'd love a solution that avoids any additional complexities for the users of my object.
Update
One way that I've found to do this is using Value Converters. In my situation I had multiple point collections. There was a main dep. property that contained the usual shape of the data. Two alternate shapes were needed for reuse in other areas/contexts.
At first I had 3 dep. props. But, I could have just had one property (the usual shape) and used a value converted to transform the points into my other 2 desired shapes. Doing this I only make the one set of points in the control. The expense of transforming points to the secondary shapes is only incurred when used. Now my main control doesn't need to anticipate how data needs to look for every possible template thrown at the control - now its the template designers problem.
Update 2
Certainly INotifyPropertyChanged and regular properties are the recommended way to handle this.
You don't necessarily have to use dependency properties to enable data-binding. However, you then have to implement INotifyPropertyChanged if changes at the source should be propagated to the target of the binding. A "normal" .NET property is easy to lazy load perhaps like this:
PointCollection points
public PointCollection Points {
get {
return this.points ?? (this.points = CreatePoints());
}
}
PointCollection CreatePoints() {
// ...
}
I'm not sure how you can fit INotifyPropertyChanged into your control, but it sounds a bit strange that your control supplies data to other parts of the system. Perhaps you need to create a view-model containing the data that you then can let your control data-bind to.
If I paraphrase your question to
How do I get notified when dependency property is changed?
will this be correct? I draw this from your phrase "Normally in .NET I'd but some logic in the Property's getter, but these are bypassed by XAML data binding".
If I'm correct, then you can register your own property changed callback. It's always called. Doesn't matter who caused the change binding, style or trigger. The following code snippet is taken from MSDN Article "Dependency Property Callbacks and Validation":
public static readonly DependencyProperty CurrentReadingProperty =
DependencyProperty.Register(
"CurrentReading",
typeof(double),
typeof(Gauge),
new FrameworkPropertyMetadata(
Double.NaN,
FrameworkPropertyMetadataOptions.AffectsMeasure,
new PropertyChangedCallback(OnCurrentReadingChanged),
new CoerceValueCallback(CoerceCurrentReading)
),
new ValidateValueCallback(IsValidReading)
);
public double CurrentReading
{
get { return (double)GetValue(CurrentReadingProperty); }
set { SetValue(CurrentReadingProperty, value); }
}
Your takeaway here is OnCurrentReadingChanged() method. Hope this helps :).