Difference between Attached and non-Attached Dependency Properties in Silverlight - c#

Okay Stackers, I've spent a good couple of hours on this question, and I want to know if anybody has a definitive answer.
For all the research I've done, I can't find ANY difference between .Register and .RegisterAttached in Silverlight. Now, before you jump the gun and tell me that .RegisterAttached is used for attaching a DP to another class, try implementing an Attached Dependency Property using DependencyProperty.Register(). I have found not a single difference, and so I am at a loss as to what the difference is.
Furthermore, in my specific case, I'm attempting to extend the functionality of the Grid class, and want to give it some extra properties. As such, I've tried listing passing both typeof(Grid) and typeof(FluidLayoutManager) (the implementing class) as the ownerType parameter and it also seems to make very little difference... (I believe it does make a difference when I pass two custom classes from the same namespace. However when passing a Microsoft defined class vs. a custom class, I always have it showing up in the XAML as a DP of the custom class.)
Any clarification on this topic would be much appreciated, as I'm sitting here scratching my head, and wondering if there is any difference at all, or if Microsoft is just screwing with me once again.

Given the discussions flowing in comments I will try to do this one in plain English:
The main difference between Attached Dependency Properties and Dependency Properties (and therefore between .Register and .RegisterAttached) is that RegisterAttached allows the value to be assigned to any dependency object whereas Register only allows it to be attached to the class passed as the ownerType parameter.
As Haris Hasan mentions (deep in the comment thread), your example is using the only type allowed (i.e. CustomControl) and does not show you that the Attached version can be assigned to ANY dependency object.
e.g. you can do this with your Attached Dependency Property (but not a plain DP):
<Grid local:AttacherClass.ADP1="1" x:Name="LayoutRoot" Background="White">
</Grid>
The best reference for ADPs I can find is this one: http://msdn.microsoft.com/en-us/library/ms749011.aspx
We used ADPs as the basis of a localisation system, so that translations could be parasited onto objects during load rather than using horrendously long bindings. Couldn't do that with DPs
Update:
I would also like to clarify that the parent limitation applies to XAML based use of the attribute. From code the parent limitation apparently does not apply.

It is wrong to believe that "RegisterAttached allows the value to be assigned to any dependency object whereas Register only allows it to be attached to the class passed as the ownerType parameter". Here is a perfectly working example of an attached property registered with Register:
class FooPropertyDeclaringType
{
public static readonly DependencyProperty FooProperty =
DependencyProperty.Register("Foo", typeof(int), typeof(FooPropertyDeclaringType));
}
class SomeUnrelatedType : DependencyObject { }
class Program
{
static void Main()
{
var obj = new SomeUnrelatedType();
obj.SetValue(FooPropertyDeclaringType.FooProperty, 10);
Debug.Assert(10 == (int)obj.GetValue(FooPropertyDeclaringType.FooProperty));
}
}
Reflector shows that the only difference between Register and RegisterAttached is that the Register throws out much of the supplied metadata and only preserves it for the instances of registering class (via OverrideMetadata). It means that attributes such as Inherits and various update notifications usually specified in the metadata do not work on properties registered with Register and attached to objects of other types (other than the registering type). So Register is actually a stripped down version of RegisterAttached. It was probably made this way for performance reasons.
In the example linked by Haris Hasan in the comments to his answer, if you change RegisterAttached to Register, the buttons stop moving (because the property no longer provides AffectsParentArrange metadata for Button type) but they are nevertheless redrawn in their new locations when you resize the window. But if you add the same metadata to the Button type after a call to InitializeComponent():
RadialPanel.AngleProperty.OverrideMetadata(
typeof(Button),
new FrameworkPropertyMetadata(
0.0, FrameworkPropertyMetadataOptions.AffectsParentArrange));
then everything works again as if RegisterAttached was called.

They might not be much different as far as implementation is concerned but they are difference in actions i.e. they are different in what they do and are used for.
Simple Register is used for simple dependency properties which you usually are used for bindings and validations so they are normal CLR properties with some additional magic which helps in WPF
RegisterAttached is normally used where you want to expose a property that can be accessed and set in the child class like DockPanel where children of control tells parent where they want to be placed using Dock.Left or Dock.Right. So they are kind of special dependency properties which can be accessed in the child controls (which is not the case with simple Register properties) and they(in case of DockPanel) helps parent control in displaying children
In short one cay say Register is used registering dependency properties which are used in same class while RegisterAttached is used for registering special dependency properties called attached properties and they are used and accessed by classes other than one which defined it
This is a good explanation of Attached Properties and what cannot be achieved through simple DP

If you register with RegisterAttached, it becomes global as a property in the store of any DependencyObject, i.e. you could SetValue on any Dependency Object
If you use Register when Get/Setvalue are called there will be a check that the call is prom an object that is castable to the registering type.
An Example of a property that behaves like RegisterAttached is Grid.Row and Grid.Column.

So exactly what is 'ownerType' used for in RegisterAttached? This issue has been nagging at me for a few years, so I finally took a closer look at 4.6.1 code in WindowsBase.
For any DependencyProperty, attached or otherwise, what it eventually comes down to is what type of PropertyDescriptor WPF obtains for late-bound XAML access, and this isn't determined until the first time (on a per type/property pairing basis) such access is attempted. This deferral is necessary because PropertyDescriptor encapsulates a property bound to a specific type, whereas the point of attached properties is to avoid exactly this.
By the time XAML access occurs, the Register(...) versus RegisterAttached(...) distinction has been lost to the mists of (run)time. As others have noted on this page, 'DependencyProperty' itself doesn't encode a distinction between an attached vs. non- variety. Every DP is assumed to be eligible for either usage, subject only to what can be figured out at runtime.
For example, the .NET code below seems to rely on not finding a matching instance property on the 'tOwner' type as the first requirement for allowing attached access. To confirm this diagnosis, it then checks whether 'tOwner' exposes one of the static access methods. This is a vague check insofar as it doesn't verify the method signatures. Those signatures only matter for XAML access; all actual runtime targets for the attached property must be DependencyObjects, which WPF accesses through DependencyObject.GetValue/SetValue whenever possible. (The VS Designer reportedly does use the static accessors, and your XAML won't compile without them)
The relevant .NET code is the static function DependencyPropertyDescriptor.FromProperty, shown here with my own comments (summary below):
internal static DependencyPropertyDescriptor FromProperty(DependencyProperty dp, Type tOwner, Type tTarget, bool _)
{
/// 1. 'tOwner' must define a true CLR property, as obtained via reflection,
/// in order to obtain a normal (i.e. non-attached) DependencyProperty
if (tOwner.GetProperty(dp.Name) != null)
{
DependencyPropertyDescriptor dpd;
var dict = descriptor_cache;
lock (dict)
if (dict.TryGetValue(dp, out dpd))
return dpd;
dpd = new DependencyPropertyDescriptor(null, dp.Name, tTarget, dp, false);
lock (dict)
dict[dp] = dpd;
/// 2. Exiting here means that, if instance properties are defined on tOwner,
/// you will *never* get the attached property descriptor. Furthermore,
/// static Get/Set accessors, if any, will be ignored in favor of those instance
/// accessors, even when calling 'RegisterAttached'
return dpd;
}
/// 3. To obtain an attached DependencyProperty, 'tOwner' must define a public,
/// static 'get' or 'set' accessor (or both).
if ((tOwner.GetMethod("Get" + dp.Name) == null) && (tOwner.GetMethod("Set" + dp.Name) == null))
return null;
/// 4. If we are able to get a descriptor for the attached property, it is a
/// DependencyObjectPropertyDescriptor. This type and DependencyPropertyDescriptor
/// both derive directly from ComponentModel.PropertyDescriptor so they share
/// no 'is-a' relation.
var dopd = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, tTarget);
/// 5. Note: If the this line returns null, FromProperty isn't called below (new C# syntax)
/// 6. FromProperty() uses the distinction between descriptor types mentioned in (4.)
/// to configure 'IsAttached' on the returned DependencyProperty, so success here is
/// the only way attached property operations can succeed.
return dopd?.FromProperty(dopd);
}
Summary: When calling RegisterAttached to create an attached DependencyProperty, the only thing 'ownerType' is used for is to identify a type which defines appropriate static Get/Set accessors. At least one of those accessors must exist on 'ownerType' or XAML attached access will not compile or silently fail. Although RegisterAttached does not fail in this case, and instead successfully returns a defunct DP. For DPs intended for attached use only, 'tOwner' doesn't have to derive from DependencyObject. You can use any regular .NET class, static or non-static, and in fact can even be a struct!

Related

How to override a dependency properties in a generic class?

So I have a class; lets use the ScrollViewer class as an example. It has a dependency property called Content which accepts anything of type System.Object, great!
Let's say I derive a class from ScrollViewer, lets call it ZoomScrollViewer, it adds some basic zooming and panning using the mouse with a keyboard press. It also adds a dependency property of it's own, AutoscaleContent.
Now, I want to be able to put a ZoomScrollViewer into a UI window, but I only want it to accept a Canvas as it's content. Naturally, I go about creating a ZoomScrollViewer<T> class.
However, how can I change the Content property so that only accepts elements of type <T>? Can I override the dependency property? I got a little confused and tried:
public new T Content
{
get { return (T)base.Content; }
set { base.Content = value; }
}
But of course this makes it no longer a dependency property, so all the XAML code fails when I set up the bindings.
Edit: It should also be noted that I've taken a look at using:
ZoomScrollViewer.ContentProperty.OverrideMetadata(typeof(ZoomScrollControl2<T>), new PropertyMetadata(...?));
To see if I could do anything using that, but it seems you can only override the default value, unless I'm missing something?
Update: I've now tried using the following:
public class ZoomScrollControl2<T> : ZoomScrollViewer where T : FrameworkElement
{
static ZoomScrollControl2()
{
ContentProperty.OverrideMetadata(typeof(ZoomScrollControl2<T>), new FrameworkPropertyMetadata(typeof(ZoomScrollControl2<T>)));
}
}
public class CanvasZoomControl : ZoomScrollControl2<Canvas>
{
}
Which I thought would work, but it still seems to accept a Content of any type.
Update: In short I'm not sure if what I want to do is even possible, so I've marked the discussion as the answer, even though it isn't an answer per-se.
I suggest to try that approach as it suggested by this MSDN article.
It should override the referal type, so you can refer to it using derived type.
Dependency Property visibility is not made esplicit in .NET Framework for derived types, as searching right property among the types tree has a cost in terms of performance, and considering that we use DP on UI binding, it can lead to non desirable performance issues.

Do INotifyPropertyChanged users use reflection to fish out the value from the actual property?

When I implement INotifyPropertyChanged does the code using the event use reflection to fish out the value from the actual property? Or use it use something other than reflection like IL emit?
No, because the PropertyChangedEventArgs raised by the event only contains the sender of the event and the name of the property which changed on the sender. If you would like access to the old or new value, you must retrieve them on your own.
As for what the Framework uses to determine what the value is currently, that will depend on the context used (one option is a PropertyDescriptor from a TypeDescriptor).
If you're talking about how the WPF data binding infrastructure gets to the data, it does some fairly sophisticated things. I can only speak to what I've seen from the disassembled source as I last saw it, as these are implementation details and subject to change. For non-Dependency properties (the ones that are typically notified using INotifyPropertyChanged), the system uses Reflection internally, but caches the references. The Binding Path property string is represented as a PropertyPath and there is an internal PropertyPathWorker that does the work of parsing this path and setting up the actual binding. This creates a cached 'list' of references, since the property path can be rather complex, such as Something.SomeProperty[0].SubProperty.(Grid.Row). The binding system allows for any of the values along the chain to change and, if any of them changes, has to reevaluate the downstream references.
In short, it's designed to be efficient, but doesn't use Emit, as it has to support re-computation of the references based on changes inside a complex path. This can be further complicated by the dynamic nature of the binding, since the actual Type of a reference along the chain can change. For instance, Something may be of type Object, so any object that has a SomeProperty IList<T> property is a valid binding target. If the Type changes, it has to re-reflect to bind to the new property on the new Type.
The client code does whatever it wants to.
Typically, InotifyPropertyChanged is consumed by the databinding infrastructure, so it will get property values using PropertyDescriptors.
INotifyPropertyChanged does nothing but tells the class to raise event. When or which property will raise event depends on your code and how you implement it. You can use reflection or Attribute (ContextBoundObject) or can use attribute to inject IL code inside setter method of property

Extender provider for WPF

Is there an equivalent to the System.ComponentModel.IExtenderProvider geered toward WPF ?
Do I have to go toward Dependency Properties and Attached Properties to build an equivalent, or is there already something baked in the oven waiting for me ?
Thanks,
Patrick
The Attached Property is the way to go http://msdn.microsoft.com/en-us/library/ms749011.aspx
You can also use AttachedPropertyBrowsableForChildrenAttribute to tell a control to extend the newly created property to all its children (Has Grid's row property).
The WPF reader and writer for XAML have no awareness of the System.ComponentModel.Container concept used in Windows Forms. XAML deploys a comprehensive system of XamlType types, including XamlMember, XamlPropery, etc., all unified under a XamlSchemaContext, and which together represent a full-blown type system superimposed over--and largely independent of--the .NET type system (i.e., "reflection"). XAML "attached properties" are only defined by-and-within this universe and are therefore existentially confined to it.
While some of this is unrelated to System.ComponentModel really, it is indeed unfortunate that these two major architectural frameworks do not, in fact conspire, communicate, or collude to collectively correlate, conflate or co-opt the concepts they do contain in common.
The good news, however--and the reason for this tardy post, and the answer to your question--is that XamlServices does have extension points to address your scenario. Because all of those "Xaml..." type-types I mentioned above are represented by public classes that are not sealed and can be overridden. The starting point is to create your own customized XamlSchemaContext and override GetXamlType method to provide your own customized XamlType-derived objects wherever your situation requires.
XamlType is where you can intercept, modify, or inject, whatever attached property behavior you want. See the LookupAttachableMember or LookupAllAttachableMembers method overrides. A method in your XamlType implementation which might be of particular interest to override is XamlType.LookupInvoker(...), which allows you to supply a customized XamlTypeInvoker instance which, in turn, has a CreateInstance(...) override that can ultimately control any/all aspects of the instance(s) deployed to the resulting deserialized object graph.
In the extreme, XamlTypeInvoker.CreateInstance can substitute some or all of the XAML-resolved CLR types entirely, but this starts to defeat the larger purpose, since any such "replacement" CLR types--just like all CLR types instantiated by XamlServices--must always have a pre-existing CLR definition. In other words, what XAML does not do--but you could certainly add via this override!--is use reflection TypeBuilder etc., to synthesize new types or members that do not already have a CLR Type equivalent.
To be clear, this means that there's no way to get WPF to recognize any sort of putative "synthetic" customized type instance, nor data-bind to "virtual" runtime properties, via just manipulating XamlType or XamlMember alone.
Meanwhile, once you've overridden types and properties and other members to create your own derived XAML type system under your derived XamlSchemaContext, you can supply an instance of that schema to the XAML reader and writer methods in XamlServices.
You can pass your custom XAML schema context into the constructors for the standard XAML readers/writers, such as XamlXmlReader and XamlObjectWriter (for the so-called "load path" scenario; I won't discuss the "save path" here). More importantly, however, you can also override these two classes as well, and they provide a rich set of virtual methods to override. As a pseudo-code example (lifted from my working code), you can add a transform(...) method to your XamlXmlReader-derived class that provides full control of a XAML deserialized object result:
// ...in your class derived from 'XamlXmlReader'
public void transform(my_xaml_obj_writer xow)
{
while (base.Read())
{
if (xow.ShouldProvideLineInfo)
xow.SetLineInfo(LineNumber, LinePosition);
switch (NodeType)
{
case XamlNodeType.NamespaceDeclaration:
xow.WriteNamespace(base.Namespace);
break;
case XamlNodeType.StartObject:
xow.WriteStartObject(base.Type);
break;
case XamlNodeType.EndObject:
xow.inject_ctor_arg(); // <--- !! (not shown)
xow.WriteEndObject();
break;
case XamlNodeType.StartMember:
xow.inject_ctor_arg(); // <--- !! (not shown)
xow.WriteStartMember(base.Member);
break;
case XamlNodeType.EndMember:
xow.WriteEndMember();
break;
case XamlNodeType.GetObject:
xow.WriteGetObject();
break;
case XamlNodeType.Value:
xow.WriteValue(base.Value);
break;
case XamlNodeType.None:
break;
}
}
}
Using this custom reader, the process of deserializing XAML to an in-memory CLR object is something like this:
void XamlToObject(FileStream fs, my_xaml_schema_context ctx)
{
using (var xxr = new xaml_xml_reader(fs, ctx))
using (var xow = new my_obj_writer(this))
{
try
{
xxr.transform(xow);
}
catch (XamlObjectWriterException xex)
{
// ...
}
}
}
The resulting XAML "root object", the in-memory CLR object which is the whole point, will be found on the Result property of your overridden XamlObjectWriter at the end of this process. In my case, I actually snoop the result object out of the XAML node stream earlier during the transform method shown above, as soon as it is created, in order to see if it has the [UsableDuringInitialization] attribute, and accordingly enable certain concurrent uses while the deserialization is still in progress.
Finally note that XamlObjectWriterSettings and XamlXmlReaderSettings can also be overridden with your own derived classes, if you want to add additional settings. More commonly you might just need to do this in order to make additional custom data available to yourself, since with overridden methods in XamlServices you tend to sometimes find yourself deep within the bowels of a callback while seemingly having insufficient contextual information.

method overloading and polymorphism

I'm writing a .NET web application in which administrators can customize the various data entry forms presented to their users. There are about half a dozen different field types that admins can create and customize (i.e. text, numeric, dropdown, file upload). All fields share a set of base attributes/behaviors (is the field required? Will it have a default field value?). There are also a series of field specific attributes/behaviors (i.e dropdown has a data source attribute, but text field does not). I'm leaving out many other characteristics of the problem domain for simplicity's sake.
The class hierarchy is straightforward: An abstract superclass that encapsulates common behaviors/attributes and about half a dozen concrete subclasses that deal with field specific stuff.
Each field type is rendered (i.e. mapped to) as a specific type of .NET server control, all of which derive from System.Web.UI.Control.
I created the following code to map values between the field domain objects and their corresponding UI control:
public static void Bind(Control control, IList<DocumentFieldBase> fieldBaseList)
foreach (DocumentFieldBase fieldBase in fields){
if (typeof (DocumentFieldText).IsInstanceOfType(fieldBase)){
TextBox textbox = (TextBox) control;
textbox.Text = (fieldBase as DocumentFieldText).GetValue();
}
if (typeof (DocumentFieldDropDown).IsInstanceOfType(fieldBase)){
DropDown dropDown= (DropDown) control;
dropDown.Text = (fieldBase as DocumentFieldSelectOne).GetValue().Text;
dropDown.DataSource= (fieldBase as DocumentFieldSelectOne).DataSource;
dropDown.Id= (fieldBase as DocumentFieldSelectOne).GetValue().Id;
}
//more if statements left out for brevity
}
}
I want to ditch those ungodly if statements that perform type checking. The approach I was shooting for was to create a method overload for each combination of field/control using subclass typing. For example:
public static void Bind(TextBox control, DocumentFieldText fieldText){
//some implementation code
}
public static void Bind(DropDown control, DocumentFieldDropDown fieldDropDown){
//some implementation code
}
I was hoping that I could then rely on .NET to call the appropriate overload at runtime using the specific subclass being used: For example:
foreach (DocumentFieldBase field in fields){
Control control = FindControl(field.Identifier);
Bind(control, field)
}
Unfortunately, the compiler chokes when I try this:
Argument '1': cannot convert from 'System.Web.UI.Control' to 'TextBox'.
If I have to cast the first argument to TextBox, I'm back to performing type checking myself and defeats the whole purpose of this exercise.
Is what I'm trying to achieve a) possible and b) a good idea?
Prior to C# 4, all overloading is done at compile time. You have to use double dispatch or the visitor pattern to effectively overload at execution time, and that gets messy quickly.
In C# 4, you could declare a variable as dynamic and let it all get sorted out at execution time:
foreach (DocumentFieldBase field in fields){
dynamic control = FindControl(field.Identifier);
Bind(control, field)
}
Obviously that's not much help at the moment though (unless you're using VS2010b1).
One option is to use a map from Type to Action<object> but then you get inheritance issues... (you'd potentially have to keep working up the type hierarchy from the concrete type up to object until you found an entry in the map). You'd also still need to cast to the right type within the action :(
The "dispatch" tag on this question is quite appropriate: what you want is called "multiple dispatch". C# (like most mainstream languages) only supports "single dispatch", where the method to be executed is selected solely on the (runtime) type of the object you call the method on, not on the (runtime) type of its arguments.
The visitor pattern can often be used to work around this. The idea is that you give DocumentFieldBase a method (that you override in concrete subclasses) which calls a method on Control (also overridden in concrete subclasses) that does the actual work.
Unfortunately, the source code of the Control class is probably not under your control*... so you'll have to resort to an even more hackish solution. The accepted answer to this question provides one that uses reflection.
*Extension methods are just syntactic sugar for static methods, and are thus resolved at compile time and of no use in this scenario.
Couldn't you have an abstract, non-static Bind() method in DocumentFieldBase, then do the downcasting inside each concrete class's implementation of it? Each DocumentFieldBase class knows what type of Control it's getting, doesn't it?

Should you access a variable within the same class via a Property?

If you have a Property that gets and sets to an instance variable then normally you always use the Property from outside that class to access it.
My question is should you also always do so within the class? I've always used the Property if there is one, even within the class, but would like to hear some arguments for and against as to which is the most correct and why.
Or is it just a matter of coding standards being used on the project?
One of the stronger argument for accessing local (class scope) variables through properties is that you add a level of abstraction in your class. If you change any logic concerning how that field is stored then the rest of your code will be left unaffected.
For example you might change that from a local variable to a property of a child object, to a database call, to a webservice call, to a static property on a class and so on. When making the change it gives you a single point of change, the property, and you do not have to update the rest of your class since they all use the property.
Also using the property enables you to apply business rules on the value of the property instead of having to enforce the same rule at each location where you'd directly access the field. Again, encapsulation
With the introduction of automatic properties there's even less reason to explicitly have a local variable, unless you need to apply business rules on the get/set
It depends on whether you want to apply any logic implemented within the property setter, and so you really have to decide on a case by case basis.
When you go directly to the private field, you know that the field is being set to exactly what you say.
When you go through the Property, the value gets set according to the setter logic, so you get any business rules or validation you want over values assigned to that field.
Pretty hard to come up with a rule about when doing either is 'correct', about the only one I'd say I follow is that in constructor initialisation I'd pretty much never use the Property.
Yes I think you should use properties internally in your classes whenever possible. Properties are more flexible and allows you to add logic for validating it's value at a central place.
You can also delay the initialization of the the field to whenever the property is used instead of being forced to do it in the constructor (or everywhere the field is used). Example:
class Test {
private int _checksum = -1;
private int Checksum {
get {
if (_checksum == -1)
_checksum = calculateChecksum();
return checksum;
}
}
}
I think it's purely preference.
Though, I find myself using the properties a lot more in C# 3.0 with the auto-property support:
class Foo {
public string Value { get; set; }
public void Write() {
Console.Write(Value);
}
}
Generally depending on the project coding standards I use a "_" or "m" preceding the name for my private class attributes. (Like below)
private int mVariable;
private int _Variable;
With those in front of the variable I recognize right away that I'm dealing with an internal variable for the class. Then when it comes to debugging later myself or someone else can immediately recognize that the code is dealing with an internal private variable and make an adjustment. So it comes down to readability for me.
Always Use Properties, Here are some of the reasons
Easy to Use. In visual Studio you can use "Prop Tab Tab". You will get the property snippet
Properties are language elements that are accessed as though they are data members
.Net framework classes uses it, the data binding code classes in the .NET Framework support properties,
Properties have all the language features of methods. Properties can be virtual

Categories

Resources