Corstiaan
Corstiaan

Reputation: 1114

Pushing a DialogViewController onto a ViewController onto NavigationController stack gives 2 pages

Noob Xamarin/MonoTouch.Dialog question: I have laid out my iOS app in the storyboard designer of Xamarin Studio. I have a UINavigationController with a root view containing a UITableView with static cells, essentially creating a main menu. The cells segue to their respective UIViewControllers.

I want to layout the about/settings screen using MonoTouch.Dialog. However, I am running into some issues combining the overall storyboard approach with the partial MonoTouch.Dialogue approach due to my newbie-ness in Xamarin/MonoTouch.Dialog

When I instantiate a new DialogViewController on the UIViewController that got segued to from the initial UITableView (AccountViewController), I get essentially two views added to the navigation stack, the first only appearing briefly and then showing the DialogViewController. My code instantiating the DialogViewController is this:

partial class AccountViewController : UIViewController
{
    public AccountViewController (IntPtr handle) : base (handle)
    {
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
        var root = new RootElement ("Settings") {
            new Section (){
                new BooleanElement ("Airplane Mode", false),
                new RootElement ("Notifications", 0, 0) {
                    new Section (null, 
                        "Turn off Notifications to disable Sounds\n" +
                        "Alerts and Home Screen Badges for the\napplications below."){
                        new BooleanElement ("Notifications", false)
                    }
                }}
        };
        var dialog = new DialogViewController (root, true);
        this.NavigationController.PushViewController (dialog, true);
        //this.NavigationController.PresentViewController (dialog, true, null); tried this but then the UINavigationController shows no back buttons
        //View.AddSubview (dialog.View); tried this but then the UINavigationController shows no back buttons
    }   
}

I'm probably pushing the DialogViewController to late in the stack, creating the intermediary blank screen, but I can't figure out where the right place is to push the DialogViewController into the navigation stack given my current architecture. Most samples in the interwebs are nearly 100% MonoTouch.Dialog, no storyboard...

Thanks!

Upvotes: 0

Views: 1537

Answers (2)

Corstiaan
Corstiaan

Reputation: 1114

I fixed it in the following way:

I created a custom class for my TableViewController (containing a TableView with static cells):

partial class MainMenuTableViewController : UITableViewController
{
    public MainMenuTableViewController (IntPtr handle) : base (handle)
    {
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
        this.TableView.Delegate = new MainMenuTableViewDelegate (this); //this is the important part. Here I set a custom delegate class for the TableView. I pass the current TableViewController as a parameter in the constructor so I can call the NavigationController from the delegate class to push my custom MonoTouch DialogViewController onto the navigation stack
    }
}

Here is the code for the TableViewDelegate:

    public class MainMenuTableViewDelegate : UITableViewDelegate
    {
        private UITableViewController _parentController;

        public MainMenuTableViewDelegate(UITableViewController parentController) : base()
        {
            _parentController = parentController;
        }

        public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
        {
            if (indexPath.Row == 2) {                   
                _parentController.NavigationController.PushViewController (new AccountDialogViewController(), true);
            }
        }
    }

I override the RowSelected method in the tableview delegate class and check if the currently selected row equals index 2, the index of the TableViewCell I want to have show my MonoTouch DialogViewController (called AccountDialogViewController). If true, I push a new instance of my AccountDialogViewController onto the navigation stack via the NavigationController property of the parent TableViewController passed in through the constructor.

Here is my AccountDialogViewController:

public class AccountDialogViewController : DialogViewController
{
    public AccountDialogViewController () : base(new RootElement("Account settings"), true)
    {               
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
        var btnUpdatePassword = UIButton.FromType(UIButtonType.RoundedRect);
        btnUpdatePassword.SetTitle("Save new password", UIControlState.Normal);
        btnUpdatePassword.Frame = new RectangleF(0, 0, 320, 44);
        btnUpdatePassword.TouchUpInside += delegate(object sender, EventArgs e) {
            var alert = new UIAlertView("Test", "msg", null, "Cancel", null);
            alert.Show();
        };
        Root.Add(new Section ("General") {
            new EntryElement("Username", "type...", "Test"),
            new EntryElement("E-mail", "type...", "Test"),
            new RootElement ("Change password") {
                new Section (null, btnUpdatePassword) {
                    new EntryElement("New password", null, null, true),
                    new EntryElement("Confirm", null, null, true)               
                }
            },
            new StringElement ("Logout", delegate {
                var alert = new UIAlertView("Are you sure?", "Tapping Yes will log you out of your account", null, "Cancel", "Yes");
                alert.Show();
            })
        });
    }
}

So, there it is. No more weird blank screens :-)

Upvotes: 1

SharpMobileCode
SharpMobileCode

Reputation: 938

You're trying to push another ViewController (in this case a DialogViewController) onto the Navigation Stack while your current ViewController is still trying to load. Another words, doing that in your ViewDidLoad is bad. You're going to have to wait until your current ViewController has finished loading and has gained focus before you can push another view controller onto the stack.

Part of using Storyboards involves the navigation built into it. Am I safe to assume your "AccountViewController" really doesn't do anything? In that case, I would not segue into that. Instead on your previous view controller, just create your DialogViewController, and then manually push it onto the stack. Hard to say without looking at your storyboard and architecture.

Upvotes: 1

Related Questions