Somewhat related to an old post on automatic INotifyPropertyChanged implementation via AOP here are the C# snippets that I use when writing properties that implement INotifyPropertyChanged. Talking to new users of WPF they find property change notification maybe a little bit foreign, fiddly, or possibly heavyweight. I have seen developers favour complex XAML code in favour of just using the property change interfaces available:
- INotifyPropertyChanged
- INotifyCollectionChanged (already implemented in ObservableCollection<T> and ReadOnlyObservableCollection<T>)
- DependencyProperties on DependencyObjects
These constructs should be used to make your life easier. A lot of work has been done my M$ to make these perform very well so dont feel that you are using a big hammer for a little nail. These are the right tools for the job. In fact I have often seen that people find they don't want to contaminate DTOs or Domain Entities with these properties hence the move to favour complex XAML code. This tendency is good but the wrong approach. The objects you use in your WPF application belong to the UI layer not to the domain model. If need be (and I recommend it) translate your DTOs or domain objects to entities specific to you presentation layer. This should allow you to achieve a level of separation and testability that you would not able to get from trying present domain or data transfer objects with complex XAML.
So anyway what this post was originally about the snippets
NotifyPropertyChanged.snippet which produces code an implementation of INotifyPropertyChanged that works with the next snippet. It is mapped to "NotifyPropertyChanged":
#region INotifyPropertyChanged Members /// <summary> /// Implicit implementation of the INotifyPropertyChanged.PropertyChanged event. /// </summary> public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// Throws the <c>PropertyChanged</c> event. /// </summary> /// <param name="propertyName">The name of the property that was modified.</param> protected void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } #endregion
and the PropertyNotify.snippet that works like the standard "prop" snippet in Visual Studio. This snippet is mapped to "propNotify":
private SomeType someValue; public SomeType SomeValue { get { return someValue;} set { if (someValue!= value) { someValue;= value; OnPropertyChanged("SomeValue"); } } }
If you have not used snippets in Visual Studio yet then you are typing too much code (or using Resharper).
*To "install", just copy the file (it's really an XML file with a ".snippet" extension) in your code snippets directory. By default, this is in the My Documents folder, "Visual Studio 2008\Code Snippets\Visual C#\My Code Snippets". *
To use just start typing either "NotifyPropertyChanged" or "propNotify" and when found hit the Tab key twice to expand them.
7 comments:
"The objects you use in your WPF application belong to the UI layer not to the domain model. If need be (and I recommend it) translate your DTOs or domain objects to entities specific to you presentation layer. This should allow you to achieve a level of separation and testability that you would not able to get from trying present domain or data transfer objects with complex XAML."
Bingo!
Hi Lee,
Well said.
Another point here... If you don't use INotifyPropertyChanged or Dependency Properties it is highly likely that your WPF application will consume ALOT more memory than it should. I've recently been charged with optimising some WPF applications and the is the most common type of garbage collection problem in WPF.
One more thing...
“In fact I have often seen that people find they don't want to contaminate DTOs or Domain Entities with these properties”
I’ve actually found having this implemented server side can be quite useful! It’s not part of WPF so there is not problem in using it server side. In fact Linq2Entities & WCF both support the use of this interface through their respective code generation tools.
Cheers,
James Miles
Nice post, but shouldn't the OnPropertyChanged method follow the established pattern, i.e. protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)?
Cheers!
I agree that I should make the method virtual. However why have the method at all if I have to pass the event args?
I think the current proposal (with the virutal keyword added) or something like this should be used
PropertyChangedEventHandler PropertyChanged += (s,e)=>{};
and then on all the properties just directly call the thing
private SomeType someValue;
public SomeType SomeValue {
get { return someValue;}
set {
if (someValue!= value) {
someValue= value; PropertyChanged(this, new PropertyChangedEventArgs("SomeValue")); }
}
}
or even easier use the automatic implementation via AOP
Thoughts?
I was coming at it purely from the FDG angle, where the pattern is to provide a protected virtual method that raises the event, with the event args as its only parameter. This gives derived classes an opportunity to handle the event by overriding the method. The downside is that you can create a lot of event args garbage, which can be a problem especially on compact/embedded devices. Having said that I generally stick to this pattern unless I have a good reason not to.
The download link doesn't seem to be working. I tried with FireFox and IE.
Adam
Sorry about that Adam. I have updated the post so they should work fine now.
Post a Comment