How to determine that given ambient property value (BackColor for example) was inherited from parent control or was set elsewhere?
Related
I've been trying to interpret the XAML code in a project I've inherited and I want to figure out where some of the values are coming from in certain elements. When I look at an object's properties in the Properties panel, I can see squares next to each property. A white square indicates that the property value is the default, a black square indicates that the property value is "local" meaning it has been changed from the default and that change can be seen in the XAML tag, and a green square means "ambient."
There are styles applied to the objects so I can sort of intuit that the values in ambient properties must come from resource dictionaries. I'm still unsure where to look for the source of the values, which I want to do in order to change them. The documentation for ambient properties is hard for me to follow and doesn't answer all my questions, and I haven't found any documentation discussing the differences between default, local, and ambient.
If this is an appropriate place to ask, can someone explain and discuss the differences between default, local, and ambient?
Is there a word used to distinguish between these types of property values, i.e. is "default" a property value "type" or what?
And are there any property value types beyond those three?
My, what a charming profile you have. ;)
I just want to mention that you can get some information about the source of a dependency property's value using the static helper method DependencyPropertyHelper.GetValueSource(DependencyObject, DependencyProperty) in the System.Windows namespace.
"Default" essentially means that no source has been specified and so the value is taken from some built-in source. Note that some default values are dynamically generated and not constant. "Local" is when the value is explicitly set in that specific dependency object, overriding any values that it would otherwise inherit. "Ambient" is when the value is derived from some other source such as a style. I would refer to the distinction between these as different base value sources.
And yes, there are more than just those three. If you put the attribute TextBlock.FontFamily="Arial" in your Window tag for example, text blocks in that window will inherit that value from it. When you observe the property in the properties panel and roll over the box, it will say "Inherited." Note that the box is still green just like it is with "Ambient."
There is actually an enum that can help illuminate the various possible base value sources. It's called BaseValueSource.
One of the first things you learn when you working with WPF is the BindingMode enum:
OneWay: Updates the binding target (target) property when the binding source (source) changes.
OneWayToSource: Updates the source property when the target property changes.
TwoWay: Causes changes to either the source property or the target property to automatically update the other.
OneTime: Updates the binding target when the application starts or when the data context changes.
I wonder why there is no OneTimeToSource mode. Something like:
OneTimeToSource: Updates the binding source when the target changes.
I thought that this mode is not available for some particular reason (such as not breaking a specific pattern) but at the same time I also find this mode extremely useful, like establish the properties of the source from target (like config, for example) at the moment of coupling.
At least, I see it as a way to keep weakly coupled two structures and allow source to adapt to the target according to the properties of the target.
So, why is not there a 'OneTimeToSource' option in binding modes?
I wonder why there is no OneTimeToSource mode. Something like:
OneTimeToSource: Updates the binding source when the target changes.
The existig OneWayToSource works exactly like this, i.e. it updates the source property each time the target property is set to a new value.
Using a OneTimeToSource mode wouldn't make much sense as this would just set the source property to the default value of the target property once when the view was loaded for the first time.
Then it wouldn't be much of a point setting up the binding in the first place. This mode would for example set the string source property of a view model that was bound to a TextBox in the view to an empty string or a null reference which already is the default value for a string.
With respect to DependencyProperty which are not attached, it is my understanding -- and pls correct me if I am wrong as I am a beginner -- that the procees of resolution of local value is based on figuring out first, per a given DependencyProperty in question, what is the key of that DependencyProperty. The key is a hash code, or some unique value, representing the type of the owner of the DependencyProperty as well as the name of the property (e.g., background).
Once this key is calculated, the value resolution process proceeds to find a mtach for that key withing a dictionary which belongs to the parent type and which contains keys of DependencyProperty (just as explained in previous sentence) and corresponding values which were set locally with the DependencyProperty Set wrapper (e.g., SetBackground) corresponding to the DependencyProperty in question. If the key is found within the dictionary, then the local value is considered resolved and the value dound in the dictionary is the value we look for.
However, if the Set wrapper was not used before per the owner control such that the dictionary mentioned in previous paragraph (DependencyProperty keys and values) does not contain the key we seek to find, then the value resolution process proceeds to move up in the logical hierarchy to next parent control and apply the same resolution process with respect to the parent control. That is, a key composed of the parent type and the same name of the property is sought in the key/values dictionary belonging to the parent control. If it's found this time, then resolution is complete; otherwise, the local value resolution proceeds to the next control in the logical hierarchy, and the process repeats on itself, until the DependencyProperty's value is resolved. If no value is found, a different way of determination is employed that is not dependent on setting the value locally.
This is more or less the process for DependencyProperty which is not attached. I was wondering if anyone could tell me what is the value resolution process (of local value) per such property. I assume that the key value dictionary is one which resides in an external control (i.e., not the control in which the DependencyProperty resides), correct ? This might be the dictionary into which values are stored(using the Set[Proeprtyname]) with respect to DependencyProperty whose parent is that external control (which must be static).
Much appreciation if anyone can shed some more light about the Attached DependencyProperty.
Attached properties do not cascade. That is, if you don't explicitly set the value on the control, then it defaults to the DefaultValue defined in the property definition.
IS attached properties enable to modify the properties of a root element or parent element in the logical tree in any one of the child .
Just wanted to check whether I have understood it right ?
Well an attached property is nothing more than a value you can attach to a DependencyObject. You can however handle value changed, of the attached property, in order to run your specific logic (this is also called attached behaviors).
The short answer yes.
I derived the StackPanel class in a OrderableStack Class.
My aim is to allow a Stack's child to set an attached property Named 'First' to true and so this child becomes the first element in the stack.
When the attached property is set to true, the PropertyChangedCallback procedure defined in Metadata is called and it first removes the child element from the stack , then inserts it at position 0. Finally all the other children have their 'First' attached property set to False.
It works , but :
-if the attached property is already defined in xaml when i display it in VS 2010, VS 2010 is indicating that 'a reference is not set...'
-i can check that every other child, except the one defined as 'first' , has its OrderableStack.First set to false in the Properties Window, but the xaml is not updated. So many children can have the OrderableStack.First attached property set to true (in XAML), even if actually only the last child to be set has the True value.
Could you help me?
if the attached property is already defined in xaml when i display it in VS 2010, VS 2010 is indicating that 'a reference is not set...'
Does this stop you from building and running your app? The way you can avoid this "designer" error is to put some nullability checks around your attached property's PropertyChangedCallback code.
i can check that every other child, except the one defined as 'first'
, has its OrderableStack.First set to false in the Properties Window,
but the xaml is not updated.
I didnt get that last bit. Do you expect your XAML designer to "simulate" the ordering in design mode? Then the best candidate designer is XAML Pad or Expression Blend. Visual Studio designers are sadly not the best out there. They also do not "simulate" animations / triggers.
I hope this helps.