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.
Related
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?
I'm working on a WPF project and have implemented a very simple way to undo one level of change which works nicely throughout the project except for one case where changes to an object's property reflects in the MemberwiseClone.
What I am doing is to do a MemberwiseClone in my object before adding or editing properties in that object, and then if the user wants to undo, I copy each property from the MemberwiseClone object back into my current object.
Because I am using WPF binding, using the MemberwiseClone is attractive to me because up until now, any change made in a property was not reflected in the MemberwiseClone. This time I have a property in my object that is an ObservableCollection of another object, and what is happening is that if I add an item to the ObservableCollection, it also gets added to the object created by MemberwiseClone and I can never truly undo.
Is there any way around this? Any thoughts you might have on this are welcomed.
Thanks.
According to Object.MemberwiseClone Remarks the object references in your ObservableCollection will be copied but not the referenced object itself. Therefore your undo collection references the same possible changed objects.
You need a deep copy, not a shallow one. Take a look at How do you do a deep copy an object in .Net (C# specifically)?
I have an Address object in my model which has 6 address lines as separate properties. In my Silverlight view I want this to be displayed in a multiline text box and to be updated using databinding.
The View is linked to a ViewModel which has an Address property which is always set. My first thought was to use a ValueConverter which was initially fine as it could take an Address object and pass back a string which is displayed.
My problem arises when I want to ConvertBack the string. I wish to update the existing Address object but cannot find a way to do this. I think you can pass back a new Address object but this is not what I want to happen.
I am on the right track here or is there a better method than using a ValueConverter.
You are almost on the right track here! You are right in your observation that the ConvertBack method would need to create a new Address instance. You cannot obtain a reference back to the original address in your converter, the binding framework does not permit this kind of tight coupling.
How about using MVVM? create a ViewModel that exposes / adapts your Address as a string, basically performing the role of your value converter. When the TwoWay binding updates this string property, your ViewModel can then update the Address that it adapts.
So I think I understand what a dependency property is and why we need them - they are properties managed by the Silverlight/WPF libraries such that the runtime can have some control over how they are set, enabling them to do such things as giving animations precedence over other types of requests on the properties and other nifty features.
My question is, how does the framework know how to do this? If dependency properties are always accessed through their getters/setters on their parent objects (which defer to GetValue() and SetValue()) then how can the dependency repository* know who is making the request in order to prioritize it?
Sorry if this is a very basic/obvious question.
* Is there a name for the container that manages dependency properties? I'm thinking the DP registry, considering we have to register them?
Yes, there is a registry but its all hidden. And No, dependency properties are not at all set via Getter and Setter instead DependencyObject has methods called GetValue and SetValue where you actually pass handle to your dependency property. Assume your DP has registry and it has dictionary and handle to your DP (the DP object you get after registering) is key.
This way, registry knows when and what to modify and what to update and to whom it needs to send notifications.
You can use reflector to explore .NET's internal, you will get idea that every DP needs to be registered by calling DependencyProperty.Register then only you can use it.