Why Plain Objects Need a Notification Contract
View models in WPF are typically ordinary CLR classes, not DependencyObject subclasses, because they should be UI-framework-agnostic and unit-testable. But without dependency properties, WPF's binding engine has no automatic way to know a property changed after the initial read; INotifyPropertyChanged solves this by defining a single event, PropertyChanged, that a class raises whenever a property's backing value changes, and which the binding infrastructure subscribes to automatically the moment a Binding is established against that object.
Cricket analogy: It is like a scoring app that only updates once unless the scorer explicitly presses a 'notify' button after each ball — without that signal, the app has no way to know the score changed since it last checked.
Implementing the Interface Correctly
public class CustomerViewModel : INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set
{
if (_name == value) return;
_name = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}The [CallerMemberName] attribute lets the compiler automatically supply the calling property's name as a string argument, eliminating a common source of copy-paste bugs where a developer raises OnPropertyChanged with the wrong hardcoded string. The equality check (if (_name == value) return;) before raising the event is not just an optimization — without it, bound controls could flicker, computed properties depending on Name could re-evaluate needlessly, and any expensive PropertyChanged subscriber logic would run on every set even when nothing actually changed.
Cricket analogy: It is like a stadium PA system automatically announcing whichever batter is on strike without a scorer having to type the name manually each time, avoiding the classic error of announcing the wrong player after a mid-over substitution.
Notifying Dependent (Computed) Properties
When one property is computed from another — for example a FullName property derived from FirstName and LastName — setting FirstName must also raise PropertyChanged for FullName, since FullName's own setter is never called and the binding engine has no way to infer the dependency automatically. This is commonly done by explicitly calling OnPropertyChanged(nameof(FullName)) inside the FirstName setter, right alongside the notification for FirstName itself, and it is one of the most frequently missed steps that causes a UI to silently show stale computed values.
Cricket analogy: It is like updating a batter's individual score but forgetting to also refresh the team total displayed on the scoreboard — the two numbers are related, but the total doesn't recompute unless something explicitly triggers that refresh too.
PropertyChanged handlers are added by the binding engine as event subscriptions, and if a view model object outlives its bound view (for example, a long-lived singleton view model bound to a short-lived dialog), a strong reference from the event can keep the view alive longer than expected. WPF's binding mechanism generally manages this via weak event patterns internally for standard bindings, but be cautious with manually wired PropertyChanged subscriptions outside the binding system, which do use strong references by default.
- INotifyPropertyChanged defines a single PropertyChanged event that a plain CLR object raises to tell the binding engine a property's value changed.
- View models implement it instead of deriving from DependencyObject, keeping them framework-agnostic and easily unit-testable.
- The [CallerMemberName] attribute lets a helper method automatically capture the correct property name, avoiding hardcoded-string typos.
- Guarding the setter with an equality check before raising the event prevents redundant notifications, UI flicker, and wasted work in subscribers.
- Computed/derived properties must explicitly raise PropertyChanged for themselves inside the setter of every property they depend on.
- Passing an empty or null property name in PropertyChangedEventArgs signals WPF to refresh all properties on that object.
- Standard WPF data binding uses weak event patterns for PropertyChanged subscriptions, but manually wired handlers outside binding do not get this protection automatically.
Practice what you learned
1. Why do WPF view models typically implement INotifyPropertyChanged instead of deriving from DependencyObject?
2. What does the [CallerMemberName] attribute do when applied to a helper method's parameter?
3. Why must a FullName property's dependency on FirstName be handled with an explicit PropertyChanged notification?
4. What is the effect of guarding a property setter with 'if (_name == value) return;' before raising PropertyChanged?
5. What does passing an empty string or null as the property name in PropertyChangedEventArgs signal to WPF?
Was this page helpful?
You May Also Like
Data Binding Fundamentals
Learn how WPF connects UI elements to data sources through the Binding object, DataContext, and the {Binding} markup extension, eliminating manual UI-update code.
Binding Modes and Converters
Understand how BindingMode controls the direction of data flow between target and source, and how IValueConverter lets bindings transform data for display.
Dependency Properties
Learn why WPF replaces plain CLR properties with DependencyProperty for UI elements, enabling data binding, styling, animation, and property value inheritance.
Related Reading
Related Study Notes in Microsoft Technologies
Browse all study notesWindows 10 / UWP Development Study Notes
.NET · 30 topics
Microsoft TechnologiesWindows Batch Scripting Study Notes
Batch · 30 topics
Microsoft TechnologiesMFC (Microsoft Foundation Classes) Study Notes
C++ · 30 topics
Microsoft TechnologiesSilverlight Study Notes
.NET · 30 topics
Microsoft TechnologiesXAML Study Notes
.NET · 30 topics
Microsoft TechnologiesMVVM Design Pattern Study Notes
.NET · 30 topics