Do folks have any guidance on when a simple .NET property that fires INotifyPropertyChanged.PropertyChanged
is su开发者_StackOverflow中文版fficient in a view model? Then when do you want to move up to a full blown dependency property? Or are the DPs intended primarily for views?
There are a few approaches:
1. The dependency property
While you using the dependency property it makes the most sense in elements-classes that have a visual appearance (UIElement
s).
Pros:
- WPF do the logic stuff for you
- Some mechanism like animation use only dependency property
- 'Fits' ViewModel style
Cons:
- You need to derive form
DependencyObject
- A bit awkward for simple stuff
Sample:
public static class StoryBoardHelper
{
public static DependencyObject GetTarget(Timeline timeline)
{
if (timeline == null)
throw new ArgumentNullException("timeline");
return timeline.GetValue(TargetProperty) as DependencyObject;
}
public static void SetTarget(Timeline timeline, DependencyObject value)
{
if (timeline == null)
throw new ArgumentNullException("timeline");
timeline.SetValue(TargetProperty, value);
}
public static readonly DependencyProperty TargetProperty =
DependencyProperty.RegisterAttached(
"Target",
typeof(DependencyObject),
typeof(Timeline),
new PropertyMetadata(null, OnTargetPropertyChanged));
private static void OnTargetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Storyboard.SetTarget(d as Timeline, e.NewValue as DependencyObject);
}
}
2. The System.ComponentModel.INotifyPropertyChanged
Usually, when creating a data object, you’ll use this approach. It is simple and neat solution for Data-like stuff.
Pros and Cons - complementary to 1. You need to to implement only one event (PropertyChanged).
Sample:
public class Student : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
}
private string name;
public string Name;
{
get { return name; }
set {
name = value;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
3.PropertyNameChanged
Rising an event for each property with specified name(f.e. NameChanged). Event must have this name and it is up to you to handle/rise them. Similar approach as 2.
4. Get the binding
Using the FrameworkElement.GetBindingExpression()
you can get the BindingExpression
object
and call BindingExpression.UpdateTarget()
to refresh.
First and second are the most likely depending what is your goal.
All in all, it is Visual vs Data.
As far as I know, DependencyProperty
is only required when you need
- PropertyValue inheritence
- you need to allow the property to be set in Style setters
- Use animation for the property
etc.
These features will not be available with normal properties.
DependencyProperty
is required if you want to allow a binding to be set on the property. Usually this is for custom UIElement
s you create. You want to allow people to be able to bind data to your UIElement
s.
<local:MyUIElement MyProperty={Binding Path=SomethingToBindTo} />
To do this requires that MyProperty is a dependancy property
The main problem I see with INotifyPropertyChanged
is if you viewmodel is complex containing many nested types it appears that you have to bubble the PropertyChanged
event up through the hierarchy.
As the other answers have already said enough about when to create dependency property. i.e.
- PropertyValue inheritence
- you need to use binding on a property
- Use animation for the property
The one more perspective/question on this is "In a WPF application is makes sense to create dependency properties in a control cause they are likely to change during user interaction like Height,width, text,content, background etc but what about other classes like Behaviors Classes(Non UI classes). Do properties in those classes need to be a dependency property?"
I won't say for very absolute or emphasis on some set of rules here but you should create your properties as DP. As from design perspective if a property is DP it's always in default form of WPF to use/bind.i.e.
- As a DP is much more fast/natural in reflecting changes compare to a normal CLR property.
- A DP has validation mechanism to validate the value assigned and a default structure to revert the value.
- A DP has Coerce value callback to control the limits of property.
- A DP has meta data associated with it unlike CLR property.
In terms of practices I've seen people doing many mistakes in nested bindings and then raising changes these kind of faults doesn't happen with a DP cause of it's design and compatibility of raising change itself. So with a little extra syntax you put a flexibility/performance/ easeness to your application. So go for it wherever affordable.
Still can't say sure for ViewModel classes/other helper classes. will update the answer if found convincing reasons in future.
Just a post worth reading on this topic
精彩评论