Search code examples
wpfmvvmcross

How to pop to root


I am writing a WPF application with MvvmCross. I have a custom view presenter that I want to use so that I can pop multiple view models in 1 shot. Here is my view presenter:

public class ViewPresenter : MvxWpfViewPresenter
{
    ContentControl _contentControl;

    Type _currentViewModelType;
    IMvxViewModel _rootViewModel;

    public ViewPresenter(ContentControl c) : base(c)
    {
        _contentControl = c;

        AddPresentationHintHandler<SetRootHint>(SetRootHintHandler);
        AddPresentationHintHandler<PopToRootHint>(PopToRootHintHandler);
    }

    protected override void ShowContentView(FrameworkElement element, MvxContentPresentationAttribute attribute, MvxViewModelRequest request)
    {
        base.ShowContentView(element, attribute, request);

        _currentViewModelType = request.ViewModelType;
    }

    private bool SetRootHintHandler(SetRootHint hint)
    {
        _rootViewModel = hint.CurrentViewModel;

        return true;
    }

    private bool PopToRootHintHandler(PopToRootHint hint)
    {
        // How to pop all the way down to _rootViewModel ?

        return true;
    }
}

How can I pop all the way back to _rootViewModel? Is there a better way of popping back multiple view models in one shot?


Solution

  • I ended up writing a helper class that keeps a reference of all the view models, as well as the one you set as the Root. And then I can just call my PopToRoot method.

    public class NavigationStack
    {
        private readonly List<IMvxViewModel> _stack;
    
        public IMvxViewModel Root { get; set; }
    
        public NavigationStack()
        {
            _stack = new List<IMvxViewModel>();
        }
    
        public void AddToStack(IMvxViewModel viewModel)
        {
            _stack.Add(viewModel);
        }
    
        public async Task PopToRoot(IMvxNavigationService navigationService)
        {
            if (Root == null)
            {
                throw new Exception("Can not pop to root because Root is null.");
            }
            else
            {
                _stack.Reverse();
    
                foreach (var v in _stack)
                {
                    if (v != Root)
                    {
                        await navigationService.Close(v);
                    }
                    else
                    {
                        break;
                    }
                }
    
                _stack.Clear();
            }
        }
    }
    

    It works, but I'm not sure if this is a good idea since I'm keeping a reference to all the IMvxViewModel in my app, and closing them one after another...does anyone know if this code can cause any problems in the framework?