Skip to content

Prism 7 for Xamarin Forms

Compare
Choose a tag to compare
@dansiegel dansiegel released this 12 Jan 04:31
· 1657 commits to master since this release
0c2d11f

General Notes

Before upgrading from Prism 6.3, please be sure to read through the release notes as there are several major and breaking changes. This release is only for Prism Core and Prism for Xamarin Forms ONLY.

Ninject Support

Ninject has been removed as a supported DI Container for Prism Forms due to compatibility issues with Ninject on iOS and Android.

Prism Core

  • .NET Standard Support

  • Added method to clear all errors on ErrorsContainer

  • Removed requirement for parameter in delegate definition of DelegateCommand.ObservesCanExecute Breaking
    Example:
    Old (v6.3): ObservesCanExcute((**vm**) => Property)
    New (v7.0): ObservesCanExecute(() => Property)

  • Add capability to DelegateCommand's ObservesProperty to observe properties of complex types
    Example:
    ObservesProperty(() => Property.NestedProperty.NestedPoperty)

Prism Forms

  • #650: Navigating between Tabs Breaking

  • #683: .NET Standard support

  • #765: Deep linking within a NavigationPage results in an incorrect ContentPage Title on Android

  • #921: Add ability to Remove pages from the navigation stack

  • #946: Support designating useModalNavigation for specific segments in Uri navigation

  • #1007: Re-license to MIT, following the Microsoft led projects

  • #1008: NavigationParameters: Not possible to specify parent type as generic parameter T

  • #1109: Retrieve current URI from Prism Xamarin.Forms NavigationService

  • #1111: Include pdb file in nuget package

  • #1024: XF: NavigationService swallowing Exceptions

  • #1025: Xamarin.Forms deprecated the Device.OS property in favor of the RuntimePlatform property. The following changes were made to accommodate these changes:
    IDeviceService

  • deprecated OnPlatform methods

  • added DeviceRuntimePlatform property - this mimics the XF API and returns a string

  • added RuntimePlatform property which returns an Enum of type RuntimePlatform and wraps the XF string-based values

  • #1027: Support macOS

  • #1044: When Detail of MasterDetailPage is null, Modal Navigation is possible

  • #1045: When calling NavigateAsync with NavigationPage, old page's Destroy on the stack is not called

  • #1046: When calling DeepLink from Navigation Stack, the second page becomes Modal navigation

  • #1054: When deep linking within NavigationPage, page order is reversed

  • #1063: Master of MasterDetailPage will not be destroyed

  • #1074: Optimize Xamarin Forms DryIoc adapter performance

  • #1085: Error occurs if null path is specified in EventToCommandBehavior

  • #1089: DebugLogger does not work in nuget-package

  • #1099: Introduce a Behavior factory into the navigation service

  • #1132: Prism Forms Modularity extension methods

  • #1133: IModuleCatalog AddModule returns wrong type

  • #1139: Modularity Enhancements

  • #1175: Upgraded to Unity 5 Breaking

  • #1076: IActiveAware not working when ContentPage (as child of a TabbedPage) is wrapped into a NavigationPage

  • #1166: Custom NavigationPage is not working properly Prism 7

  • #1187: Change TabbedPage navigation behavior Breaking

  • #1198: Rename IApplicationLifecycle to IApplicationLifecycleAware Breaking

  • #1200: Add GoBackToRoot method

  • #1232: PageNavigationService should check for MultiPage Parent

  • #1225: OnNavigatedTo Contains Extra Parameter

  • #1254: remove support for DependenyService autoresolution Breaking

  • #1286: Adding modules to Prism in newest PR version

  • #1325: Removes support for Ninject due to container incompatibility with iOS and Android

  • added IPageLifecycleAware and PageLifecycleAwareBehavior to enable responding to the Page's Appearing and Disappearing events

Container Extensions

  • deprecated the RegisterTypeForNavigationOnPlatform signature that requires explicit platform parameters
  • added new signature that accepts new IPlatform objects
    Example:
Container.RegisterForNavigationOnPlatform<MainPage, MainPageViewModel>("Main", 
	new Platform<MainPage_Android>(RuntimePlatform.Android),
	new Platform<MainPage_iOS>(RuntimePlatform.iOS));

PrismApplication API Changes - BREAKING

Added new Prism.Ioc namespace to handle DI container abstractions. Interacting with the container is now done via the IContainerProvider and the IContainerRegistry interfaces. The IContainerProvider interface is used to resolve services from the container. The IContainerRegistry is used to register types with the container. Access to the actual DI container can be achieved by using the GetContainer() extension method off of the IContainerRegistry and IContainerProvider interfaces.

Notable changes:

  • Removed ModuleCatalog property
  • Changed signature of ConfigureModuleCatalog() to ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
  • Changed signature of RegisterTypes() to RegisterTypes(IContainerRegistry containterRegistry)
  • Removed CreateContainer() method
  • Removed CreateNavigationService() method
  • Removed CreateLogger() method
  • Removed CreateModuleManager() method
  • Removed CreateModuleCatalog() method
  • Changed order of application initialization process (platform specific types are registered before application types)
  • Container property is now of type IContainerProvider
  • Renamed ConfigureContainer to RegisterRequiredTypes(IContainerRegistry containterRegistry)
  • Renamed RegisterTypeForNavigation to RegisterForNavigation

IModule API Changes - BREAKING

  • Obsolete Initialize() method - move all existing code into RegisterTypes and OnInitialized methods
  • Added RegisterTypes(IContainerRegistry containerRegistry) method - used to register types with the container
  • Added OnInitialized() method - used to perform any action after the module has been created, and types have been registered with the container.

ModuleInfo API Changes - BREAKING

  • Removed defaut ctor
  • Changed order of ctor parameters from ModuleInfo(Name, ModuleType, Mode) to ModuleInfo(ModuleType, Name, Mode)

TabbedPage Navigation Behavior Change - BREAKING

Current Behavior (v6.3.0)

NavigateAsync("TabbedPage/ViewA/ViewB") will select the tab ViewA in the TabbedPage if it exists, then continue navigating. If ViewA does not exist as a tab, then you will continue to navigate as expected.

NavigateAsync("TabbedPage/NavigationPage/ViewA/ViewB") would search the TabbedPage for the first instance of a tab that was a NavigationPage, then navigate within the Navigation page the remaining ViewA and ViewB pages. This provided the ability to deep link into a tab's nested navigation page, but there was no way to opt-out of this behavior.

Also, the INavigationAware methods did not get called to all tabs meaning that you would be responsible for forwarding any parameters to all your tabs.

New Behavior

NavigateAsync("TabbedPage/ViewA/ViewB") will no longer select any tabs, but rather continue processing the navigation as separate pages on the navigation stack.

If you wish to select a tab, you will now use a parameter called "selectedTab" to indicate which tab you would like to select.

NavigateAsync("TabbedPage?selectedTab=MiddleTab/ViewA/ViewB")

This will navigate to the TabbedPage, selected the "MiddleTab" and continue navigating ViewA and ViewB onto the navigation stack.

For tabs that are wrapped inside a NavigationPage, you do not need to change anything. The syntax is the same. This will search each tab to see if it is a navigation page and if the CurrentPage of the NavigationPage matches "MiddleTab", the tab will be selected. This is much more flexible than the existing behavior as before it would take the first instance of the NavigationPage found. Now you can choose which tab exactly.

There is a constant in the KnownNavigationParameters called SelectedTab that you can use instead of a string.

NavigateAsync($"TabbedPage?{KnownNavigationParameters.SelectedTab}=MiddleTab")

Some INavigationAware methods are now fired on all Tabs:

  • OnNavigatingTo will be invoked on the TabbedPage and ALL TABS.
  • OnNavigatedTo will be invoked on the TabbedPage and only the SELECTED TAB.
  • OnNavigatedFrom will be invoked on the TabbedPage and only the SELECTED TAB.

Note: the parameter key selectedTab is now a reserved parameter name. Similar to a reserved keyword in C#. If you use this in your app as a key, you may experience undesired behavior.

Note: At this time there is no native support for deep linking into a Tab that is a navigation page. Please let me know if you need this functionality.

Dynamic Tab Generation

You can now dynamically create tabs when navigating to a TabbedPage by using the KnownNavigationParameters.CreateTab constant or by using the "createTab" parameter name.
_navigationService.NavigateAsync("MyTabbedPage?createTab=ViewA&createTab=ViewB");
This will create a TabbedPage and then create two tabs, ViewA and ViewB.
To create a tab that wraps a page in a NavigationPage, simply denote this as a nested hierarchy using the | character.
_navigationService.NavigateAsync("MyTabbedPage?createTab=NavigationPage|ViewA");

Remove pages from navigation stack

This feature allows you to remove pages form the navigation stack of a NavigationPage while at the same time navigating to a new page. For each page you wish to remove, prefix your navigation path with ../.

Example
Our app requires a user to login in order to edit "User" profile information. This will require the user to be prompted to login and then once successful continue to edit the profile. This leaves us with the following navigation stack:

"NavigationPage/UserList/UserDetails/LoginPage/EditUser"

If we were to hit the back button from the EditUser page, we would be returned to the LoginPage. This is not the desired experience. Instead, we want to go back to the UserDetails which was just updated. To achieve this we provide the following navigation URI from the LoginPage page with a successful login attempt.

NavigationService.NavigateAsync("../EditUser");

This would remove the LoginPage and then immediately navigate to the "EditUser" page which we now have access to.

You can chain the ../ instruction for each page that needs to be removed from the stack.

Given: "NavigationPage/ViewA/ViewB/ViewC/ViewD"
Navigate from ViewD with: NavigationService.NavigateAsync("../../../ViewE");
Results in: "NavigationPage/ViewA/ViewE"

Note: This only works when navigating within a NavigationPage! Modal pages are not supported.

UseModalNavigation in specific deep link segments

You can now control the various segments of a deep ink by setting the useModalNavigation parameter on any specific navigation segment in the URI.

NavigatAsync("NavigationPage/ViewA/ViewB/NavigationPage?useModalNavigation=true/ViewC/ViewD");

You can also use the built-in constant KnownNavigationParameters.UseModalNavigation

NavigatAsync($"NavigationPage/ViewA/ViewB/NavigationPage? {KnownNavigationParameters.UseModalNavigation} =true/ViewC/ViewD");

Note: the parameter key useModalNavigation is now a reserved parameter name. Similar to a reserved keyword in C#. If you use this in your app as a key, you may experience undesired behavior.