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.
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 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.
If I am setting one dependency property equal to another dependency property, will they automatically get updated if one chagnes, or do I still need to bind them. Also if two dp are part of the same object (same type too) and I set them equal to each does the same apply as above, or only this case works and the one above doesn't?
will they automatically get updated if one chagnes, or do I still need to bind them
No. Each is a separate property, and setting one to the other just sets the value. If you want them to be "bound together" then you should create a binding that binds them together.
This is true whether they're in the same class or different classes.
I'm looking for a SL4 equivalent to .NET 4's SetCurrentValue API, which would appear to be exactly what I need for my scenario.
In short, I'm writing an attached behavior that updates the value of a given property at appropriate times. However, I don't want it to overwrite any bindings that are set on that dependency property. I merely want to push that value to the property (and therefore have any bindings refresh based on that value).
From what I can tell, there's no easy way to do this yet in SL4.
Thanks
Silverlight does not provide direct access to this level of dependency value. However its this level of value that Animations in storyboards set when they manipulate a property.
Hence a Storyboard with a 0 length duration containing a single DiscreteObjectKeyFrame might achieve your desired result.
I've managed to simulate what I'm after by detecting bindings and injecting a surrogate object between the source and target. I can then manipulate the surrogate and have both sides of the original binding refresh.
It's ugly and more work than I'd like, but it seems to work.
Kent