I am trying to implement a Custom UIViewController class that will act as my navigation controller rather than using the default navigation controller. Below is my container class I have:
enter code here
public partial class ContainerView : MvxViewController
{
static bool UserInterfaceIdiomIsPhone {
get { return UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone; }
}
private UIViewController _currentView;
protected ContainerViewModel ContainerModel
{ get { return base.ViewModel as ContainerViewModel; } }
public ContainerView ()
: base (UserInterfaceIdiomIsPhone ? "ContainerView_iPhone" : "ContainerView_iPad", null)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
var loginView = this.CreateViewControllerFor(ContainerModel.Login) as UIViewController;
ShowViewController(loginView);
// Perform any additional setup after loading the view, typically from a nib.
}
public ContainerView(UIViewController controller)
: base(UserInterfaceIdiomIsPhone ? "ContainerView_iPhone" : "ContainerView_iPad", null)
{
ShowViewController(controller);
}
public void ShowViewController(UIViewController viewController)
{
if (_currentView !=null)
{
RemoveCurrentViewController();
}
AddChildViewController(viewController);
viewController.View.Frame = GetViewFrame();
containerView.AddSubview(viewController.View);
_currentView = viewController;
viewController.DidMoveToParentViewController(this);
}
public void RemoveCurrentViewController()
{
_currentView.WillMoveToParentViewController(null);
_currentView.View.RemoveFromSuperview();
_currentView.RemoveFromParentViewController();
}
public RectangleF GetViewFrame()
{
return containerView.Bounds;
}
}
My first load is fine as the login view is loaded into the containerView which is an outlet from the nib. The problem is on subsequent request my outlet is null. I may be doing this wrong but I am attempting to set the viewcontroller in the Presenter Show method as per below:
public class MyPresenter: MvxTouchViewPresenter
{
private static ContainerView _cv;
public BlackhawkPresenter(MvxApplicationDelegate appDelegate, UIWindow window)
: base(appDelegate, window)
{
_cv = new ContainerView();
window.RootViewController = _cv;
}
protected override UINavigationController CreateNavigationController(UIViewController viewController)
{
return new BlackhawkNavigationController(viewController);
}
public override void Show(Cirrious.MvvmCross.ViewModels.MvxViewModelRequest request)
{
var viewController = (UIViewController)Mvx.Resolve<IMvxTouchViewCreator>().CreateView(request);
if(request.ViewModelType == typeof(ContainerViewModel))
base.Show(request);
else
_cv.ShowViewController(viewController);
}
}
for the else statement in the show as the "ViewDidLoad" never fires my outlet is null. I am not sure of any othe rway to intercept the call for ShowViewModel to display it in container View in my container class.
Your code is a bit confusing (a bit incomplete) but my guess is that you have more than one ContainerView
created
one created during:
_cv = new ContainerView();
a second one created during
base.Show(request);
If this is the case, then only one of these is actually being shown as the RootViewController and _cv
might be left as a dangling reference to a not-used view controller.
To find a solution, try taking a look at MvxTouchViewPresenter
- you can either replace this class in its entirety (if you don't want any of it's functionality) or you can find one of the virtual methods to intercept/override to capture the variables you need - source code is https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Touch/Views/Presenters/MvxTouchViewPresenter.cs
e.g. maybe something like this would work:
protected override void ShowFirstView(UIViewController viewController)
{
_cv = (ContainerView)viewController;
base.ShowFirstView(viewController);
}
... but I'm sure plenty of other solutions are available.