Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add attribute to show page on iOS #3339

Merged
merged 7 commits into from May 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MS-PL license.
// See the LICENSE file in the project root for more information.

using MvvmCross.Presenters.Attributes;

namespace MvvmCross.Platforms.Ios.Presenters.Attributes
{
public class MvxPagePresentationAttribute : MvxBasePresentationAttribute
{
public static bool DefaultWrapInNavigationController = false;
public bool WrapInNavigationController { get; set; } = DefaultWrapInNavigationController;
}
}
55 changes: 55 additions & 0 deletions MvvmCross/Platforms/Ios/Presenters/MvxIosViewPresenter.cs
Expand Up @@ -30,6 +30,8 @@ public class MvxIosViewPresenter : MvxAttributeViewPresenter, IMvxIosViewPresent

public IMvxTabBarViewController TabBarViewController { get; protected set; }

public IMvxPageViewController PageViewController { get; protected set; }

public IMvxSplitViewController SplitViewController { get; protected set; }

public override MvxBasePresentationAttribute CreatePresentationAttribute(Type viewModelType, Type viewType)
Expand Down Expand Up @@ -109,6 +111,14 @@ public override void RegisterAttributeTypes()
},
CloseTabViewController);

AttributeTypesToActionsDictionary.Register<MvxPagePresentationAttribute>(
(viewType, attribute, request) =>
{
var viewController = (UIViewController)this.CreateViewControllerFor(request);
return ShowPageViewController(viewController, attribute, request);
},
ClosePageViewController);

AttributeTypesToActionsDictionary.Register<MvxModalPresentationAttribute>(
(viewType, attribute, request) =>
{
Expand Down Expand Up @@ -166,6 +176,19 @@ public override void RegisterAttributeTypes()
return true;
}

if (viewController is IMvxPageViewController pageViewController)
{
PageViewController = pageViewController;

// set root
SetupWindowRootNavigation(viewController, attribute);

if (!await CloseModalViewControllers()) return false;
if (!await CloseSplitViewController()) return false;

return true;
}

// check if viewController is a SplitViewController
if (viewController is IMvxSplitViewController splitController)
{
Expand Down Expand Up @@ -300,6 +323,30 @@ protected void SetupWindowRootNavigation(UIViewController viewController, MvxRoo
return Task.FromResult(true);
}

protected virtual Task<bool> ShowPageViewController(
UIViewController viewController,
MvxPagePresentationAttribute attribute,
MvxViewModelRequest request)
{
if (PageViewController == null)
throw new MvxException("Trying to show a page without a PageViewController, this is not possible!");

/*if (viewController is IMvxTabBarItemViewController tabBarItem)
{
attribute.TabName = tabBarItem.TabName;
attribute.TabIconName = tabBarItem.TabIconName;
attribute.TabSelectedIconName = tabBarItem.TabSelectedIconName;
}*/

if (attribute.WrapInNavigationController)
viewController = CreateNavigationController(viewController);

PageViewController.AddPage(
viewController,
attribute);
return Task.FromResult(true);
}

protected virtual Task<bool> ShowModalViewController(
UIViewController viewController,
MvxModalPresentationAttribute attribute,
Expand Down Expand Up @@ -393,6 +440,14 @@ protected virtual Task<bool> CloseTabViewController(IMvxViewModel viewModel, Mvx
return Task.FromResult(false);
}

protected virtual Task<bool> ClosePageViewController(IMvxViewModel viewModel, MvxPagePresentationAttribute attribute)
{
if (PageViewController != null && PageViewController.RemovePage(viewModel))
return Task.FromResult(true);

return Task.FromResult(false);
}

protected virtual Task<bool> CloseMasterSplitViewController(IMvxViewModel viewModel, MvxSplitViewPresentationAttribute attribute)
{
if (SplitViewController != null && SplitViewController.CloseChildViewModel(viewModel, attribute))
Expand Down
17 changes: 17 additions & 0 deletions MvvmCross/Platforms/Ios/Views/IMvxPageViewController.cs
@@ -0,0 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MS-PL license.
// See the LICENSE file in the project root for more information.

using MvvmCross.Platforms.Ios.Presenters.Attributes;
using MvvmCross.ViewModels;
using UIKit;

namespace MvvmCross.Platforms.Ios.Views
{
public interface IMvxPageViewController
{
void AddPage(UIViewController viewController, MvxPagePresentationAttribute attribute);

bool RemovePage (IMvxViewModel viewModel);
}
}
168 changes: 168 additions & 0 deletions MvvmCross/Platforms/Ios/Views/MvxBasePageViewController.cs
@@ -0,0 +1,168 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MS-PL license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using Foundation;
using MvvmCross.Logging;
using MvvmCross.Binding.BindingContext;
using MvvmCross.Platforms.Ios.Views.Base;
using MvvmCross.ViewModels;
using UIKit;

namespace MvvmCross.Platforms.Ios.Views
{
public class MvxBasePageViewController : MvxEventSourcePageViewController, IMvxIosView
{
public MvxBasePageViewController(UIPageViewControllerTransitionStyle style = UIPageViewControllerTransitionStyle.Scroll, UIPageViewControllerNavigationOrientation navigationOrientation = UIPageViewControllerNavigationOrientation.Horizontal, UIPageViewControllerSpineLocation spineLocation = UIPageViewControllerSpineLocation.None) : base(style, navigationOrientation, spineLocation)
{
this.AdaptForBinding();
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation, UIPageViewControllerSpineLocation spineLocation, float interPageSpacing) : base(style, navigationOrientation, spineLocation, interPageSpacing)
{
this.AdaptForBinding();
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation) : base(style, navigationOrientation)
{
this.AdaptForBinding();
}

public MvxBasePageViewController(NSCoder coder) : base(coder)
{
this.AdaptForBinding();
}

protected MvxBasePageViewController(NSObjectFlag t) : base(t)
{
this.AdaptForBinding();
}

protected internal MvxBasePageViewController(IntPtr handle) : base(handle)
{
this.AdaptForBinding();
}

public MvxBasePageViewController(string nibName, NSBundle bundle) : base(nibName, bundle)
{
this.AdaptForBinding();
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation, NSDictionary options) : base(style, navigationOrientation, options)
{
this.AdaptForBinding();
}
public object DataContext
{
get
{
// special code needed in PageViewController because View is initialized during construction
return BindingContext?.DataContext;
}
set
{
BindingContext.DataContext = value;
}
}

public IMvxViewModel ViewModel
{
get { return DataContext as IMvxViewModel; }
set { DataContext = value; }
}

public MvxViewModelRequest Request { get; set; }

public IMvxBindingContext BindingContext { get; set; }

public override void ViewDidLoad()
{
base.ViewDidLoad();
ViewModel?.ViewCreated();
}

public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
ViewModel?.ViewAppearing();
}

public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
ViewModel?.ViewAppeared();
}

public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
ViewModel?.ViewDisappearing();
}

public override void ViewDidDisappear(bool animated)
{
base.ViewDidDisappear(animated);
ViewModel?.ViewDisappeared();
}

public override void DidMoveToParentViewController(UIViewController parent)
{
base.DidMoveToParentViewController(parent);
if (parent == null)
ViewModel?.ViewDestroy();
}

public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender)
{
base.PrepareForSegue(segue, sender);
this.ViewModelRequestForSegue(segue, sender);
}
}

public class MvxBasePageViewController<TViewModel> : MvxPageViewController, IMvxIosView<TViewModel> where TViewModel : class, IMvxViewModel
{
public MvxBasePageViewController()
{
}

public MvxBasePageViewController(NSCoder coder) : base(coder)
{
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation) : base(style, navigationOrientation)
{
}

public MvxBasePageViewController(string nibName, NSBundle bundle) : base(nibName, bundle)
{
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation, UIPageViewControllerSpineLocation spineLocation) : base(style, navigationOrientation, spineLocation)
{
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation, NSDictionary options) : base(style, navigationOrientation, options)
{
}

public MvxBasePageViewController(UIPageViewControllerTransitionStyle style, UIPageViewControllerNavigationOrientation navigationOrientation, UIPageViewControllerSpineLocation spineLocation, float interPageSpacing) : base(style, navigationOrientation, spineLocation, interPageSpacing)
{
}

protected MvxBasePageViewController(NSObjectFlag t) : base(t)
{
}

protected internal MvxBasePageViewController(IntPtr handle) : base(handle)
{
}

public new TViewModel ViewModel
{
get { return (TViewModel)base.ViewModel; }
set { base.ViewModel = value; }
}
}
}