将 DialogViewController 推到 ViewController 到 NavigationController 堆栈上会得到 2 页

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

Noob Xamarin/MonoTouch.Dialog 问题:我已经在 Xamarin Studio 的故事板设计器中布置了我的 iOS 应用程序。我有一个 UINavigationController,其根视图包含一个带有静态单元格的 UITableView,本质上是创建一个主菜单。单元格转到各自的 UIViewControllers。

我想使用 MonoTouch.Dialog 布局 about/settings 屏幕。但是,由于我在 Xamarin/MonoTouch.Dialog

中的新手身份,我 运行 遇到了一些将整体故事板方法与部分 MonoTouch.Dialogue 方法相结合的问题

当我在从初始 UITableView (AccountViewController) 继承的 UIViewController 上实例化一个新的 DialogViewController 时,我基本上将两个视图添加到导航堆栈,第一个仅短暂出现,然后显示 DialogViewController。我实例化 DialogViewController 的代码是这样的:

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
    }   
}

我可能将 DialogViewController 推到堆栈的后期,创建中间空白屏幕,但我无法确定在我当前的架构下将 DialogViewController 推入导航堆栈的正确位置。 互联网上的大多数样本接近 100% MonoTouch.Dialog,没有故事板...

谢谢!

您正在尝试将另一个 ViewController(在本例中为对话框ViewController)推送到导航堆栈,而您当前的 ViewController 仍在尝试加载。换句话说,在您的 ViewDidLoad 中这样做是不好的。您将不得不等到当前 ViewController 完成加载并获得焦点,然后才能将另一个视图控制器推入堆栈。

使用 Storyboards 的一部分涉及其中内置的导航。我可以安全地假设您的 "AccountViewController" 真的什么都没做吗?在那种情况下,我不会继续下去。而不是在您以前的视图控制器上,只需创建您的 DialogViewController,然后手动将其压入堆栈。不看你的故事板和架构很难说。

我通过以下方式修复了它:

我为我的 TableViewController(包含带有静态单元格的 TableView)创建了自定义 class:

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
    }
}

这是 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);
            }
        }
    }

我覆盖了 tableview 委托中的 RowSelected 方法 class 并检查当前选定的行是否等于索引 2,即我想要显示我的 MonoTouch DialogViewController(称为 AccountDialogViewController)的 TableViewCell 的索引。如果为真,我将通过构造函数传入的父 TableViewController 的 NavigationController 属性 将我的 AccountDialogViewController 的新实例推送到导航堆栈上。

这是我的 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();
            })
        });
    }
}

所以,就是这样。不再出现奇怪的空白屏幕:-)