Lesson 03.6 – Update Player data with the PropertyChanged event

In this lesson, we will finish connecting the Model (Player.cs) to the View (MainWindow.xaml). With this change, when a property value changes on the Model or ViewModel, the View will automatically update.

 

 

Summary

  • An “Interface” defines the properties and functions that must exist in any class that “implements” the interface.
    • It also lets other classes know how the classes with the interface will work, and how they can be used.
  • Databinding does not automatically know when a property value changes in the DataContext object.
    • The View can know about changes to properties, if the ViewModel (or Model) classes implement the INotifyPropertyChanged interface.
    • When a class implements INotifyPropertyChanged, its properties “raise” a PropertyChanged “event”. The View “listens” for that event, and updates the UI, when it receives notification of the change.
  • To make the property raise the PropertyChanged event, when it gets a new value, they cannot be auto-properties.
    • We need to add extra code to the property “set”, to raise the Property Changed event, when the property is set to a new value.
    • To add this extra code, we need to add a “backing variable” for the property – a variable the property uses to store its value.
    • Then, we need to add a code to raise the PropertyChanged event, for anything that may be subscribed to the eventhandler, such as the View.

 

Source Code

 

Player.cs

 

MainWindow.xaml

 

MainWindow.xaml.cs

 

Return to main page

 

15 thoughts on “Lesson 03.6 – Update Player data with the PropertyChanged event

    1. Yes. Although, the property changed event is a built-in one that is automatically recognized. So, for the property changed event, we do not need to create the delegate, or manually connect from the “subscriber” (the ViewModel) to the “publisher” (the View).

      In future lessons, we will create our own custom events, for events like OnPlayerKilled and OnMonsterKilled. Those will require the delegate, subscribing, etc.

    1. Yes, you generally implement INotifyPropertyChanged in the Model. In the section of the Microsoft webpage labeled “The Model Class”, it mentions, “Typically, the model implements the facilities that make it easy to bind to the view. This usually means it supports property and collection changed notification through the INotifyPropertyChanged and INotifyCollectionChanged interfaces.”

      The View normally binds to properties of the ViewModel and the Models. This is because the View is normally displaying values from the Model properties. If we didn’t do this, we would need to duplicate properties from the Models in the ViewModel. Then, you would still need to have the Models raise events; however, they would be caught by the ViewModel – which would update its properties, and raise its ProperyChanged events, for the UI to capture. That would create a lot of duplicated code (the same properties in the Models and the ViewModel).

      You would use the ViewModel to handle “actions” from the UI, such as a button click. However, the ViewModel functions that handle those actions are usually small. They mainly call the appropriate functions in the Models, which have the more complex logic.

      Please let me know if that wasn’t clear, or if you have other questions.

  1. ok, so a few questions here… first of all, the virtual method OnPropertyChanged implies that it can be overridden in derived classes. Is this a default way of specifying this or are you planning to derive further classes from this Player class? if not planning on creating derived classes, is it better not to make it virtual?

    I understand that you must implement everything offered in an interface. this interface only had an event. ultimately, I think my question is how do I see/understand the functionality of the interface itself. When i look at the definition in VS, i don’t see it being derived from anything else and no explanation of how or when to use it. So, I go on you telling me I need this, but me being REALLY OCD when it comes to this stuff, I need to know the workings of it and having difficulty finding it. any advice?

    thanks

    1. It’s a common practice to make functions in base classes “virtual”, unless all its derived classes are “sealed”. In that situation, you would know there will never be a future derived class that needs to override the base function. So, you can safely remove the “virtual”.

      Because this program is still being developed, and I expect people will eventually modify the code to create their own versions, I prefer to leave the function virtual for now. If I ever decide the program is “complete”, and want to release a Version 1.0 of it, I would run static analysis tools on it (with very strict rules), and clean up issues like this.

      Other people prefer to be extremely strict from the beginning. Personally, I wouldn’t keep an unused class/function/property/variable in the project. But, I consider things like this (non-overridden virtual functions in base classes, class scope more visible than needed, etc.) to be acceptable during development.

      I’m not sure about your question, “I think my question is how do I see/understand the functionality of the interface itself.” If I didn’t answer it above, can you give me some more details of what you’re looking for?

  2. Thank you. No, I think I just need to read more on interfaces and OO in general to get a better understanding of how some of these things fit in the foundation of the language.

  3. Does the question mark in this line of code prevent trying to use Invoke if PropertyChanged is null?

     

     

  4. Sorry for my newbie questions, but I still don’t quite understand the backing value thing. Why can’t we just update “ExperiencePoints” directly for example? It seems so weird to need both a “ExperiencePoints” and a “_experiencePoints”.

    Can you elaborate a bit? Isn’t auto-properties used so that you DON’T need to add backing values manually? I am so confused.

    Thanks.

    1. With auto-properties, we only have “{ get; }” and “{ set; }”. All we can do is put a value into the property and read its value. We can’t add any more code in there – like raising a PropertyChanged notification, throwing an error if the value is out of range, calculating/setting other properties, etc. So, we need treat the getter and setter more like functions. As individual “functions”, they need to have a place to share the value for the property. That’s the backing variable’s job – it’s a class-level variable that can be used by both the getter and the setter “functions”.

      FYI, if you look at the compiled code for an auto-property, it actually creates a backing variable. There’s more information about that here: https://jeremybytes.blogspot.com/2013/04/explained-properties-in-net.html

      Let me know if that isn’t clear.

      1. Thanks for the answers. I guess my question was more like: If it already automatically creates a backing variable, why do we have to define it manually?

        I guess it makes sense if it’s absolutely required in order to raise a PropertyChanged notification though.

        Again, thanks for the help.

        I’m also stuck in another part of this tutorial (because I use UWP) where we reference an image with a string path.

        UWP doesn’t have the settings you used to set the image Build Action to Resource. Gotta figure that out somewhow. 🙂

        1. It is mostly to give us a place to add the PropertyChanged code, and any other logic we may want to have for the “set”. It can also be used in the “get” for “lazy loading” a property – although that’s mostly for large applications that need to worry about performance when loading values from a database.

          For the graphics, that’s something I’m going to need to look into for this program in the future. I want to make it so a programmer can easily modify their game world, and that means the program will need to use a different technique from making the image files resources. But, it’s going to be a while before making that change to this app. Please share if you find a good solution for your UWP version.

Leave a Reply

Your email address will not be published. Required fields are marked *