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

 

30 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.

  5. I may have missed it in the video lession but you do need to add
    using System.ComponentModel;
    for the INotifyProperyChanged to work in C#

    I am now getting in the habit of checking the “using” libraries against the original code if something does not work in the code.

    Is there anywhere on the internet I can have complete list of the “usng” libraries that allows me to know when to use them in any code amy code that write.

    1. Hi Brian,

      I don’t know of any place that lists all the namespaces that are built in to the .NET Framework. There are probably several hundred of them. I use a Visual Studio tool called ReSharper, which knows all the available namespaces in a solution and automatically add the correct “using” directives (when it can figure out which one you probably want to use). Microsoft is building more features like this directly into Visual Studio. But, I don’t know if they’ve added this yet.

      I try to mention new “using” directives in the lesson – but the safest thing to do is check the source code to see if they’ve changed.

  6. In case this drives anyone mad don’t forget this in player class

    using System.ComponentModel;

    For some reason I had this missing when I was starting a new classes in Visual studio 2019
    without it the event won’t work.

    1. Thanks for sharing that. I don’t know if VS 2019 changed their default “using” directives, or if I missed that because I use ReSharper (which automatically adds the “using” directives when I type a command that needs a new one).

  7. Hey Scott,

    im literally working on a WPF MVVM application and i have read some posts now about the mvvm pattern. And my question to you is why your code is now violating the mvvm pattern ?

    As i know the Model should implement the INotification

    So when we make a change for example on a textbox the binding in XAML to the ViewModel will initialize the logic in the Model (change text or sort it, etc.)
    So the communication is View -> ViewModel -> Model (where the actual business logic is inherited) -> through the INotification the View is refreshed.

    Or am I wrong?

    For me until know my viewmodel has only getter and setter and those relate to the model class.

    1. Hi Andre,

      You will find that ViewModels often have propertychanged notifications. I say this as someone who’s done contract development at dozens of companies over the last 38 years. The project I worked on today had propertychanged notifications in its ViewModels – and this is at a company whose gross revenue is larger than many countries gross domestic product.

      You could change this game to have a GameSession (model) class, and move the logic from the GameSessionViewModel class into GameSession. Then, you could have GameSessionViewModel completely empty except for a property that holds the GameSession object. That would eliminate the need to have propertychanged notifications in the ViewModel. But, then you’d have an almost-empty ViewModel that does nothing, and you’ve added another “layer” to your architecture. In a program this small, it’s not a real problem. But, in larger applications, this often leads to architectures that are difficult to understand, maintain, and modify.

      But, if you want to change the program to work differently, go ahead – as soon as you typed the code into your editor, it’s your code.

  8. Dear Scott Lilly:

    I am getting the following error: “‘MainWindow’ does not contain a definition for ‘ButtonBase_OnClick’ and no accessible extension method ‘ButtonBase_OnClick’ accepting a first argument of type ‘MainWindow’ could be found (are you missing a using directive or an assembly reference?)” I copy-pasted your code several times, so it looks exactly like yours. Why am I having this problem while you are not?

  9. Never mind. Visual Studio just magically decided it wanted to behave again and solved the problem itself. Thank you for your time anyway.

    1. That usually happens when someone accidentally double-clicks on the SuperAdventure class, when it’s in Design mode in Visual Studio. When you double-click a control in design mode, Visual Studio will create a function in SuperAdventure.cs and an “eventhandler” in SuperAdventure.Designer.cs that calls that function. Then, if you paste in the code from the lesson, the eventhandler can’t find its function.

      You can learn more about eventhandlers in lesson 21.3.

  10. great explanation! thank you. i also got caught out by not having the using directive but then spotted it at the top in the video 🙂 i’m on VS2017 and not using resharper yet so that might be it

    1. You’re welcome. Automatically adding required “using” directives is probably me favorite feature of ReSharper. But, it does make creating tutorials a little more difficult – since it’s easy to forget to mention it.

  11. I have problem with the Line :

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string PropertyName )
    {
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs (PropertyName));
    }

    I use Visual Studio 2010 on a low spec machine in office and the compiler doesn’t seem to understand the ” PropertyChanged?.Invoke ” part . there are red lines under it and the error is : ‘only Assignment, call, increment, decrement, and new object expressions can be used as statement’

    1. Hi Shahriar,

      If you’re using an older version of Visual Studio, you might not have the recent version of the .NET Framework – which has this feature. If you can’t upgrade to newer versions of the .NET Framework and Visual Studio, you should be able to do the same thing with this code:


      protected virtual void OnPropertyChanged(string PropertyName )
      {
      if(PropertyChanged != null)
      {
      PropertyChanged.Invoke(this, new PropertyChangedEventArgs (PropertyName));
      }
      }

      The “?” basically means, “If PropertyChanged is not null, try to run this function”. The code above does that by using an “if” to check if PropertyChanged is not null.

Leave a Reply

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