In this lesson, we’re going to get rid of our base class that handles PropertyChanged notifications. We’ll replace it with a NuGet package that automatically handles these notifications for all properties.
This change eliminates something I didn’t really like about the BaseNotificationClass.
Normally, inheritance is used to create child classes that are more-specific versions of the parent class. For example, the Player and Monster classes are more-specific versions of LivingEntity.
The model and viewmodel classes aren’t more-specific versions of BaseNotificationClass. They’re just classes where we want to implement this common property changed notification behavior. So, getting rid of BaseNotificationClass seems cleaner to me.
A big problem in programming is that many programmers suffer from Not-Invented-Here Syndrome – a refusal to use well-written and well-supported libraries.
Many of us like to solve the puzzles around programming and think the best decision is to always write our own code. I once worked on a project where a programmer spent a month writing a function that could have literally been done with two lines of code using a library that the project was already using. The worst part was that the hand-written code had several bugs.
So, instead of continuing to use our BaseNotificationClass, we’re going to use the Fody code weaver NuGet package. This package lets us add features that automatically are added when we compile our code. The most popular feature is to automatically raise PropertyChanged notifications.
Step 1: Add Fody NuGet packages
In the Engine, SOSCSRPG.Models, and SOSCSRPG.ViewModels projects, add these two NuGet packages:
- Fody
- PropertyChanged.Fody
Step 2: Create FodyWeavers.xml files
In the Engine, SOSCSRPG.Models, and SOSCSRPG.ViewModels projects, create a FodyWeavers.xml file with the contents below:
<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<PropertyChanged />
</Weavers>
Step 3: Delete Engine\BaseNotificationClass.cs
Step 4: Fix classes that were using BaseNotificationClass
In the classes that were inheriting from BaseNotificationClass, make the following changes:
- Add “using System.ComponentModel;” to the using directives
- Replace BaseNotificationClass inheritance with INotifyPropertyChanged implementation
- Add “public event PropertyChangedEventHandler PropertyChanged;”
- Delete all calls to OnPropertyChanged from the setters
The files to change are:
Engine\Models\GroupedInventoryItem
Engine\Models\LivingEntity
Engine\Models\PlayerAttribute
Engine\Models\QuestStatus
Engine\ViewModels\CharacterCreationViewModel
Engine\ViewModels\GameSession
Engine\Models\Player only needs to have the call to OnPropertyChanged removed, since it’s getting the other behavior by inheriting from the LivingEntity class
Step 5: Test the game
NEXT LESSON: Lesson 19.5: Convert properties to auto-properties
PREVIOUS LESSON: Lesson 19.3: Move data and image files out of Engine project
Hi Scott,
a few lessons back, we deleted our empty (standard) constructors, leaving only the ones where we pass in parameters, like the GameSession constructor.
I don’t know if this is a .NET6 specific problem, but since i deleated these empty constructors, i get compile errors, telling me, that no standard empty constructor for a certain type (like in GameSession) was found.
We use GameSession as DataContext for our Data Binding in WPFUI, to get some intellisense. Not having an empty constructor leads to the above compile error.
Putting one back in results in NullReferenceExceptions for my GameSession Properties like “HasLocationToNorth” when starting a new game.
I am a bit confused on why this is happening, because your compiles seem to run fine without these problems.
Do you have any hints on what i could do to solve this issue?
Nevermind… i had some “stupid-code” in MainWindow.xaml that forced me to have a paremeterless constructor.
I used to have this code in there:
The resulting error:
Type ‘GameSession’ is not usable as an object element because it is not public or does not define a public parameterless constructor or a type converter.
Can’t really remember why i put it there… probably because i had some problems getting intellisense to work, before you started to implement it or show how to do it.
I am always annoyed from WPF not showing intellisense and allways having to guess if the property is typed correctly.
Ok for some reason unknown, my XAML code got swallowed by the webpage. xD
Doesn’t want me to inject code into your page i guess, lol
Lets try without the brackets…
Window.DataContext
viewmodel:GameSession
Window.DataContext
Any comments that have a less than sign in them get modified, since that’s a potential was for someone to do XSS (Cross-Site Script injection) in the site. The best way to share source code in a comment here is probably to post it at https://gist.github.com/, then share the link to the gist page.
Thanks, thats good to know.
I don’t think Visual Studio has ever been perfect with XAML editing – especially IntelliSense. That’s one area I wish it would improve. I haven’t tried VS Code or JetBrains Rider, but they might handle XAML editing better.