iosxamarin.iosmonotouch.dialog

ViewDidAppear on a UINavigationController not getting called when navigating back


I have a UITabBarController that hosts 5 UINavigationControllers (let's call them N1 - N5). Each of the UINavigationControllers has UI elements that cause a UITableViewController to be pushed onto the navigation stack (I use MonoTouch.Dialog DialogViewController to implement these UITableViewControllers). Let's call those T1 - T5.

When I navigate between the tabs, the ViewDidAppear method gets called on each of N1 - N5 as expected. But when I touch a UI element on, say, N1, that causes T1 to get pushed onto the nav stack, and then try to go back using the back button, N1's ViewDidAppear method doesn't get called.

The funny thing is that if I "tab over" to a different tab (say N2) and then "tab back" to N1, the ViewDidAppear will be called as normal. And even if I have T1 pushed onto the nav stack, if I do the same tabbing around, N1's ViewDidAppear will still be called.

The MonoTouch code for N1 looks like this:

public class CalendarPage : UINavigationController
{
    private DialogViewController dvc;

    public override void ViewDidAppear (bool animated)
    {           
        // initialize controls
        var now = DateTime.Today;
        var root = new RootElement("Calendar")
        {
            from it in App.ViewModel.Items
                where it.Due != null && it.Due >= now
                orderby it.Due ascending
                group it by it.Due into g
                select new Section (((DateTime) g.Key).ToString("d")) 
                {
                    from hs in g
                        select (Element) new StringElement (((DateTime) hs.Due).ToString("d"),
                            delegate 
                            {
                                ItemPage itemPage = new ItemPage(this, hs);
                                itemPage.PushViewController();
                            })
                        { 
                            Value = hs.Name
                        }                                                    
                }
        };

        if (dvc == null)
        {
            // create and push the dialog view onto the nav stack
            dvc = new DialogViewController(UITableViewStyle.Plain, root);
            dvc.NavigationItem.HidesBackButton = true;  
            dvc.Title = NSBundle.MainBundle.LocalizedString ("Calendar", "Calendar");
            this.PushViewController(dvc, false);
        }
        else
        {
            // refresh the dialog view controller with the new root
            var oldroot = dvc.Root;
            dvc.Root = root;
            oldroot.Dispose();
            dvc.ReloadData();
        }
        base.ViewDidAppear (animated);
    }
}

Solution

  • I figured out what was going on. When the back button is pressed on the inner DialogViewController (created in ItemPage), the outer DialogViewController ("T1" above) is now the first responder, NOT the UINavigationController ("N1"). My confusion stemmed from the fact that I turned the back button off on that outer DialogViewController so I was assuming I had popped out all the way to the UINavigationController (N1), whereas I was still in a DialogViewController (T1).

    I implemented the desired behavior (refreshing the contents of "T1") by creating a ViewDissapearing event on the inner DialogViewController (ItemPage in this case) and checking whether I am popping out - and if so, invoking the parent controller's ViewDidAppear method.

            actionsViewController.ViewDissapearing += (sender, e) => 
            {
                if (actionsViewController.IsMovingFromParentViewController)
                    controller.ViewDidAppear(false);
            };
    

    Note the funny thing about this code is that the property that actually works is IsMovingFromParentViewController, NOT IsMovingToParentViewController (which is intuitively what you'd think would be set when you're navigating back). I imagine this may be a bug in MT.Dialog, but something that can't be fixed for back-compact reasons.

    I hope this ends up helping someone...