Reputation: 24602
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)
{
}
Upvotes: 0
Views: 47
Reputation: 121
To only answer your question.
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)
{
}
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
Upvotes: 1
Reputation: 12179
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:
View(Page)
is still aware of the ViewModel
.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.
Upvotes: 1
Reputation: 1268
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.
Upvotes: 1