'Does mvvmcross have a built-in message for viewmodel to tell view when ViewAppearing/Disappearing happen?

I have logic to be executed in a Xamarin.Forms ContentView (not a Page), when it appears and disappears. This is an mvvmcross content view:

public partial class MyContentView : MvxContentView

I would expect this to be a common need, but I'm not finding a built-in mvvmcross method call or override for this. Is there one? [There was a multiple-year discussion about adding these to Xamarin.Forms itself, but that was never implemented. I was hoping mvvmcross addressed this for views, as they did for their viewmodels.]

NOTE: I'm aware of multiple ways I could roll my own; but surely this is fundamental; built-in?


For completeness, here are the alternatives I'm aware of:

  • "Appearing" I can approximate well enough via override OnViewModelSet. But I don't see a corresponding override for the view going away.
  • In OnViewModelSet, could hook up a Binding Set and a Binding or two. To leverage MvxViewModel's lifecycle events. This is my current plan; will add to my BaseView class. So my inheritance hierarchy becomes MyContentView : BaseView : MvxContentView.
  • MvxMessaging (or Xamarin.Forms MessageCenter).

So there are plenty of alternatives. I just feel that I must be overlooking something, since this seems like a common, standard, need. After all, each platform has its own view life-cycle methods. And mvvmcross has corresponding viewmodel life-cycle methods. I'm just trying to get the cross-platform Xamarin.Forms view to have the same life-cycle methods - without inventing my own solution.



Solution 1:[1]

The most concise (for the View) solution I've found so far is to add a standard c# EventHandler to my base MvxViewModel. And a property that toggles as viewmodel appears and disappears. Property's setter invokes the event handler.

viewmodel:

public class BaseViewModel : MvxViewModel
{
    // ...
    
    public event EventHandler<BoolEventArgs> AppearingStateEvent;

    private bool _AppearingState;
    public bool AppearingState
    {
        get => _AppearingState;
        set
        {
            SetProperty(ref _AppearingState, value);
            AppearingStateEvent?.Invoke(this, new BoolEventArgs(value));
        }
    }

    public override void ViewAppearing()
    {
        base.ViewAppearing();
        AppearingState = true;
    }

    public override void ViewDisappearing()
    {
        AppearingState=false;
        base.ViewDisappearing();
    }
}

uses class:

    public class BoolEventArgs : EventArgs
    {
        public bool Value;
        public BoolEventArgs(bool value)
        {
            Value = value;
        }
    }

view:

public class BaseContentView : MvxContentView
{
    // ...
    
    protected override void OnBindingContextChanged()
    {
        base.OnBindingContextChanged();

        if (ViewModel is BaseViewModel vm)
        {
            // Remove old, in case we get here twice. Avoids duplicate events.
            vm.AppearingStateEvent -= Vm_AppearingStateEvent;
            vm.AppearingStateEvent += Vm_AppearingStateEvent;
        }
    }

    protected virtual void Vm_AppearingStateEvent(object sender, BoolEventArgs e)
    {
        bool appearingState = e.Value;
        // ...
    }
}

View subclasses can override Vm_AppearingStateEvent, to perform actions when view appears or disappears.

Solution 2:[2]

No, we do not publish any messages when the ViewModel changes, nor on lifecycle changes.

Our ViewModels are lifecycle aware, where you can override OnViewAppeared, OnViewDisappeared etc. in the ViewModel. To have these work you need to use MvvmCross variants of Activity/Fragment/ViewController, if you assign a ViewModel to a custom control, you need to call these methods yourself.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Cheesebaron