1
votes

I want to show a UIPopoverController by clicking on a UIBarButtonItem on the Navigation bar. This UIPopoverController needs a "ContentViewController", that would be a MvxTableViewController with some data-binding. The problem is, if I instantiate some class derived from MvxTableViewController directly - instead of doing ShowViewModel<blah>(), I got an exception on "base.ViewDidLoad" on the overriden method ViewDidLoad.

What am I missing?

Thanks in advance!

EDIT:

If i use, for instance, a MvxViewController with an UITableView:

public class Test : MvxViewController
{
    public override void ViewDidLoad()
    {
        View = new UIView() { BackgroundColor = UIColor.White };
        //TableView = new UITableView(new RectangleF(0, 0, 300, 300));
        base.ViewDidLoad();

        var table = new UITableView(new RectangleF(0, 0, 300, 300));
        // ios7 layout
        if (RespondsToSelector(new Selector("edgesForExtendedLayout")))
            EdgesForExtendedLayout = UIRectEdge.None;

        var source = new MvxStandardTableViewSource(table, "TitleText Nome");
        table.Source = source;

        var set = this.CreateBindingSet<Test, Core.ViewModels.FirstViewModel>();
        set.Bind(source).To(vm => vm.Distritos);
        set.Apply();

        table.ReloadData();
    }
}

And if i have, on FirstViewModel's ViewDidLoad, during the construction of a Navigation Bar:

  var buttonLocalizacao = new UIBarButtonItem("Localização", UIBarButtonItemStyle.Plain, (s, e) => {

            distritoViewController = new Test();
            nc = new UINavigationController(distritoViewController);
            var distritoPopOver = new UIPopoverController(nc);
            distritoPopOver.ContentViewController = nc;
            distritoPopOver.PopoverContentSize = new SizeF(300, 300);

            distritoPopOver.PresentFromBarButtonItem((UIBarButtonItem)s, UIPopoverArrowDirection.Up, true);

        });

Everytime i hit the UIBarButtonItem "Localização" i get an exception on Test's "base.ViewDidLoad". Does this make sense?

EDIT 2:

This is the exception i receive:

"Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object at Cirrious.MvvmCross.ViewModels.MvxViewModelLoader.LoadViewModel (Cirrious.MvvmCross.ViewModels.MvxViewModelRequest request, IMvxBundle savedState) [0x00000] in :0 at Cirrious.MvvmCross.Touch.Views.MvxViewControllerExtensionMethods.LoadViewModel (IMvxTouchView touchView) [0x00000] in :0 at Cirrious.MvvmCross.Touch.Views.MvxViewControllerExtensionMethods+<>c__DisplayClass1.b__0 () [0x00000] in :0 at Cirrious.MvvmCross.Views.MvxViewExtensionMethods.OnViewCreate (IMvxView view, System.Func`1 viewModelLoader) [0x00000] in :0 at Cirrious.MvvmCross.Touch.Views.MvxViewControllerExtensionMethods.OnViewCreate (IMvxTouchView touchView) [0x00000] in :0 at Cirrious.MvvmCross.Touch.Views.MvxViewControllerAdapter.HandleViewDidLoadCalled (System.Object sender, System.EventArgs e) [0x00000] in :0 "

1
I normally instantiate this contentViewcontroller before hand, so that I dont keep instantiating the same contentViewController everytime the bar button item is pressed. I then just attach the contentViewController onto the popViewController when it needs to be presented. Mine is also a small mini table where the user selects a choice between data presented in cells on this popoverController. - Pavan
I can't get it to work somehow...do you have some example i can see? Thanks! - Nuno Miguel Fonseca
Why dont you post your project and show us what your code looks like, and I'll be happy to help? Thanks! - Pavan
I'd guess there's more trace ahead of that exception saying that the ViewModel for Test couldn't be loaded. If you need to you can always set the ViewModel/DataContext yourself before calling base.ViewDidLoad() - but without a DataContext then no data can be shown. - Stuart
"Test" has some data-binding, but the data is located is located in a FirstViewModel property, meaning there isn't really a TestViewModel, because the data isnt there, only the binding, as you can see in Test's ViewDidLoad. Does this make sense? If you could show us some example of this, creating MvxViewControllers directly, to assist in the use of a UIPopoverController, it would be fantastic, i can't seem to get hold of an example of this anywhere...thanks! - Nuno Miguel Fonseca

1 Answers

1
votes

Finally got it:

Instead of:

var buttonLocalizacao = new UIBarButtonItem("Localização", UIBarButtonItemStyle.Plain, (s, e) => {

        distritoViewController = new Test();
        nc = new UINavigationController(distritoViewController);
        var distritoPopOver = new UIPopoverController(nc);
        distritoPopOver.ContentViewController = nc;
        distritoPopOver.PopoverContentSize = new SizeF(300, 300);

        distritoPopOver.PresentFromBarButtonItem((UIBarButtonItem)s, UIPopoverArrowDirection.Up, true);

    });

I had to create a distinct ViewModel to hold my MvxTableViewController (each MvxTableViewController, or MvxViewController, demands a corresponding ViewModel?), meaning, i could not bind "Test", that is a MvxTableViewController, to another, different, ViewModel (FirstViewModel for instance). "Test" must have a ViewModel of it's own.

So, eventually the corresponding ViewModel must be instantiated previously, and only after that can we instantiate the MvxTableViewController using "CreateViewControllerFor". Replacing the above "Test" for "DistritoViewModel", the rest is straightforward:

 var buttonLocalizacao = new UIBarButtonItem("Localização", UIBarButtonItemStyle.Plain, (s, e) => {

            if (distritoPopOver == null)
            {
                var viewModel = new DistritoViewModel();
                var secondv = this.CreateViewControllerFor(viewModel) as MvxTableViewController;

                nc = new UINavigationController(secondv);
                distritoPopOver = new UIPopoverController(nc);
                distritoPopOver.PopoverContentSize = new SizeF(300, 300);
            }

            distritoPopOver.PresentFromBarButtonItem((UIBarButtonItem)s, UIPopoverArrowDirection.Up, true);

        });

Keep in mind: the variable distritoPopover, that holds the UIPopoverController, must be a class variable, or instantiated outside the Action in UIBarButtonItem, otherwise it will be garbage collected and cause an immediate crash after display!

Thanks everyone for the tips :)