When developing with the MVVM pattern, there are many cases where you need to deliver events from one ViewModel to another or from a ViewModel to a View in a 1:1 or 1:N manner. In this case, you can create a static class to handle events accessible globally, or create a service class to handle event variables accessible from multiple ViewModels through dependency injection. However, using the WeakReferenceMessenger class provided by CommunityToolkit, you can easily implement a Pub/Sub style event queue.
Although it is simple and convenient to use, in practice, there are many cases where you need to apply debounce time to the event stream or use the event buffer as a ring buffer, which is not possible with WeakReferenceMessenger, so it is a bit disappointing.
To understand the simple usage, I will explain based on the code written in the previous article.
Goal: When a button is clicked in the View, use WeakReferenceMessenger to send a message from MainWindowViewModel to MainWindowView to display "Hello World" in the TextBox control.
It is easy to handle events from View to ViewModel through binding, but it is not easy to make the View perform a specific action by triggering an arbitrary event from the ViewModel, so we will implement this using WeakReferenceMessenger.
Create a Messages folder in the project and create a TestMessage class file.
using CommunityToolkit.Mvvm.Messaging.Messages;
namespace MyTestApp.Messages
{
public class TestMessage : ValueChangedMessage<string>
{
public TestMessage(string text) : base(text)
{
}
}
}
MainWindow.xaml.cs
using CommunityToolkit.Mvvm.Messaging;
using MyTestApp.Messages;
using System.Windows;
namespace MyTestApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
WeakReferenceMessenger.Default.Register<TestMessage>(this, (r, m) =>
{
ctlTextBox.Text = m.Value;
});
}
}
}
MainWindowViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using MyTestApp.Messages;
namespace MyTestApp.ViewModels
{
public partial class MainWindowViewModel : ObservableObject
{
[ObservableProperty]
private string title;
public MainWindowViewModel()
{
Title = "Initial Value";
}
[RelayCommand]
private void SendMessage()
{
WeakReferenceMessenger.Default.Send(new TestMessage("Hello World"));
}
}
}
MainWindow.xaml
<Window x:Class="MyTestApp.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:MyTestApp"
mc:Ignorable="d"
Title="MainWindow"
Height="450"
Width="800"
DataContext="{Binding Source={StaticResource VmLocator}, Path=MainWindowVM}">
<Grid>
<StackPanel Orientation="Vertical">
<TextBox Text="{Binding Title}" />
<Button Content="Click Here"
Command="{Binding SendMessageCommand}" />
<TextBox x:Name="ctlTextBox" />
</StackPanel>
</Grid>
</Window>
Now, after compiling and running, you can see "Hello World" displayed in the TextBox when you click the button.
ยฉ 2025 juniyunapapa@gmail.com.