Pass OnAppearing to a ViewModel in Xamarin Forms MVVM?

Viewed 7830

I have business logic that loops around and does waits and other things. Currently this is in the code behind.

From what I have been able to read this is the wrong place and I should be placing this in the viewModel (correct me if wrong). If that's the case then should I have an OnAppearing method in my VM and if so how should I pass the OnAppearing to the View Model?

Currently my page OnAppearing looks like this:

    protected async override void OnAppearing()
    {
        base.OnAppearing();
        Title = Settings.mode.Text() + " Deck";
        vm.LearnViewVisible = Settings.mode.IsLearn();
        vm.PracticeViewVisible = Settings.mode.IsPractice();
        vm.QuizViewVisible = Settings.mode.IsQuiz();
        vm.QuizStartViewVisible = false;

If I am to be moving most of the business logic to the ViewModel then would that mean that all of this would move to an OnAppearing() method I create in the ViewModel?

3 Answers

Other way is using Behaviors.Forms from David Britch

    ...
    <ContentPage.Behaviors>
        <behaviors:EventHandlerBehavior EventName="Appearing">
            <behaviors:InvokeCommandAction Command="{Binding PageAppearingCommand}" />
        </behaviors:EventHandlerBehavior>
        <behaviors:EventHandlerBehavior EventName="Disappearing">
            <behaviors:InvokeCommandAction Command="{Binding PageDisappearingCommand}" />
        </behaviors:EventHandlerBehavior>
    </ContentPage.Behaviors>
    ...

Original

Or Xamarin Community Toolkit EventToCommandBehavior

    <ContentPage.Behaviors>
            <xct:EventToCommandBehavior
                EventName="Appearing"
                Command="{Binding PageAppearingCommand}" />
            <xct:EventToCommandBehavior
                EventName="Disappearing"
                Command="{Binding PageDisappearingCommand}" />
    </ContentPage.Behaviors>

Related Question: EventHandlerBehavior vs EventToCommandBehavior

This is how i link my Viewmodel. I would recommend setting up a ViewModelBase with : VModelActive and VModelInactive

Code Behind:

public partial class YourClass : ContentPage
    {
        ViewModelClass viewModelClass;
        public YourClass()
        {
            InitializeComponent();
            viewModelClass = new ViewModelClass();
            this.BindingContext = viewModelClass;                
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            viewModelClass.VModelActive(this, EventArgs.Empty);
        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();
            viewModelClass.VModelInactive(this, EventArgs.Empty);
        }
    }

View Model

public override void VModelActive(Page sender, EventArgs eventArgs)
        {
            base.VModelActive(sender, eventArgs);
            //your code 
        }

public override void VModelInactive(Page sender, EventArgs eventArgs)
        {
            base.VModelInactive(sender, eventArgs);
            //your code
        }

Here is example from my solution

public partial class TaskDetailsPage : MvvmContentPage
{
    private readonly TaskDetailsViewModel _model;

    public TaskDetailsPage()
    {
        InitializeComponent();
        Shell.SetNavBarIsVisible(this, true);
        Shell.SetTabBarIsVisible(this, false);
        _model = BindingContext as TaskDetailsViewModel;
    }

    protected override string NavigationRoute => UniqeCodes.Routes.TaskDetailsPage;

    

    protected override void OnAppearing()
    {
        _model.Init();
    }
}

Related