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.
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.
Having to work with a legacy silverlight application I ran into a strange piece of code. The viewmodel has a List dependency property as binding source for the grid. This DP has a default value, an other List that is used globally in the app. This is used to easily share entity data between different parts of the application.
DependencyProperty MyEntitiesProperty = DependencyProperty.Register("MyEntities", typeof(List<Entity>), typeof(...), new PropertyMetadata(Global.Entities));
Now, when the list is changed (on user actions), the global list is repopulated from database but MyEntities is never set explicitly. This does not work: the grid (the binding target) never changes. So its a wrong solution.
I speculate that the idea behind all this could have been been the following: if you have a DP with a given value and you never set a local value for it then the effective value of the DP will be the default value. If the 'underlying' default value is changed, the changes are reflected in the effective value.
If it worked, it was a nice way of sharing data between independent viewmodels without fiddling with property change events and such.
What is wrong here? Is it a big misunderstanding of how DPs work or the idea was ok and some implementation details were missed?
Please comment if something is not clear.
Well, taking also your comment into account, it is a big misunderstanding of how DPs work. Let me explain:
Setting a globally known list as the default value of MyEntities might not be a pattern I recommend, but is technically not faulty and can be done to share a list. MyEntities now holds a reference to this very list.
If you now replace the global list with a new list instance, the old instance does not cease to exist. Your property MyEntities still holds a reference to the old list. The value of a DP is only updated automatically if it is bound via Binding to either an ordinary property that is wired with the INotifyPropertyChanged mechanism or another DP.
Setting a default value happens neither via a Binding to an ordinary property nor via a Binding to another DP, it is just a plain old object reference.
I can think of several ways to correct the situation:
First solution
If the global list implements INotifyCollectionChanged (e.g. ObservableCollection, DependencyObjectCollection) you can - instead of creating a new list instance - just delete the old items from the list and add the new items. The views that have a reference to the list will perform an update as soon as they receive the associated CollectionChanged event.
Second solution
Make sure the Global.Entities list is available and always up-to-date as a public property (wired with INotifyPropertyChanged) on the DataContext of the root view. Now when you want a nested view somewhere deep down inside the UI tree to be connected to this Global.Entities list you can bind it to the root view's DataContext' public list property.
<MyRootView>
... nested views spread across multiple files ...
<MyNestedEntitiesListDisplay
MyEntities="{Binding
Path=DataConext.GlobalEntities,
RelativeSource={RelativeSource AncestorType=MyRootView}}"/>
I guess I never thought to question it before, but it seems weird that you can store different values for a property on each instance of a control even though though the static property that was registered was only registered once. Is the property in the dictionary actually stored under another dictionary that keeps track of which object corresponds to which value of the property?
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.
When we use any attached property against any dependency object, I thunk it actually maps the property and the value with the dependency object.
E.g. <DockPanel><TextBlock x:Name="MyText" DockPanel.Dock="Top"/></DockPanel>
Here value "Top" is mapped with DockPanels DockProperty via the dependency object textblock "MyText"
But my question is when is this mapping disposed? The reason I am asking this is the DockPanel's DockProperty is static\shared. So it must be having such multiple mappings Pair (Of value, dependency object) maitained against it in some kind of internal dictionary. (just a guess)
So this must be garbage collected when the dependency object is destroyed.
So now my point is is there any way that I should know IF such attached property diposing is taking place (like some kind of dispairing or dispose event for the given attached property and dependency object)?
Also if such garbage collection doesnt take place then isnt this a memory leak?
Thx
Vinit Sankhe.
As I understand the new property system in the WPF, the DependecyObject itself stores the value.
In your example, this would be the textblock.
Don't get confused as you call a static member - it is supposed to be implemented like:
element.SetValue(DockPanel.TopProperty, value);
So there happens no static field storage.
I think it was created using WeakReference. So removing of empty references takes place periodically.