DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Implement Hibernate Second-Level Cache With NCache
  • Modify JSON Data in Postgres and Hibernate 6
  • Top 10 C# Keywords and Features
  • Ensuring Reliable Microservice Deployment With Spring Boot Build Info Maven Plugin

Trending

  • Testing SingleStore's MCP Server
  • Simplify Authorization in Ruby on Rails With the Power of Pundit Gem
  • Scalability 101: How to Build, Measure, and Improve It
  • Subtitles: The Good, the Bad, and the Resource-Heavy

Implementing INotifyPropertyChanged

In article, a web development guru walks us through how we can use INotifyPropertyChanged to craft code that adheres to the DRY concept of programming.

By 
Gunnar Peipman user avatar
Gunnar Peipman
·
Apr. 03, 19 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
10.5K Views

Join the DZone community and get the full member experience.

Join For Free

This is a short post about how to implement INotifyPropertyChanged without using any advanced tooling. I have some small UWP applications where I'm using MVVM to separate presentation and logic. Here is how I use INotifyPropertyChanged with a base class for multiple view models.

First, one's introduction to INotifyPropertyChanged comes usually through some existing view model. The interface is used to communicate to the view that some properties in the view model have changed. Take a look at thePropertyChanged event and theNotifyPropertyChanged method (this method is not part of the interface).

public class GalleryViewModel : INotifyPropertyChanged
{
    public ObservableCollection<GalleryItem> Items { get; set; }

    public GalleryViewModel()
    {
        Items = new ObservableCollection<GalleryItem>();
        OpenImage = new RelayCommand<GalleryItem>(a => { SelectedItem = a; });
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName]string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private GalleryItem _selectedItem;

    public GalleryItem SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            _selectedItem = value;
            NotifyPropertyChanged();
            NotifyPropertyChanged("SelectedItemVisibility");
            NotifyPropertyChanged("ListVisibility");
        }
    }

    public Visibility SelectedItemVisibility
    {
        get
        {
            return _selectedItem == null ? Visibility.Collapsed : Visibility.Visible;
        }
        set { }
    }

    public Visibility ListVisibility
    {
        get
        {
            return _selectedItem != null ? Visibility.Collapsed : Visibility.Visible;
        }
        set { }
    }

    public async Task LoadData()
    {
        var service = new GalleryService();
        var items = await service.LoadItems(null);


        foreach(var item in items)
        {
            Items.Add(item);
        }
    }

    public RelayCommand<GalleryItem> OpenImage { get; internal set; }
}

For the PropertyChanged method, there are many implementations. Jeremy Bytes's blog has an excellent overview of the evolution of INotifyPropertyChanged for those who want to find out more. Here, I will stick with what I have in the sample model above.

NotifyPropertyChanged Method

I have the shortest version of this method that I found. It works with newer .NET Frameworks.

public event PropertyChangedEventHandler PropertyChanged;

protected void NotifyPropertyChanged([CallerMemberName]string propertyName = "")
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

For those who find it tricky or weird, I'll give a few words for explanation.

CallerMemberName attribute is for the compiler. When the propertyName argument is not given to the method call, then the name of the calling method or property is set to propertyName. These two calls to the NotifyPropertyChanged() method are equal:

public GalleryItem SelectedItem
{
    get { return _selectedItem; }
    set
    {
        _selectedItem = value;
        NotifyPropertyChanged();
        NotifyPropertyChanged("SelectedItem");
    }
}

But why this kind of shortcut? What it is good for? Although my sample model above fires the change of three properties it's not too common. Very often, we need to fire just one change event and it goes for the current property that changed. This is why this shortcut is good: we don't have to write the property name as a string and our code works even when the property name is changed.

NotifyPropertyChangedBase

Repeating the INotifyPropertyChanged event and method to fire this event to every single view model doesn't make much sense. We get a load of repeated code and if we want to change something we have to modify all copies of the repeated code. To avoid this, I wrote a NotifyPropertyChangedBase class.

public abstract class NotifyPropertyChangedBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged([CallerMemberName]string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Now we have a PropertyChanged event and NotifyPropertyChanged() method in a separate base class and we don't have to duplicate the code to all view models. Using this base class I can write the view model above like shown here.

public class GalleryViewModel : NotifyPropertyChangedBase
{
    public ObservableCollection<GalleryItem> Items { get; set; }

    public GalleryViewModel()
    {
        Items = new ObservableCollection<GalleryItem>();
        OpenImage = new RelayCommand<GalleryItem>(a => { SelectedItem = a; });
    }      

    private GalleryItem _selectedItem;

    public GalleryItem SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            _selectedItem = value;
            NotifyPropertyChanged();
            NotifyPropertyChanged("SelectedItemVisibility");
            NotifyPropertyChanged("ListVisibility");
        }
    }

    public Visibility SelectedItemVisibility
    {
        get
        {
            return _selectedItem == null ? Visibility.Collapsed : Visibility.Visible;
        }
        set { }
    }

    public Visibility ListVisibility
    {
        get
        {
            return _selectedItem != null ? Visibility.Collapsed : Visibility.Visible;
        }
        set { }
    }

    public async Task LoadData()
    {
        var service = new GalleryService();
        var items = await service.LoadItems(null);


        foreach(var item in items)
        {
            Items.Add(item);
        }
    }

    public RelayCommand<GalleryItem> OpenImage { get; internal set; }
}

From here we can go even further and use frameworks like Prism or MVVM Light Toolkit to have most of the important base classes and MVVM features out-of-box.

Wrapping Up

Implementing INotifyPropertyChanged manually is not hard. Newer versions of C# provide us with the CallerMemberName ttributea and calls the method to fire events for property changes that get even smaller. Plus we don't have to write property names as strings. To avoid repeating INotifyPropertyChanged code to all view models, we created a simple base class and made our model extend it. We can also write the more general ViewModelBase that offers more functionalities that view models may need.

View model Property (programming)

Published at DZone with permission of Gunnar Peipman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Implement Hibernate Second-Level Cache With NCache
  • Modify JSON Data in Postgres and Hibernate 6
  • Top 10 C# Keywords and Features
  • Ensuring Reliable Microservice Deployment With Spring Boot Build Info Maven Plugin

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!