How to request message in WinUI 3 with MVVM Toolkit?

403 Views Asked by At

Goal and sitatuion:

I Just follow the ‘Request Messages’ examples from MVVM Tooolkit Sample app but it doesn't work.

The problem:

My ‘Username’ and RequestCurrentUserName() becomes null (see the image) or the below code.

Maybe my code is just wrong or can I get the error because I don’t have IsActive on my UserSenderViewModel Somewhere? And how should I do it? They are using OnActivated().

Screenshot of error in debugging mode

ViewModel

https://github.com/CommunityToolkit/MVVM-Samples/blob/master/samples/MvvmSample.Core/ViewModels/MessengerPageViewModel.cs

public class ViewModelRequestMessenger: ObservableObject
{

    public class UserSenderViewModel : ObservableRecipient
    {
        public string Username { get; private set; } = "Bob";

        protected override void OnActivated()
        {
            Messenger.Register<UserSenderViewModel, CurrentUsernameRequestMessage>(this, (r, m) => m.Reply(r.Username));
        }
    }


    private string username;

    public string Username
    {
        get => username;
        private set => SetProperty(ref username, value);
    }

    // Sends a message to request the current username, and updates the property
    public void RequestCurrentUsername()
    {
        Username = WeakReferenceMessenger.Default.Send<CurrentUsernameRequestMessage>();
    }

    // Resets the current username
    public void ResetCurrentUsername()
    {
        Username = null;
    }

    // A sample request message to get the current username
    public sealed class CurrentUsernameRequestMessage : RequestMessage<string>
    {
    }

}

MainWindow.xaml

     <StackPanel Spacing="8">
        <StackPanel.DataContext>
            <viewmodels:ViewModelRequestMessenger x:Name="ViewModel"/>
        </StackPanel.DataContext>
        <TextBlock Text="{x:Bind ViewModel.Username, Mode=OneWay}"/>
        <Button
        Content="Click to request the username!"
        Click="{x:Bind ViewModel.RequestCurrentUsername}"/>
        <Button
        Content="Click to reset the local username!"
        Click="{x:Bind ViewModel.ResetCurrentUsername}"/>

    </StackPanel>

Code-Behind MainWindow.xaml.cs

    public sealed partial class MainWindow : Window
    {
        //private ViewModelRequestMessenger ViewModel { get; } = new();
        
        public MainWindow()
        {
            this.InitializeComponent();
            //this.ViewModel = new ViewModelRequestMessenger(); 
        }

    }
1

There are 1 best solutions below

0
Roy Li - MSFT On BEST ANSWER

I checked the sample, and you might forget to set the IsActive of the SenderViewModel to True.

Made a simple demo based on the sample and it works correctly. You could check the following code.

Xaml:

  <StackPanel Spacing="8">
        <TextBlock Text="{x:Bind ViewModel.Username, Mode=OneWay}"/>
        <Button
    Content="Click to request the username!"
    Click="{x:Bind ViewModel.RequestCurrentUsername}"/>
  </StackPanel>

Code-behind:

public sealed partial class MainWindow : Window
{
    public MessengerRequestModel ViewModel { get; set; }

    public MainWindow()
    {
        this.InitializeComponent();
        ViewModel = new MessengerRequestModel();
        // you might miss this 
        ViewModel.SenderViewModel.IsActive = true;
    }
   
}

public class MessengerRequestModel : ObservableObject
{
    public ICommand RequestCurrentUsernameCommand { get; }

    public UserSenderViewModel SenderViewModel { get; } = new();


    // Simple viewmodel for a module sending a username message
    public class UserSenderViewModel : ObservableRecipient
    {
        public UserSenderViewModel()
        {
            SendUserMessageCommand = new RelayCommand(SendUserMessage);
        }

        public ICommand SendUserMessageCommand { get; }

        private string username = "Bob";

        public string Username
        {
            get => username;
            private set => SetProperty(ref username, value);
        }

        protected override void OnActivated()
        {
            Messenger.Register<UserSenderViewModel, CurrentUsernameRequestMessage>(this, (r, m) => m.Reply(r.Username));
        }

        public void SendUserMessage()
        {
            Username = Username == "Bob" ? "Alice" : "Bob";

            Messenger.Send(new UsernameChangedMessage(Username));
        }
    }

  

    private string? username;

    public string? Username
    {
        get => username;
        private set => SetProperty(ref username, value);
    }

    public void RequestCurrentUsername()
    {
        Username = WeakReferenceMessenger.Default.Send<CurrentUsernameRequestMessage>();
    }

    public void ResetCurrentUsername()
    {
        Username = null;
    }

    // A sample message with a username value
    public sealed class UsernameChangedMessage : ValueChangedMessage<string>
    {
        public UsernameChangedMessage(string value) : base(value)
        {
        }
    }

    // A sample request message to get the current username
    public sealed class CurrentUsernameRequestMessage : RequestMessage<string>
    {
    }

}