Search code examples
c#xamarinxamarin.formsfreshmvvm

FreshMVVM and resetting VM before popping Modal


  • FreshMVVM 3.0.0
  • Xamarin Forms 4.2

A number of our input pages are loaded modally and when the user presses Save we execute a Command like this

var newTemperature = new Temperature()
{
    Date = DateTime.Now,
    Value = this.TemperatureValue,
    CaptureType = CaptureType.Manual,
    IsModified = true,
};

await this.Services.DataService.SaveAsync(newTemperature);

// Save completed, now close modal.
await this.CoreMethods.PopPageModel(data, modal, animate);

If you look at the CoreMethods.PopPageModel call in GitHub you can see that it deals with two processes

  1. Raising the PageWasPopped signal
  2. Calling to the Navigation Service to pop the page off of the navigation stack

The FreshMVVM code that handles the page being popped is in FreshPageModel. Among other things the code unhooks from the Appearing and Disappearing events and sets the BindingContext to null. As you can see from the above order that means the BindingContext on the View is set to null before it is popped off the stack.

The problem with this is that for a short period of between 0.5 and 1.5 seconds the user sees a View that looks like the data has all been reset. This could be quite disconcerting if they have just pressed Save.

If I reverse the order of the logic in PopPageModel and pop from the navigation stack before calling RaisePageWasPopped this issue goes away.

Has nobody else seen this problem before?

Any users of FreshMVVM who want to point out the error of my suggested approach?


Solution

  • Our solution to this issue was to implement our own PopPageModel method which essentially switches the order around so that PopPage is called on the Navigation Stack before a call to RaisePageWasPopped

    This is what we call when we want to dismiss the Page

    public Task DismissAsync(bool modal = true, bool animate = true)
    {
        return this.DispatcherService.RunOnUiThreadAsync(
            async () =>
                {
                    string navServiceName = this.CurrentNavigationServiceName;
                    if (this.IsModalFirstChild)
                    {
                        await this.CoreMethods.PopModalNavigationService(true);
                    }
                    else
                    {
                        IFreshNavigationService rootNavigation = FreshIOC.Container.Resolve<IFreshNavigationService>(navServiceName);
                        await rootNavigation.PopPage(modal, animate);
    
                        if (modal)
                        {
                            this.RaisePageWasPopped();
                        }
                    }
                });
    }