C
C#4w ago
BigBallard

✅ Creating ViewModel for Maui doesn't propagate changes

I am attempting to cleanup my Maui app a bit and wanted to create an abstract class ViewModel that implements the boilerplate code for INotifyPropertyChanged. When I user ViewModel on an already functioning page, the properties are not being updated and displayed to the bound control. ViewModel
public abstract class ViewModel: INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;

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

protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
public abstract class ViewModel: INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;

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

protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
SignUpViewModel
using System.ComponentModel;
using System.Net.Mail;
using System.Runtime.CompilerServices;
using System.Windows.Input;

namespace ToolerMobile.Pages;

public class SignUpViewModel : ViewModel
{
private string _email = "", _errorMessage = "";

public string Email
{
get => _email;
set
{
_email = value;
ValidateForm();
}
}

public string ErrorMessage
{
get => _errorMessage;
private set
{
_errorMessage = value;
SetField(ref _errorMessage, value);
}
}

private void ValidateForm()
{
ErrorMessage = "";
try
{
if (_email.Length == 0)
{
return;
}
new MailAddress(_email);
}
catch (Exception e)
{
ErrorMessage = "Invalid email address.";
}
}
using System.ComponentModel;
using System.Net.Mail;
using System.Runtime.CompilerServices;
using System.Windows.Input;

namespace ToolerMobile.Pages;

public class SignUpViewModel : ViewModel
{
private string _email = "", _errorMessage = "";

public string Email
{
get => _email;
set
{
_email = value;
ValidateForm();
}
}

public string ErrorMessage
{
get => _errorMessage;
private set
{
_errorMessage = value;
SetField(ref _errorMessage, value);
}
}

private void ValidateForm()
{
ErrorMessage = "";
try
{
if (_email.Length == 0)
{
return;
}
new MailAddress(_email);
}
catch (Exception e)
{
ErrorMessage = "Invalid email address.";
}
}
With this, ErrorMessage changes are not shown in the app where if I implment INotifyPropertyChanged directly, it works.
12 Replies
ティナ
ティナ4w ago
you can set a break point to check why SetField doesnt call PropertyChanged
kurumi
kurumi4w ago
Take a look at Community Toolkit, it is much easier to work with it in MAUI Also it has a discord server which you can find here $mauitoolkit https://learn.microsoft.com/en-us/dotnet/architecture/maui/mvvm-community-toolkit-features
MVVM Toolkit Features - .NET
Helper components to simplify app development and maintenance
kurumi
kurumi4w ago
Just a small suggestion which simplifies MAUI boilerplate a lot
BigBallard
BigBallardOP4w ago
Ya but it also does a lot of code generation which I am not a big fan of. Plus it's another dependency.
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
BigBallard
BigBallardOP4w ago
It's a dependency to make things easier which are not that difficult to just do. newtonsoft is very much it's own thing compared to this. I prefer to not use code gen, that's just my preference, as it can make debugging more difficult and convoluted. This is from my experience. Debugged and found you can't set the backing variable yourself before SetField, kind of duh moment but I learned something.
leowest
leowest4w ago
its the other way around, sg's make it much easier to debug and u can access the generated code in visual studio on top of that, Newtonsoft is old .net comes with STJ out of the box and u should avoid Newstonsoft unless ur dealing with edge case scenarios or malform json STJ is not a dependency its plug and play, its only a dependency on .net framework where u can also use it
kurumi
kurumi4w ago
Even .net json tool is source generated to be compatible with native aot
leowest
leowest4w ago
specially if ur working with MAUI u should avoid these outdated solutions u mentioned
BigBallard
BigBallardOP4w ago
if it is so essential, why don't they make it default and not an extra optional package
leowest
leowest4w ago
no one said its essential its a really handful tooling and at the end of the day who decides what to use is you, or the specs imposed. there are other options out there too and the least invasive and less bloated is that and rejecting sg to use outdated libraries is just not a good turnaround specially with the new features introduced in ctk.mvvm which lets u use partial properties made it real nice https://devblogs.microsoft.com/dotnet/announcing-the-dotnet-community-toolkit-840/

Did you find this page helpful?