1
Answer

How to deal with viewmodels whose actions affect each other?

Hey folks,

I got an MVVM dotnet project using the mvvm community toolkit.

Now I am facing a situation where I have one viewmodel A which offers a user action that will modify the database and because
of this change my viewmodel B needs requery the database and update its data.
I came across events or messaging which provides me with an option for viewmodel-to-viewmodel communication, but afaik
all options only support sync function execution and no async option (but I deal with database so it must be async I think).

My current way to solve it is the following, but I am unsure if this is the recommended common best approach.

CommunityToolkit.Mvvm.Messaging.Messages;

public sealed class NotifyMessage : ValueChangedMessage<string>
{
    public NotifyMessage(string value) : base(value) { }
}

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;


public partial class ViewModelA : ObservableObject
{
    public ViewModelA()
    {
    }

    private void UpdateData()
    {
        // do stuff
        SendMessage();
    }

    private void SendMessage()
    {
        WeakReferenceMessenger.Default.Send(new NotifyMessage("Data update in A"));
    }
}

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using System.Diagnostics;


public partial class ViewModelB : ObservableObject, IRecipient<NotifyMessage>, IDisposable
{
    [ObservableProperty] private string _lastMessage = "B";

    public ViewModelB()
    {
        WeakReferenceMessenger.Default.Register<NotifyMessage>(this);
    }

    public async void Receive(NotifyMessage message)
    {
        LastMessage = message.Value;
        try {
            await RefreshData();
        }
        catch (Exception e)
        {
            Console.WriteLine("ERROR: " + e.Message);
        }
    }

    private async Task RefreshData()
    {
        await Task.Delay(1000);
        Console.WriteLine(LastMessage);
    }

    public void Dispose()
    {
        WeakReferenceMessenger.Default.Unregister<NotifyMessage>(this);
    }
}


In viewmodel B I have one "async void" which is bad. But I don't see how to get around that otherwise. Or do I have a architectural issue and this should not rise?
I am a bit confused because this should be a quite common problem, but I didn't found any way to solve it in a good way.

Answers (1)