Is there a way to know the first time a Dependency Property is accessed through XAML binding so I can actually "render" the value of the property when needed?
I have an object (class derived from Control) that has several PointCollection Dependency Properties that may contain 100's or 1000's of points. Each property may arrange the points differently for use in different types shapes (Polyline, Polygon, etc - its more complicated then this, but you get the idea). Via a Template different XAML objects use TemplateBinding to access these properties. Since my object uses a Template I never know what XAML shapes may be in use for my object - so I never know what Properties they may or may not bind to. I'd like to only fill-in these PointCollections when they are actually needed.
Normally in .NET I'd but some logic in the Property's getter, but these are bypassed by XAML data binding.
I need a WPF AND Silverlight compatible solution.
I'd love a solution that avoids any additional complexities for the users of my object.
Update
One way that I've found to do this is using Value Converters. In my situation I had multiple point collections. There was a main dep. property that contained the usual shape of the data. Two alternate shapes were needed for reuse in other areas/contexts.
At first I had 3 dep. props. But, I could have just had one property (the usual shape) and used a value converted to transform the points into my other 2 desired shapes. Doing this I only make the one set of points in the control. The expense of transforming points to the secondary shapes is only incurred when used. Now my main control doesn't need to anticipate how data needs to look for every possible template thrown at the control - now its the template designers problem.
Update 2
Certainly INotifyPropertyChanged and regular properties are the recommended way to handle this.
You don't necessarily have to use dependency properties to enable data-binding. However, you then have to implement INotifyPropertyChanged if changes at the source should be propagated to the target of the binding. A "normal" .NET property is easy to lazy load perhaps like this:
PointCollection points
public PointCollection Points {
get {
return this.points ?? (this.points = CreatePoints());
}
}
PointCollection CreatePoints() {
// ...
}
I'm not sure how you can fit INotifyPropertyChanged into your control, but it sounds a bit strange that your control supplies data to other parts of the system. Perhaps you need to create a view-model containing the data that you then can let your control data-bind to.
If I paraphrase your question to
How do I get notified when dependency property is changed?
will this be correct? I draw this from your phrase "Normally in .NET I'd but some logic in the Property's getter, but these are bypassed by XAML data binding".
If I'm correct, then you can register your own property changed callback. It's always called. Doesn't matter who caused the change binding, style or trigger. The following code snippet is taken from MSDN Article "Dependency Property Callbacks and Validation":
public static readonly DependencyProperty CurrentReadingProperty =
DependencyProperty.Register(
"CurrentReading",
typeof(double),
typeof(Gauge),
new FrameworkPropertyMetadata(
Double.NaN,
FrameworkPropertyMetadataOptions.AffectsMeasure,
new PropertyChangedCallback(OnCurrentReadingChanged),
new CoerceValueCallback(CoerceCurrentReading)
),
new ValidateValueCallback(IsValidReading)
);
public double CurrentReading
{
get { return (double)GetValue(CurrentReadingProperty); }
set { SetValue(CurrentReadingProperty, value); }
}
Your takeaway here is OnCurrentReadingChanged() method. Hope this helps :).
Related
I am currently migrating a number of attached behaviours I have created to Blend Behaviours so that they support drag and drop within Expression Blend. I have noticed that authors of Blend behaviours tend to define the behaviour properties as dependency properties.
I have created a behaviour, TiltBehaviour, which exposes a public dependency property, TiltFactor, of type double. Within Expression Blend I can set the value of this property, however, the option to add a "Data Binding ..." is grayed out:
I have also noticed that Behaviors extend DependencyObject, therefore they do not have a DataContext and therefore cannot inherit the DataContext of the element to which they are attached. This feels like a real weakness to me!
So, the bottom-line is, if I cannot set a binding to my behaviors dependency property in Blend, and it does not inherit a DataContext, why bother using dependency properties at all? I could just use CLR properties instead.
Blend behaviors would be almost useless unless they supported binding! I recreated your tilt behavior and it supports binding in Blend 4 with no problems so I don't know exactly where you went wrong. Perhaps you can reproduce my simple example and then infer what's wrong with your setup.
Here's the (non-functional) tilt behavior with dependency property:
public class TiltBehavior : Behavior<FrameworkElement>
{
public double TiltFactor
{
get { return (double)GetValue(TiltFactorProperty); }
set { SetValue(TiltFactorProperty, value); }
}
public static readonly DependencyProperty TiltFactorProperty =
DependencyProperty.Register("TiltFactor", typeof(double), typeof(TiltBehavior), new UIPropertyMetadata(0.0));
}
Then just create a new window and drop the behavior onto the grid and Blend creates this:
<Grid>
<i:Interaction.Behaviors>
<local:TiltBehavior/>
</i:Interaction.Behaviors>
</Grid>
and the Blend "Data Binding..." option is available in the properties tab.
I tested this with both WPF and Silverlight projects. The built-in behaviors, triggers and actions all support binding by virtue of using being dependency properties and all the Blend samples use binding heavily and so this has to work.
In fact you can just drop a built-in behavior like FluidMoveBehavior onto your grid and check that Duration, which is a dependency property, supports binding. If that doesn't work, I have no idea what's going on!
Let's consider then how binding works for these strange beasts called behaviors.
As WPF or Silverlight programmers we are very familiar with binding for things like FrameworkElement. It has a property called DataContext that we can manipulate to control the default binding source and that property is inherited by nested elements when we don't override it.
But behaviors (and triggers and actions) are not of type FrameworkElement. They are ultimately derived from DependencyObject, as we might expect. But while we can using binding on any class derived from DependencyObject, our familiar DataContext is missing at this low-level and so the binding has to supply the source. That's not very convenient.
So behaviors are derived (on WPF anyway) from Animatable and Animatable is derived from Freezable. The Freezable class is where the simplicity of dependency objects intersects with the complexity of framework elements. The Freezable class is also the base class for more familiar things like brushes and image sources. These classes don't need the full complexity of a framework element, but they want to participate, in a limited way with the elements that they are associated with.
Through a complicated magical process, Freezable instances acquire an inheritance context: the framework element they are most closely associated with, and when a default binding is used (one without a source), the Freezable uses the DataContext of it's associated element instead.
In fact as you learn about behaviors the AssociatedObject is a central concept; for a behavior it is the thing that the behavior is attached to. But the important point is that all Freezable objects can use the DataContext of their AssociatedObject by proxy.
All this magic is what Josh Smith calls the:
Hillberg Freezable Trick
And so all this leads up to saying that due to the Hillberg Freezable Trick, Blend behaviors support binding using the data context of their associated element as the default source. As a result, bindings for behaviors seem to "just work" without any effort on our part. Behaviors are a thousand times more useful because of this.
Edit: dain is correct you can still bind to the DataContext which is created artificially, how often have you seen people bind to a SolidColorBrush.Color? It also works even though SolidColorBrush inherits from DependencyObject and hence has no DataContext.
See this blog post on the inheritance context.
The thing is that since the behaviours are attached, they do not appear in the logical tree and hence would not inherit a DataContext anyway.
I have a complex WPF control that for some reasons (ie. performance) is not using dependency properties but simple C# properties (at least at the top level these are exposed as properties).
The goal is to make it possible to bind to some of those top level properties -> I guess I should declare them as DPs.(right? or is there some other way to achieve this? )
I started reading on MSDN about DependencyProperties and DependencyObjects and found an example:
public class MyStateControl : ButtonBase
{
public MyStateControl() : base() { }
public Boolean State
{
get { return (Boolean)this.GetValue(StateProperty); }
set { this.SetValue(StateProperty, value); }
}
public static readonly DependencyProperty StateProperty = DependencyProperty.Register(
"State", typeof(Boolean), typeof(MyStateControl),new PropertyMetadata(false));
}
If I'm right - this code enforces the property to be backed up by DependencyProperty which restricts it to be a simple property with a store(from functional point of view, not technically) instead of being able to calculate the property value each time getter is called and setting other properties/fields each time setter is called.
What can I do about that? Is there any way I could make those two worlds meet at some point?
//edit
I guess I have to tell you a little more about what I want to do and what my limitations are. So:
I have TabControl that is bound to a collection of ViewModel(I'm using MVVM pattern) objects. Every tab is meant to be an editor for one object of that collection. Objects can be of different types so I have multiple definitions each with a different DataType property. Now I have that complex WPF Control that I want to use as a part of one of those DataTemplates. If I use usual TextBox I can simply bind to its Text property, but I can't do the same with Text property of that custom control simply because its Text property is not a dependency property.
In this scenario I have :
no direct access to the control itself nor to its events
no code behind file that I can use to do that kind of thing
I can see however a dirty solution -
In the Window class I would have to subscribe to CollectionChanged event of the collection that is bound to the TabControl.
Whenever an item is added to that collection use ItemContainerGenerator to obtain a copy of I suppose TabItem and use it to find the right copy of 'complex control'
Regiter items handlers to 'complex controls' events to do the job
This is wrong because:
this is agains MVVM - I have to play with tab control to do the job instead of doing it in the ViewModel class
this couples in an unwanted way the view and viewmodel
I think you are mixing up Dependency Properties and implementing INotifyPropertyChanged on your classes.
You don't need your property to be a dependency property, you just need your class to implement INotifyPropertyChanged and call OnPropertyChanged whenever the state of your object changes in a way that would affect the value you want to expose to binding.
So let's say you have a property Sum that you want to bind to. The Sum property simple adds two other properties (or fields, or whatever) together. When anything happens that affects the Sum calculation, you want to notify that the Sum value has changed, so the any controls bound to Sum get updated.
public int Sum => Value1 + Value2;
public int Value1
{
set
{
// changing this affects "Sum", so I need to notify that the binding should update
_value1 = value;
OnPropertyChanged("Sum");
}
}
public int Value2
{
set
{
// changing this affects "Sum", so I need to notify that the binding should update
_value2 = value;
OnPropertyChanged("Sum");
}
}
It seems to me that you've been saddled with a WPF user control that was built by someone who didn't intend it to be used with data binding. I would assume that this is for one of two reasons: a) there's some logical reason that you shouldn't be able to bind to this property, or b) the original author of this control didn't know what he was doing. You haven't provided enough information for me to know which of those two conditions is the one you're really working under.
But in general, the reason you can't expose calculated properties for binding is that calculated properties generally don't have a setter. It doesn't make sense to set a property whose value is calculated.
If there are other properties whose values need to be updated when this one changes, the right approach (or at least the one consonant with the design of dependency properties) is to handle those updates in the dependency property's callback function, which is kind of what the callback function is for.
I am new to WPF and trying to wrap my head around WPF's framework, what it does and does not do for you.
To clarify this, I would like to know what is the difference between this:
public List<MyCustomObject> MyCustomObjects
{
get { return (List<MyCustomObject>)GetValue(MyCustomObjectsProperty); }
set { SetValue(MyCustomObjectsProperty, value); }
}
public static readonly DependencyProperty MyCustomObjectsProperty =
DependencyProperty.Register("MyCustomObjects", typeof(List<MyCustomObject>),
typeof(Main), new UIPropertyMetadata(new List<MyCustomObject>()));
and this:
public ObservableCollection<MyCustomObject> MyCustomObjects { get; set; }
public Main ()
{
MyCustomObjects = new ObservableCollection<<MyCustomObject>();
}
Ok, we must put some order into things, there's a few concepts mixed in together here.
First of all, you're asking what the difference is between a field-backed property and a dependency property. Google would be your best friend, however I recommend this blog post by WPF's vanguard Josh Smith: Overview of dependency properties in WPF
In short: dependency properties support the richness that is WPF: Styling, animation, binding, metadata, and more.
Secondly, you're asking what the difference is between a List and an ObservableCollection. Well the latter provides change notifications (in the forms of events) on any change to the collection (addition, removal, change of order, clearing, etc.), and the former does not. You can read more about that here: The ObservableCollection Class
In short: ObservableCollection provides change notifications which are required for the UI to automatically reflect changes in the view model.
In addition to Aviad and Reed's answers, I would like to point out a serious bug in your first code sample :
public static readonly DependencyProperty MyCustomObjectsProperty =
DependencyProperty.Register("MyCustomObjects", typeof(List<MyCustomObject>),
typeof(Main), new UIPropertyMetadata(new List<MyCustomObject>()));
The new List<MyCustomObject>() used as the default value will be created only once, so by default all instances of your type will share the same List<MyCustomObject> instance, which is probably not what you want... The only sensible default value here is null
In the first case, you're setting up a Dependency Property containing a List<T> instance.
In the second, you're making a normal CLR property, but having it setup as an ObservableCollection<T>.
For WPF Data Binding, there are some differences here.
Typically, you want all of your properties in the DataContext (which is the object that, by default, things "bind" to) to either implement INotifyPropertyChanged or to be a Dependency Property. This lets the binding framework know when changes are made to that object. Normally, though, you'd only use a Dependency Property if your working with a custom control - it's usually a better idea to have your object to which your data bound be a separate class, assigned to the DataContext. (For details here, see Josh Smith on MVVM or my recent detailed post on MVVM...)
However, with a collection, you typically also want the binding system to know when the items within the collection change (ie: an item is added). ObservableCollection<T> handles this by implementing INotifyCollectionChanged.
By using the second approach (using an ObservableCollection<T>), your UI can tell when items were added or removed from the collection - not just when a new collection is assigned. This lets things work automatically, like a ListBox adding elements when a new item is added to your collection.
1:
You're using a dependency property to "tell" the framework when that property is changed. This will have the following consequences for your binding:
MyCustomObjects.Add(new MyCustomObject()); //Wont update the view through databinding
MyCustomObjects = new List<MyCustomObject>(); //Will update the view through databinding
You could gain the same databinding functionality by implementing INotifyPropertyChanged on which ever class exposes the property, but dependency properties a capable of much more than just notifying about changes. These are rather advanced features though, which you aren't likely to come across in your average joe app :)
2:
You're using an observable collection, which implements INotifyCollectionChanged for you, to tell the databinding whenever the content of the collection has changed. This will have the opposite consequences than #1:
MyCustomObjects.Add(new MyCustomObject()); //Will update the view through databinding
MyCustomObjects = new ObservableCollection<MyCustomObject>(); //Won't update the view through databinding
When implementing the ViewModel in a Model-View-ViewModel architecture WPF application there seem to be two major choices how to make it databindable. I have seen implementations that use DependencyProperty for properties the View is going to bind against and I have seen the ViewModel implementing INotifyPropertyChanged instead.
My question is when should I prefer one over the other? Are there any performance differences? Is it really a good idea to give the ViewModel dependencies to WPF? What else do I need to consider when make the design decision?
Kent wrote an interesting blog about this topic: View Models: POCOs versus DependencyObjects.
Short summary:
DependencyObjects are not marked as
serializable
The DependencyObject class overrides and seals the Equals() and
GetHashCode() methods
A DependencyObject has thread affinity – it can only be accessed
on the thread on which it was
created
I prefer the POCO approach. A base class for PresentationModel (aka ViewModel) which implements INotifyPropertyChanged interface can be found here: http://compositeextensions.codeplex.com
According to the WPF performance guide, DependencyObjects definitely perform better than POCOs that implement INotifyPropertyChanged:
http://msdn.microsoft.com/en-us/library/bb613546.aspx
The choice is totally based on your business logic and UI abstraction level. If you dont want a good separation then DP will work for you.
DependencyProperties will be applicable mainly at the VisualElements level so it won't be good idea if we create lot of DPs for each of our business requirements. Also there is a greater cost for DP than a INotifyPropertyChanged. When you design a WPF/Silverlight try to design UI and ViewModel totally separate so that at any point of time we can change the Layout and UI controls (Based on theme and Styles)
Refer this post also - https://stackoverflow.com/questions/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel . The link has a lot of reference to Model-View-ViewModel pattern, which is very relevant to this discussion.
From an expressiveness standpoint, I thoroughly enjoy using dependency properties and cringe at the thought of INotifyPropertyChanged. Apart from the string property names and possible memory leaks due to event subscription, INotifyPropertyChanged is a much more explicit mechanism.
Dependency properties imply "when this, do that" using easily-understood static metadata. It is a declarative approach that gets my vote for elegance.
Dependency properties are intended to supports binding (as a target) on UI elements not as a source to data binding, this is where INotifyProperty comes in. From a pure point of view you shouldn't use DP on a ViewModels.
"In order to be the source of a binding, a property does not need to be a dependency property; you can use any CLR property as a binding source. However, in order to be the target of a binding, the property must be a dependency property. For a one-way or two-way binding to be effective, the source property must support change notifications that propagate to the binding system and thus the target. For custom CLR binding sources, this means that the property must support INotifyPropertyChanged. Collections should support INotifyCollectionChanged."
All dependency objects cannot be serialised (This could hamper the use of ViewModels and DTO (POCO)'s.
There are differences between DP within Silverlight compared to WPF.
http://msdn.microsoft.com/en-us/library/cc221408(v=VS.95).aspx
http://msdn.microsoft.com/en-us/library/cc903933(VS.95).aspx
INotifyPropertyChanged when used also gives you the ability to add more logic in the code of your getters and setter of your properties.
DependencyProperty example:
public static DependencyProperty NameProperty = DependencyProperty.Register( "Name", typeof( String), typeof( Customer ) );
public String Name
{
set { SetValue( NameProperty, value ); }
get { return ( String ) GetValue( NameProperty ); }
}
In your getter and setter --- all you can do is simply call SetValue and GetValue respectively, b/c in other parts of the framework the getter/setter is not called, instead it directly calls SetValue, GetValue, so your property logic wouldnt reliably be executed.
With INotifyPropertyChanged, define an event:
public event PropertyChangedEventHandler PropertyChanged;
And then simply have any logic anywhere in your code, then call:
// ...
// Something cool...
// ...
if( this.PropertyChanged != null )
{
PropertyChanged( this, new PropertyChangedEventArgs( "Name" ) );
}
// More cool stuff that will reliably happen...
This could be in a getter/setter, or anywhere else.
Is it really a good idea to give the ViewModel dependencies to WPF?
.NET 4.0 will have System.Xaml.dll, so you won't have to take a dependency on an arbitrary framework to utilize it. See Rob Relyea's post about his PDC session.
My take
XAML is a language for describing objects, and WPF is a framework whose described objects are UI elements.
Their relationship is similar to C#, a language for describing logic, and .NET, a framework which implements particular kinds of logic.
XAML's purpose is declarative object graphs. The W*F technologies are great candidates for this paradigm, but XAML exists independently of them.
XAML and the entire dependency system were implemented as separate stacks for WF and WPF, probably to leverage the experience of different teams without creating a dependency (no pun intended) between them.
I too had to consider this decision recently.
I found that the INotifyPropertyChanged mechanism suited my needs better because it allowed me to glue my GUI to an existing business logic framework without duplicating state. The framework I was using had its own observer pattern and it was easy to forward one level of notification on to the next. I simply had a class which implemented the observer interface from my business logic framework and the INotifyPropertyChanged interface.
With DP you cannot define the backend that stores the state yourself. I would have had to let .net cache a copy of every item of state I was binding to. This seemed like an unnecessary overhead - my state is large and complicated.
So here I found INotifyPropertyChanged better for exposing properties from business logic to GUI.
That being said where I needed a custom GUI widget to expose a property and for changes to that property to affect other GUI widgets DP proved the simple solution.
So there I found DP useful for GUI to GUI notification.
Dependency properties are the glue of custom control creation. If you are interested in using Intelli-sense to show your properties in the properties window at XAML design time you must use Dependency properties. INPC will never show a property in the property window at design time.
It seems that Dependency Properties should be used in controls that you create such as Buttons. To use properties in XAML and use all the WPF features, those properties must Dependency Properties.
However, your ViewModel is better off using INotifyPropertyChanged. Using INotifyPropertyChanged will give you the ability to have getter/setter logic if you need to.
I recommend checking out Josh Smith's version of a base class for a ViewModel that already implements INotifyPropertyChanged:
http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/
I think this is an excellent example of how to do a ViewModel.
I think DependencyProperty and INotifyPropertyChanged are used for two different things in Binding : the first for enabling a property to be a target of a binding and receive the input from another property (use {Binding ...} to set the property), the last when you want the value of a property to be used as the source of a binding (name in the Binding Path Expression).
So the choice is merely technical.
I prefer a more direct approach, which I blogged about in Presentation Model Without INotifyPropertyChanged. Using an alternative to data binding, you can bind directly to CLR properties without any bookkeeping code. You just write plain-old .NET code in your View Model, and it gets updated when your Data Model changes.
There is only one thing why to prefer a DependencyObject - Binding will work better. Just try an example with a ListBox and TextBox, populate list with data from INotifyPropertyChanged property vs. DependencyProperty and edit current item from TextBox...
If you want to expose properties to other controls you must use Dependency properties... But good luck because they take a while to figure out...
In WPF:
Can someone please explain the relationship between DependencyProperty and Databinding?
I have a property in my code behind I want to be the source of my databinding.
When does a DependencyProperty (or does it) come into play if I want to bind this object to textboxes on the XAML.
The target in a binding must always be a DependencyProperty, but any property (even plain properties) can be the source.
The problem with plain properties is that the binding will only pick up the value once and it won't change after that because change notification is missing from the plain source property.
To provide that change notification without making it a DependencyProperty, one can:
Implement INotifyPropertyChanged on the class defining the property.
Create a PropertyNameChanged event. (Backward compatibility.)
WPF will work better with the first choice.
What is the DependencyProperty?
The DependencyProperty class is one of the most important design bases hidden deep in the .Net Framework WPF.
This class is protected by sealed from the .NET Framework.
This property differs from the one-dimensional general property in that it not only stores field values, but also takes advantage of the various functions provided within the class.
Most importantly, there is a full foundation for data binding. You can also send notifications whenever you bind something.
DependencyProperty
Wpf Xaml Binding
It's already a late answer, but I'll introduce the results of my research.