The Problem
I spent some time looking at ways to reduce all the repetitive property declarations required for MVVM. So have a lot of other people, most of whom are far smarter than me.
The Community Toolkit looked very promising.
But even though it claims to work in VB and .Net Framework it does not. No errors, no warnings, no binding errors, modifying properties in controls does not update the bound properties. So that's a shame.
The good news
One of my colleagues recommend FODY - a GitHub project that claims to work for VB in .Net Framework. OK - I'm game. I put together the most trivial project I could think of. We have our ViewModels in our code-behind, we use VB, and we're still on .Net Framework. Yes, we're practically Neanderthal.
FODY is much bigger than simply providing MVVM functionality. It's a framework for all sorts of things. The specific package I need is called PropertyChanged.Fody. Let's get started then.
In Visual Studio 2022 create a WPF, VB, .NetFramework project called FODY
In the menu select Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution...
Click the Browse tab and search for FODY
Install Fody and PropertyChanged.Fody into your solution. Your packages.config will look something like this.
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Fody" version="6.8.1" targetFramework="net472" developmentDependency="true" />
<package id="PropertyChanged.Fody" version="4.1.0" targetFramework="net472" />
</packages>
Now we will write some standard XAML with a text box and a text block. Whatever you type in the text box will appear in the text block thanks to some MVVM bindings. Fody does not require any changes to your XAML.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FODY"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="FODY Test" Height="450" Width="800">
<StackPanel Orientation="Vertical" HorizontalAlignment="Left">
<TextBox Text="{Binding theText, UpdateSourceTrigger=PropertyChanged}" Width="100"/>
<TextBlock Text="{Binding theText}"/>
</StackPanel>
</Window>
Without clever add-ins the view model would look something like this. Which requires a lot of typing.
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Class MainWindow
Implements INotifyPropertyChanged
Private _theText As String = ""
Public Property theText As String
Get
Return _theText
End Get
Set(value As String)
SetProperty(_theText, value)
End Set
End Property
Public Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Public Function SetProperty(Of T)(ByRef storage As T, value As T, <System.Runtime.CompilerServices.CallerMemberName> Optional PropertyName As String = Nothing) As Boolean
If Object.Equals(storage, value) Then Return False
storage = value
NotifyPropertyChanged(PropertyName)
Return True
End Function
Public Sub NotifyPropertyChanged(<System.Runtime.CompilerServices.CallerMemberName> Optional PropertyName As String = Nothing)
RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(PropertyName))
End Sub
End Class
The end result predictably looks like this
But with Fody we can replace these 30 lines of code with something far more succinct.
Imports PropertyChanged
<AddINotifyPropertyChangedInterface>
Class MainWindow
Public Property theText As String = ""
End Class
Which gives us exactly the same result.
A common technique for investigating binding issues is to put break points on property getters and setters to make sure they are being called when expected. Setter not called when the user modifies a control - check UpdateSourceTrigger. Getter not called after the setter is called - control is not bound to the property. When we don't have explicit setters and getters, we can't use these techniques.
So maybe all that repetitive code has value after all.
No comments:
Post a Comment