简体   繁体   中英

How can I modify my application from VM making direct calls to the back end C# to instead use Xamarin MessagingCenter?

I am using ICommand like this but from what I understand it would be better to use the Xamarin MessagingCenter. Can someone suggest how I could change my code so as to use that and what changes would be needed.

public partial class SettingsPageViewModel : BaseViewModel
{
    public ICommand OpenPageCmd { get; }
    public SettingsPageViewModel(SettingsPage settingsPage)
    {
        this.settingsPage = settingsPage;
        OpenPageCmd = new Command<string>((pageType) => settingsPage.OpenPage(pageType));
    }

public partial class SettingsPage : ContentPage
{

    SettingsPageViewModel vm;

    public SettingsPage()
    {
        InitializeComponent();
        vm = new SettingsPageViewModel(this);
        BindingContext = vm;
    }

    public void OpenPage(string pageType)
    {  
    }

This is a big misconception. The point of MVVM is to separate the logic and the view of your app. Right here you are passing a reference of the page to the viewmodel, this breaks the whole idea of MVVM.

  • OpenPageCmd should execute a method located in the viewmodel/businesslogic (which handles opening a new page)
  • Remove "OpenPage(...)" in your ContentPage.
  • You don't need the MessagingCenter at all in this scenario

To only answer your question.

  1. You need to Subscribe for a message in your SettingsPage code behind

     public SettingsPage() { InitializeComponent(); vm = new SettingsPageViewModel(this); BindingContext = vm; MessagingCenter.Subscribe<SettingsPageViewModel, string>(this, "NavigateToSettings", NavigateToSettingsAction); } private void NavigateToSettingsAction(MainViewModel obj, string pageType) { OpenPage(pageType); } public void OpenPage(string pageType) { } 
  2. Send Message from within the OpenPageCmd command in SettingsPageViewModel

     public SettingsPageViewModel() { OpenPageCmd = new Command<string>((pageType) => { MessagingCenter.Send(this, "NavigateToSettings", pageType); }); } 

the code above should achieve what you need. Keep in mind, you should never reference any View from within ViewModel like you did. And my own approach is to Navigate using a Navigation Service but this is a whole other story.

EDIT

Here is a link to an example of implementing Navigation Service using MVVMLight

https://mallibone.com/post/xamarin.forms-navigation-with-mvvm-light

Since I answered your previous question and I understand the context, though it will make sense if I will reply. The misconceptions should be clear at this point as the question is about how to improve this code.

MessagingCenter is easy to use and at the same time to misuse. You have to make sure to subscribe and unsubscribe properly. Usually you do so on OnAppearing and OnDisappearing methods. Here is an example:

public partial class SettingsPageViewModel : BaseViewModel
{
    public ICommand OpenPageCmd { get; }
    public SettingsPageViewModel()
    {
        OpenPageCmd = new Command<string>((pageType) =>   MessagingCenter.Send(new MyFirstMessage(pageType), MyFirstMessage.Message));
    }
}
public class MyFirstMessage
{
    public static readonly string Message = nameof(MyFirstMessage);
    public string PageType { get; }

    public MyFirstMessage(string pageType)
    {
        PageType = pageType;
    }
}

public partial class SettingsPage : ContentPage
{
    SettingsPageViewModel vm;

    public SettingsPage()
    {
        InitializeComponent();
        vm = new SettingsPageViewModel(this);
        BindingContext = vm;
    }

   protected override void OnAppearing()
    {
        base.OnAppearing();
        MessagingCenter.Subscribe(this, MyFirstMessage.Message, (MyFirstMessage obj) => OpenPage(obj.PageType));
    }

    protected override void OnDisappearing()
    {
        base.OnDisappearing();
        MessagingCenter.Unsubscribe<MyFirstMessage>(this, MyFirstMessage.Message);
    }

    void OpenPage(string pageType)
    {

    }
}

Beside that, I can spot at least another 2 issues in the provided example:

  1. The View(Page) is still aware of the ViewModel .
  2. It seems that you need a NavigationService instead of using MessagingCenter .

Both issues can be easily solved, but the solution is to long to type and involves different aspects. Therefore, I would recommend to check architecture examples on github .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM