{"action":"created","issue":{"url":"https://api.github.com/repos/xamarin/Xamarin.Forms/issues/2415","repository_url":"https://api.github.com/repos/xamarin/Xamarin.Forms","labels_url":"https://api.github.com/repos/xamarin/Xamarin.Forms/issues/2415/labels{/name}","comments_url":"https://api.github.com/repos/xamarin/Xamarin.Forms/issues/2415/comments","events_url":"https://api.github.com/repos/xamarin/Xamarin.Forms/issues/2415/events","html_url":"https://github.com/xamarin/Xamarin.Forms/issues/2415","id":313100247,"node_id":"MDU6SXNzdWUzMTMxMDAyNDc=","number":2415,"title":"Xamarin.Forms.Shell Spec","user":{"login":"jassmith","id":30443,"node_id":"MDQ6VXNlcjMwNDQz","avatar_url":"https://avatars2.githubusercontent.com/u/30443?v=4","gravatar_id":"","url":"https://api.github.com/users/jassmith","html_url":"https://github.com/jassmith","followers_url":"https://api.github.com/users/jassmith/followers","following_url":"https://api.github.com/users/jassmith/following{/other_user}","gists_url":"https://api.github.com/users/jassmith/gists{/gist_id}","starred_url":"https://api.github.com/users/jassmith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jassmith/subscriptions","organizations_url":"https://api.github.com/users/jassmith/orgs","repos_url":"https://api.github.com/users/jassmith/repos","events_url":"https://api.github.com/users/jassmith/events{/privacy}","received_events_url":"https://api.github.com/users/jassmith/received_events","type":"User","site_admin":false},"labels":[{"id":343860853,"node_id":"MDU6TGFiZWwzNDM4NjA4NTM=","url":"https://api.github.com/repos/xamarin/Xamarin.Forms/labels/t/enhancement","name":"t/enhancement","color":"84b6eb","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":73,"created_at":"2018-04-10T21:44:11Z","updated_at":"2018-06-13T06:39:56Z","closed_at":null,"author_association":"MEMBER","body":"# Xamarin.Forms Shell Spec\r\nMake it simple and straightforward for new developers to get a complete app experience that is properly structured, uses the right elements, with very little effort and a clear path to being good by default.\r\n\r\nShell is an opinionated API at points, it does not always default every value to some .Default which may change based on the running platform. Instead it may set a value which is then respected across all platforms regardless what the platform default is.\r\n\r\nNote: Drawing Spec moved to: #2452\r\n\r\n# Visual Treatment\r\nNeeds screenshots...\r\n\r\n# Shell Hierarchy\r\nUnderstanding the Shell hierarchy at first can seem overwhelming at first. It represents a complex hierarchy and provides powerful mechanisms for minimizing the amount of boilerplate xaml required to create rich hierarchies.\r\n\r\nThus when first learning shell it is easiest to learn without the shortcuts first, and then introduce the shortcuts to see how to easily minimize the amount of XAML being written.\r\n\r\nNote that all samples that follow do not use templated ShellContent's, which are discussed elsewhere in the spec. Failure to properly use ShellContents with a ContentTemplate will result in all pages being loaded at startup, which will negatively impact startup performance. These samples are for learning purposes only.\r\n\r\nFortunately using ShellContents with ContentTemplates is usually more concise than not using them.\r\n\r\n## No shortcuts\r\nMany of these samples will look needlessly complex, and in reality they are. In the next section these will get simplified.\r\n\r\n### A simple one page app\r\n```xaml\r\n<Shell xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n       xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n       xmlns:local=\"clr-namespace:MyStore\"\r\n       FlyoutBehavior=\"Disabled\"\r\n       x:Class=\"MyStore.Shell\">\r\n\r\n  <ShellItem>\r\n    <ShellSection>\r\n      <ShellContent>\r\n        <local:HomePage />\r\n      </ShellContent>\r\n    </ShellSection>\r\n  </ShellItem>\r\n</Shell>\r\n```\r\n\r\n![step1](https://user-images.githubusercontent.com/30443/40998552-09aa2c7e-68bd-11e8-9ba3-e92d8ec76344.PNG)\r\n\r\nThe top bar can be hidden entirely by setting `Shell.NavBarVisible=\"false\"` on the MainPage. The Flyout would also look rather sparse in this mode and is thus disabled in this sample.\r\n\r\n### Two page app with bottom tabs\r\n```xaml\r\n<Shell xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n       xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n       xmlns:local=\"clr-namespace:MyStore\"\r\n       FlyoutBehavior=\"Disabled\"\r\n       x:Class=\"MyStore.Shell\">\r\n\r\n  <ShellItem>\r\n\r\n    <ShellSection Title=\"Home\" Icon=\"home.png\">\r\n      <ShellContent>\r\n        <local:HomePage />\r\n      </ShellContent>\r\n    </ShellSection>\r\n\r\n    <ShellSection Title=\"Notifications\" Icon=\"bell.png\">\r\n      <ShellContent>\r\n        <local:NotificationsPage />\r\n      </ShellContent>\r\n    </ShellSection>\r\n\r\n  </ShellItem>\r\n</Shell>\r\n```\r\n\r\n![step2](https://user-images.githubusercontent.com/30443/40998559-0e9fb3b6-68bd-11e8-819e-9dcdee3d396e.PNG)\r\n\r\nBy adding a section `ShellSection` to the `ShellItem` another bottom tab appears. Settings the approriate title and icon allows control over the Tab item title and icon.\r\n\r\n### Two page app with top and bottom tabs\r\n```xaml\r\n<Shell xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n       xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n       xmlns:local=\"clr-namespace:MyStore\"\r\n       FlyoutBehavior=\"Disabled\"\r\n       x:Class=\"MyStore.Shell\">\r\n\r\n  <ShellItem>\r\n\r\n    <ShellSection Title=\"Home\" Icon=\"home.png\">\r\n      <ShellContent>\r\n        <local:HomePage />\r\n      </ShellContent>\r\n    </ShellSection>\r\n\r\n    <ShellSection Title=\"Notifications\" Icon=\"bell.png\">\r\n\r\n      <ShellContent Title=\"Recent\">\r\n        <local:NotificationsPage />\r\n      </ShellContent>\r\n\r\n      <ShellContent Title=\"Alert Settings\">\r\n        <local:SettingsPage />\r\n      </ShellContent>\r\n\r\n    </ShellSection>\r\n\r\n  </ShellItem>\r\n</Shell>\r\n```\r\n\r\n![step3](https://user-images.githubusercontent.com/30443/40998570-140b5382-68bd-11e8-968d-f7c6b87d50bf.PNG)\r\n\r\nBy adding a second `ShellContent` to the `ShellSection` a top tab bar is added and the pages can be flipped between when the bottom tab is selected.\r\n\r\n### Two page app using flyout navigation\r\n```xaml\r\n<Shell xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n       xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n       xmlns:local=\"clr-namespace:MyStore\"\r\n       x:Class=\"MyStore.Shell\">\r\n\r\n  <Shell.FlyoutHeader>\r\n    <local:FlyoutHeader />\r\n  </Shell.FlyoutHeader>\r\n\r\n  <ShellItem Title=\"Home\" Icon=\"home.png\">\r\n    <ShellSection>\r\n      <ShellContent>\r\n        <local:HomePage />\r\n      </ShellContent>\r\n    </ShellSection>\r\n  </ShellItem>\r\n\r\n  <ShellItem Title=\"Notifications\" Icon=\"bell.png\">\r\n    <ShellSection>\r\n      <ShellContent>\r\n        <local:NotificationsPage />\r\n      </ShellContent>\r\n    </ShellSection>\r\n  </ShellItem>\r\n</Shell>\r\n```\r\n\r\n![step4](https://user-images.githubusercontent.com/30443/40998574-17ca458c-68bd-11e8-8d45-639933e0dfd7.PNG)\r\n\r\nThe flyout is re-enabled in this sample. Here the user can switch between the two pages using the flyout as an intermediary. A header has also been added to look nice.\r\n\r\n## Using shorthand syntax\r\n\r\nNow that all levels of the hierarchy have been shown and breifly explained, it is possible to leave most of the unneeded wrapping out when defining a hierarchy. `Shell` only ever contains `ShellItem`s which only ever contain `ShellSection`s which in turn only ever contain `ShellContent`s. However there are implicit conversion operators in place to allow for automatic up-wrapping.\r\n\r\n### A simple one page app\r\n```xaml\r\n<Shell xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n       xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n       xmlns:local=\"clr-namespace:MyStore\"\r\n       FlyoutBehavior=\"Disabled\"\r\n       x:Class=\"MyStore.Shell\">\r\n\r\n  <local:HomePage />\r\n</Shell>\r\n```\r\n\r\nWith implicit wrapping the Page is automatically wrapped all the way up to a `ShellItem`. It is not needed to write out all the intermiedate layers. The `Title` and `Icon` from the `Page` will be bound up to any implicitly generated parents.\r\n\r\n### Two page app with bottom tabs\r\n```xaml\r\n<Shell xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n       xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n       xmlns:local=\"clr-namespace:MyStore\"\r\n       FlyoutBehavior=\"Disabled\"\r\n       x:Class=\"MyStore.Shell\">\r\n\r\n  <ShellItem>\r\n    <local:HomePage Icon=\"home.png\" />\r\n    <local:NotificationsPage Icon=\"bell.png\" />\r\n  </ShellItem>\r\n</Shell>\r\n```\r\n\r\nThe pages are now implicitly wrapped up into ShellContent and their own ShellSections. This results in two different tabs being created, just like before.\r\n\r\n### Two page app with top and bottom tabs\r\n```xaml\r\n<Shell xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n       xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n       xmlns:local=\"clr-namespace:MyStore\"\r\n       FlyoutBehavior=\"Disabled\"\r\n       x:Class=\"MyStore.Shell\">\r\n\r\n  <ShellItem>\r\n    <local:HomePage Icon=\"home.png\" />\r\n\r\n    <ShellSection Title=\"Notifications\" Icon=\"bell.png\">\r\n        <local:NotificationsPage />\r\n        <local:SettingsPage />\r\n    </ShellSection>\r\n  </ShellItem>\r\n</Shell>\r\n```\r\n\r\n### Two page app using flyout navigation\r\n```xaml\r\n<Shell xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n       xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n       xmlns:local=\"clr-namespace:MyStore\"\r\n       x:Class=\"MyStore.Shell\">\r\n\r\n  <Shell.FlyoutHeader>\r\n    <local:FlyoutHeader />\r\n  </Shell.FlyoutHeader>\r\n\r\n  <local:HomePage Icon=\"home.png\" />\r\n  <local:NotificationsPage Icon=\"bell.png\" />\r\n</Shell>\r\n```\r\n\r\nHere the implicit wrapping goes all the way up to shell item so there is no need for us to do any wrapping ourselves.\r\n\r\n# Navigation Model\r\n## Push Navigation\r\n\r\nAll navigation is based on the View’s .Navigation property. Pushes go into the current ShellSection that is displayed. This means in a push event the top tabs will go away and the bottom tabs will remain.\r\n\r\n## URI Navigation\r\nThe Shell can be navigated using the standard Navigation property as discussed above, however shell introduces a far more convenient navigation mechanism.\r\n\r\nNavigation URI's are formatted as follows:\r\n\r\n```\r\n[Shell.RouteScheme]://[Shell.RouteHost]/[Shell]/[ShellItem]/[ShellSection]/[ShellContent]/[NavStack1]/[NavStack2]...\r\n```\r\n\r\nAll items in the shell hierarchy have a route associated with them. If the route is not set by the developer, the route is generated at runtime. Runtime generated routes are not gauranteed to be stable across different runs of the app and thus are not useful for deep linking.\r\n\r\n# Handling the Back Button\r\n\r\nSince Shell will be in the enviable position of not having to use native controls, all forms of back button overriding can and should be supported.\r\n\r\nProper handling of the back button needs to support the following features:\r\n\r\n\r\n- Intercepting interactions and stopping them\r\n- Replacing the back button with something else\r\n- Hiding the back button entirely when desired\r\n- Work for software and hardware buttons\r\n\r\nThe API needs to be granular to the page level for ease of use, but also be able to be handled further up the stack in a more general level.\r\n\r\n# Code Samples and API\r\n## Samples\r\n```xaml\r\n<Shell>\r\n  <Shell.FlyoutHeaderTemplate>\r\n    <DataTemplate>\r\n      <Grid>\r\n        <Label Text=\"{x:Bind HeaderText}\" />\r\n      </Grid>\r\n    </DataTemplate>\r\n  </Shell.FlyoutHeaderTemplate>\r\n  \r\n  // Flyout Item 1\r\n  <ShellItem Title=\"My music\" ItemsSource=\"{x:Bind MyMusicModels}\" TabLocation=\"Bottom\">\r\n    <ShellItem.ItemTemplate>\r\n      <local:MyMusicItemTemplateSelection />\r\n    </ShellItem.ItemTemplate>\r\n  </ShellItem>\r\n  \r\n  // Flyout Item 2\r\n  <ShellItem Title=\"Home\" Icon=\"home.png\" GroupBehavior=\"ShowTabs\">\r\n    <ShellContent Title=\"My Friends\">\r\n      <local:FriendsPage />\r\n    </ShellContent>\r\n    <local:FeedPage />\r\n    <local:ProfilePage />\r\n  </ShellItem>\r\n  \r\n  // Flyout Item 3\r\n  <local:SettingsPage />\r\n  \r\n  // Flyout Item 4\r\n  <MenuItem Text=\"Log Out\" Command=\"{x:Bind LogOutCommand}\" />\r\n</Shell>\r\n```\r\n### Single Page App using Shell\r\n```xaml\r\n<Shell FlyoutVisibility=\"Disabled\">\r\n  <local:MyPage />\r\n</Shell>\r\n```\r\n### Single Group of Tabs app (no Flyout)\r\n```xaml\r\n<Shell FlyoutVisibility=\"Disabled\">\r\n  <ShellItem>\r\n    <local:MyPage />\r\n    <local:MySecondPage />\r\n    <local:MyThirdPage />\r\n  </ShellItem>\r\n</Shell>\r\n```\r\n### Multiple pages in flyout with no tabs\r\n```xaml\r\n<Shell FlyoutVisibility=\"Disabled\">\r\n  <local:MyPage />\r\n  <local:MySecondPage />\r\n  <local:MyThirdPage />\r\n</Shell>\r\n```\r\n### Single Page Searchable App\r\n```xaml\r\n<Shell FlyoutVisibility=\"Disabled\">\r\n  <local:MyPage />\r\n</Shell>\r\n```\r\n```csharp\r\npublic class MyPage : ContentPage\r\n{\r\n  public class MyPageSearchHandler : SearchHandler\r\n  {\r\n    public MyPageHandler ()\r\n    {\r\n      SearchBoxVisibility = SearchBoxVisibility.Collapsed;\r\n      IsSearchEnabled = true;\r\n      Placeholder = \"Search me!\";\r\n    }\r\n\r\n    protected override async void OnSearchConfirmed (string query)\r\n    {\r\n      IsSearching = true;\r\n    \r\n      await PerformSearch (query);\r\n      UpdateResults ();\r\n      \r\n      IsSearching = false;\r\n    }\r\n    \r\n    protected override void OnSearchChanged (string oldValue, string newValue)\r\n    {\r\n      // Do nothing, we will wait for confirmation\r\n    }\r\n  }\r\n\r\n  public MyPage ()\r\n  {\r\n    Shell.SetSearchHandler (this, new MyPageSearchHandler ());\r\n  }\r\n}\r\n```\r\n## API Definition\r\n\r\n### Shell\r\nThis is the base class for Shell's. It defines a somewhat strict navigational model however all shells must adhere to it in general. It does not include any theming or design language specific features.\r\n\r\n```csharp\r\n[ContentProperty(\"Items\")]\r\npublic class Shell : Page, IShellController\r\n{\r\n  // Attached Properties\r\n  public static readonly BindableProperty BackButtonBehaviorProperty;\r\n  public static readonly BindableProperty FlyoutBehaviorProperty;\r\n  public static readonly BindableProperty NavBarVisibleProperty;\r\n  public static readonly BindableProperty SearchHandlerProperty;\r\n  public static readonly BindableProperty SetPaddingInsetsProperty;\r\n  public static readonly BindableProperty TabBarVisibleProperty;\r\n  public static readonly BindableProperty TitleViewProperty;\r\n  public static readonly BindableProperty ShellBackgroundColorProperty;\r\n  public static readonly BindableProperty ShellDisabledColorProperty;\r\n  public static readonly BindableProperty ShellForegroundColorProperty;\r\n  public static readonly BindableProperty ShellTabBarBackgroundColorProperty;\r\n  public static readonly BindableProperty ShellTabBarDisabledColorProperty;\r\n  public static readonly BindableProperty ShellTabBarForegroundColorProperty;\r\n  public static readonly BindableProperty ShellTabBarTitleColorProperty;\r\n  public static readonly BindableProperty ShellTabBarUnselectedColorProperty;\r\n  public static readonly BindableProperty ShellTitleColorProperty;\r\n  public static readonly BindableProperty ShellUnselectedColorProperty;\r\n\r\n  public static BackButtonBehavior GetBackButtonBehavior(BindableObject obj);\r\n  public static FlyoutBehavior GetFlyoutBehavior(BindableObject obj);\r\n  public static bool GetNavBarVisible(BindableObject obj);\r\n  public static SearchHandler GetSearchHandler(BindableObject obj);\r\n  public static bool GetSetPaddingInsets(BindableObject obj);\r\n  public static bool GetTabBarVisible(BindableObject obj);\r\n  public static View GetTitleView(BindableObject obj);\r\n  public static void SetBackButtonBehavior(BindableObject obj, BackButtonBehavior behavior);\r\n  public static void SetFlyoutBehavior(BindableObject obj, FlyoutBehavior value);\r\n  public static void SetNavBarVisible(BindableObject obj, bool value);\r\n  public static void SetSearchHandler(BindableObject obj, SearchHandler handler);\r\n  public static void SetSetPaddingInsets(BindableObject obj, bool value);\r\n  public static void SetTabBarVisible(BindableObject obj, bool value);\r\n  public static void SetTitleView(BindableObject obj, View value);\r\n  public static Color GetShellBackgroundColor(BindableObject obj);\r\n  public static Color GetShellDisabledColor(BindableObject obj);\r\n  public static Color GetShellForegroundColor(BindableObject obj);\r\n  public static Color GetShellTabBarBackgroundColor(BindableObject obj);\r\n  public static Color GetShellTabBarDisabledColor(BindableObject obj);\r\n  public static Color GetShellTabBarForegroundColor(BindableObject obj);\r\n  public static Color GetShellTabBarTitleColor(BindableObject obj);\r\n  public static Color GetShellTabBarUnselectedColor(BindableObject obj);\r\n  public static Color GetShellTitleColor(BindableObject obj);\r\n  public static Color GetShellUnselectedColor(BindableObject obj);\r\n  public static void SetShellBackgroundColor(BindableObject obj, Color value);\r\n  public static void SetShellDisabledColor(BindableObject obj, Color value);\r\n  public static void SetShellForegroundColor(BindableObject obj, Color value);\r\n  public static void SetShellTabBarBackgroundColor(BindableObject obj, Color value);\r\n  public static void SetShellTabBarDisabledColor(BindableObject obj, Color value);\r\n  public static void SetShellTabBarForegroundColor(BindableObject obj, Color value);\r\n  public static void SetShellTabBarTitleColor(BindableObject obj, Color value);\r\n  public static void SetShellTabBarUnselectedColor(BindableObject obj, Color value);\r\n  public static void SetShellTitleColor(BindableObject obj, Color value);\r\n  public static void SetShellUnselectedColor(BindableObject obj, Color value);\r\n\r\n  // Bindable Properties\r\n  public static readonly BindableProperty CurrentItemProperty;\r\n  public static readonly BindableProperty CurrentStateProperty;\r\n  public static readonly BindableProperty FlyoutBackgroundColorProperty;\r\n  public static readonly BindableProperty FlyoutHeaderBehaviorProperty;\r\n  public static readonly BindableProperty FlyoutHeaderProperty;\r\n  public static readonly BindableProperty FlyoutHeaderTemplateProperty;\r\n  public static readonly BindableProperty FlyoutIsPresentedProperty;\r\n  public static readonly BindableProperty GroupHeaderTemplateProperty;\r\n  public static readonly BindableProperty ItemsProperty;\r\n  public static readonly BindableProperty ItemTemplateProperty;\r\n  public static readonly BindableProperty MenuItemsProperty;\r\n  public static readonly BindableProperty MenuItemTemplateProperty;\r\n\r\n  public Shell();\r\n\r\n  public event EventHandler<ShellNavigatedEventArgs> Navigated;\r\n\r\n  public event EventHandler<ShellNavigatingEventArgs> Navigating;\r\n\r\n  public ShellItem CurrentItem {get; set;}\r\n\r\n  public ShellNavigationState CurrentState {get; }\r\n\r\n  public Color FlyoutBackgroundColor {get; set;}\r\n\r\n  public FlyoutBehavior FlyoutBehavior {get; set;}\r\n\r\n  public object FlyoutHeader {get; set;}\r\n\r\n  public FlyoutHeaderBehavior FlyoutHeaderBehavior {get; set;}\r\n\r\n  public DataTemplate FlyoutHeaderTemplate {get; set;}\r\n\r\n  public bool FlyoutIsPresented {get; set;}\r\n\r\n  public DataTemplate GroupHeaderTemplate {get; set;}\r\n\r\n  public ShellItemCollection Items {get; }\r\n\r\n  public DataTemplate ItemTemplate {get; set;}\r\n\r\n  public MenuItemCollection MenuItems {get; }\r\n\r\n  public DataTemplate MenuItemTemplate {get; set;}\r\n\r\n  public string Route {get; set;}\r\n\r\n  public string RouteHost { get; set; }\r\n\r\n  public string RouteScheme { get; set; }\r\n\r\n  public async Task GoToAsync(ShellNavigationState state, bool animate = true);\r\n\r\n  protected virtual void OnNavigated(ShellNavigatedEventArgs args);\r\n\r\n  protected virtual void OnNavigating(ShellNavigatingEventArgs args);\r\n}\r\n```\r\n#### Description\r\n\r\nAttached Properties:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| SearchHandlerProperty | Attached property for the definition of a page level Search capability. Can be attached at multiple points in the hierarchy.   Uses some of the features defined here https://material.io/guidelines/patterns/search.html#search-in-app-search |\r\n| BackButtonBehavior | Allows complete override of how the back button behaves. Applies to on-screen and physical back buttons. |\r\n| FlyoutBehavior | Defines how the Flyout should present itself. This can be attached to `ShellItem`s, `ShellContent`s, or `Page`s to override the default behavior. |\r\n| NavBarVisibleProperty | Property set on a `Page` to define if the NavBar should be visible when it is presented |\r\n| SetPaddingInsetsProperty | Setting this property on a `Page` will cause its `Padding` to be set such that its content will not flow under any Shell chrome. |\r\n| TabBarVisibleProperty | Property set on a `Page` to define if the TabBar should be visible when it is presented |\r\n| TitleViewProperty | Property set on a `Page` to define the `TitleView` |\r\n| ShellBackgroundColorProperty | Describes the background color which should be used for the chrome elements of the Shell. This color will not fill in behind the Content of the Shell. |\r\n| ShellDisabledColorProperty | The color to shade text/icons which are disabled |\r\n| ShellForegroundColorProperty | The color to shade normal text/icons in the shell |\r\n| ShellTabBarBackgroundColorProperty | Override of ShellBackgroudnColor for the TabBar. If not set ShellBackgroundColor will be used |\r\n| ShellTabBarDisabledColorProperty | Override of ShellDisabledColor for the TabBar. If not set ShellDisabledColorProperty will be used |\r\n| ShellTabBarForegroundColorProperty | Override of ShellForegroundColorProperty for the TabBar. If not set ShellForegroundColorProperty will be used |\r\n| ShellTabBarTitleColorProperty | Override of ShellTitleColorProperty for the TabBar. If not set ShellTitleColorProperty will be used |\r\n| ShellTabBarUnselectedColorProperty | Override of ShellUnselectedColorProperty for the TabBar. If not set ShellUnselectedColorProperty will be used |\r\n| ShellTitleColorProperty | The color used for the title of the current Page |\r\n| ShellUnselectedColorProperty | The color used for unselected text/icons in the shell chrome |\r\n\r\nProperties:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| CurrentItem | The currently selected ShellItem |\r\n| CurrentState | The current navigation state of the Shell. Passing this state back to GoToAsync will cause the Shell to return to navigate back state. |\r\n| FlyoutBackgroundColorProperty | The background color of the Flyout menu |\r\n| FlyoutBehavior | Sets the default `FlyoutBehavior` for the `Shell`. |\r\n| FlyoutHeader | The object used as the Header of the Flyout. If `FlyoutHeaderTemplate` is not null, this is passed as the `BindingContext` to the inflated object. If `FlyoutHeaderTemplate` is null and `FlyoutHeader` is of type `View` it will be used directly. Otherwise it will be shown by calling ToString() and displaying the result. |\r\n| FlyoutHeaderBehavior | Sets the behavior of the `FlyoutHeader` when the Flyout needs to be scrolled to show contents. |\r\n| FlyoutHeaderTemplate | The template used to create a header for the Flyout. |\r\n| FlyoutIsPresented | Gets or sets whether or not the Flyout is current visible |\r\n| GroupHeaderTemplate | The `DataTemplate` used to show a Group Header if a `ShellItem` requests to be displayed as a Group of Tabs in the Flyout. If null, no header is displayed. |\r\n| Items | The primary Content of a Shell. Items define the list of items that will show in the Flyout as well as the content that will be displayed when a sidebar item is selected. |\r\n| ItemTemplate | The `DataTemplate` used to show items from the `Items` collection in the Flyout. Allows the developer to control visuals in the Flyout. |\r\n| MenuItems | A collection of `MenuItem`s which will show up in the flyout in their own section. |\r\n| MenuItemTemplate | The `DataTemplate` to use when displayed a `MenuItem` in the Flyout. |\r\n| Route | The route part to address this element when performing deep linking. |\r\n| RouteHost | The string to place in the host portion of the URI generated when creating deep-links |\r\n| RouteScheme | The string to place in the scheme portion of the URI generated when creating deep-links |\r\n\r\nPublic Methods:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| GoToAsync | Navigate to a `ShellNavigationState`. Returns a Task which will complete once the animation has completed. |\r\n\r\nPublic Events:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| Navigating | The `Shell` is about to perform a Navigation either due to user interaction or the developer calling an API. The developer may cancel Navigation here if possible. |\r\n| Navigated | The `Shell` has completed a Navigation event. |\r\n\r\n### ShellItemCollection\r\nA collection for `ShellItem`s\r\n```csharp\r\npublic sealed class ShellItemCollection : IEnumerable<ShellItem>, IList<ShellItem>\r\n```\r\n\r\n### MenuItemCollection\r\nA collection for `MenuItem`s\r\n```csharp\r\npublic sealed class MenuItemCollection : IEnumerable<MenuItem>, IList<MenuItem>\r\n```\r\n\r\n### ShellSectionCollection\r\nA collection for `ShellSection`s\r\n```csharp\r\npublic sealed class ShellSectionCollection : IEnumerable<ShellSection>, IList<ShellSection>\r\n```\r\n\r\n### ShellContentCollection\r\nA collection for `ShellContent`s\r\n```csharp\r\npublic sealed class ShellContentCollection : IEnumerable<ShellContent>, IList<ShellContent>\r\n```\r\n\r\n### ShellNavigatingEventArgs\r\nAn `EventArgs` used to describe a navigation event which is about to occur. The `ShellNavigationEventArgs` may also be used to cancel the navigation event if the developer desires.\r\n```csharp\r\npublic class ShellNavigatingEventArgs : EventArgs\r\n{\r\n  public ShellNavigationState Current { get; }\r\n\r\n  public ShellNavigationState Target { get; }\r\n\r\n  public ShellNavigationSource Source { get; }\r\n\r\n  public bool CanCancel { get; }\r\n\r\n  public bool Cancel ();\r\n}\r\n```\r\n\r\nProperties:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| Current | The current NavigationState of the `Shell`. Calling `GoToAsync` with this `ShellNavigationState` will effectively undo this navigation event. |\r\n| Target | The state the `Shell` will be in after this navigation event completes. |\r\n| Source | The type of navigation which occurred to trigger this event. There may be multiple flags set. |\r\n| CanCancel | Whether or not the navigation event is cancellable. Not all events can be cancelled. |\r\n\r\nPublic Methods:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| Cancel | Cancels the current navigation event. Returns true if the cancellation was succesful. |\r\n\r\n### ShellNavigatedEventArgs\r\n```csharp\r\npublic class ShellNavigatedEventArgs : EventArgs\r\n{\r\n  public ShellNavigationState Previous { get; }\r\n\r\n  public ShellNavigationState Current { get; }\r\n\r\n  public ShellNavigationSource Source { get; }\r\n}\r\n```\r\n\r\nProperties:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| Previous | The prior NavigationState of the `Shell`. |\r\n| Current | The new state the `Shell` is in when this navigation event completed. |\r\n| Source | The type of navigation which occurred to trigger this event. There may be multiple flags set. |\r\n\r\n### ShellNavigationState\r\n```csharp\r\npublic class ShellNavigationState\r\n{\r\n  public Uri Location { get; set; }\r\n\r\n  public ShellNavigationState ();\r\n  public ShellNavigationState (string location);\r\n  public ShellNavigationState (Uri uri);\r\n\r\n  public static implicit operator ShellNavigationState (Uri uri);\r\n  public static implicit operator ShellNavigationState (String value);\r\n}\r\n```\r\n\r\nProperties:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| Location | The Uri which describes the navigation state of the `Shell` |\r\n\r\nConstructors:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| (void) | Creates a new `ShellNavigationState` with a null Location |\r\n| (String) | Creates a new `ShellNavigationState` with the Location set to the supplied `string` |\r\n| (Uri) | Creates a new `ShellNavigationState` with the Location set to the supplied `Uri` |\r\n\r\n\r\n### ShellNavigationSource\r\n```csharp\r\n[Flags]\r\npublic enum ShellNavigationSource\r\n{\r\n  Unknown = 0,\r\n  Push,\r\n  Pop,\r\n  PopToRoot,\r\n  Insert,\r\n  Remove,\r\n  ShellItemChanged,\r\n  ShellSectionChanged,\r\n  ShellContentChanged,\r\n}\r\n```\r\n\r\n### BaseShellItem\r\n```caharp\r\npublic class BaseShellItem : NavigableElement\r\n{\r\n  public static readonly BindableProperty FlyoutIconProperty;\r\n  public static readonly BindableProperty IconProperty;\r\n  public static readonly BindableProperty IsCheckedProperty;\r\n  public static readonly BindableProperty IsEnabledProperty;\r\n  public static readonly BindableProperty TitleProperty;\r\n\r\n  public ImageSource FlyoutIcon { get; set; }\r\n\r\n  public ImageSource Icon { get; set; }\r\n\r\n  public bool IsChecked { get; }\r\n\r\n  public bool IsEnabled { get; set; }\r\n\r\n  public string Route { get; set; }\r\n\r\n  public string Title { get; set; }\r\n}\r\n```\r\n\r\nProperties:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| FlyoutIcon | The default icon to use when displayed in the Flyout. Will default to Icon if not set. |\r\n| Icon | The icon to display in parts of the chrome which are not the Flyout. |\r\n| IsChecked | If the `BaseShellItem` is currently checked in the Flyout (and thus should be highlighted) |\r\n| IsEnabled | If the the `BaseShellItem` is selectable in the chrome |\r\n| Route | Equivelant to setting Routing.Route |\r\n| Title | The Title to display in the UI |\r\n\r\n### ShellGroupItem\r\n\r\n```csharp\r\npublic class ShellGroupItem : BaseShellItem\r\n{\r\n  public static readonly BindableProperty FlyoutDisplayOptionsProperty;;\r\n\r\n  public FlyoutDisplayOptions FlyoutDisplayOptions { get; set; }\r\n}\r\n```\r\n\r\nProperties:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| FlyoutDisplayOptions | Controls how this item and its children are displayed in the flyout |\r\n\r\n### ShellItem\r\n```csharp\r\n[ContentProperty(\"Items\")]\r\npublic class ShellItem : ShellGroupItem, IShellItemController, IElementConfiguration<ShellItem>\r\n{\r\n  public static readonly BindableProperty CurrentItemProperty;\r\n\r\n  public ShellItem();\r\n\r\n  public ShellSection CurrentItem { get; set; }\r\n\r\n  public ShellSectionCollection Items;\r\n\r\n  public static implicit operator ShellItem(ShellSection shellSection);\r\n\r\n  public static implicit operator ShellItem(ShellContent shellContent);\r\n\r\n  public static implicit operator ShellItem(TemplatedPage page);\r\n\r\n  public static implicit operator ShellItem(MenuItem menuItem);\r\n}\r\n```\r\n\r\nProperties:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| CurrentItem | The selected `ShellSection`. |\r\n| Items | The `ShellSectionCollection` which is the primary content of a ShellItem. This collection defines all the tabs within a ShellItem. |\r\n\r\n### ShellSection\r\n```csharp\r\n[ContentProperty(\"Items\")]\r\npublic class ShellSection : ShellGroupItem, IShellSectionController\r\n{\r\n  public static readonly BindableProperty CurrentItemProperty;\r\n  public static readonly BindableProperty ItemsProperty\r\n\r\n  public ShellSection();\r\n\r\n  public ShellContent CurrentItem { get; set; }\r\n\r\n  public ShellContentCollection Items { get; }\r\n\r\n  public IReadOnlyList<Page> Stack { get; }\r\n\r\n  public static implicit operator ShellSection(ShellContent shellContent);\r\n\r\n  public virtual async Task GoToAsync(List<string> routes, IDictionary<string, string> queryData, bool animate);\r\n\r\n  protected virtual IReadOnlyList<Page> GetNavigationStack();\r\n\r\n  protected virtual void OnInsertPageBefore(Page page, Page before);\r\n\r\n  protected async virtual Task<Page> OnPopAsync(bool animated);\r\n\r\n  protected virtual async Task OnPopToRootAsync(bool animated);\r\n\r\n  protected virtual Task OnPushAsync(Page page, bool animated);\r\n\r\n  protected virtual void OnRemovePage(Page page);\r\n}\r\n```\r\n\r\nProperties:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| CurrentItem | The selected `ShellContent` of the ShellSection. |\r\n| Items | The `ShellContentCollection` which is the root content of the ShellSection. |\r\n| Stack | The current pushed navigation stack on the ShellSection. |\r\n\r\nMethods:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| GoToAsync | Used by deep-linking to navigate to a known location. Should not need to be called directly in most cases. |\r\n| GetNavigationStack | Returns the current navigation stack |\r\n| OnInsertPageBefore | Called when the `INavigation` interfaces `InsertPageBefore` method is called |\r\n| OnPopAsync | Called when the `INavigation` interfaces `PopAsync` method is called |\r\n| OnPopToRootAsync | Called when the `INavigation` interfaces `PopToRootAsync` method is called |\r\n| OnPushAsync | Called when the `INavigation` interfaces `PushAsync` method is called |\r\n| OnRemovePage | Called when the `INavigation` interfaces `RemovePage` method is called |\r\n\r\n### ShellContent\r\n```csharp\r\n[ContentProperty(\"Content\")]\r\npublic class ShellContent : BaseShellItem, IShellContentController\r\n{\r\n  public static readonly BindableProperty ContentProperty;\r\n  public static readonly BindableProperty ContentTemplateProperty;\r\n  public static readonly BindableProperty MenuItemsProperty;\r\n\r\n  public ShellContent();\r\n\r\n  public object Content { get; set; }\r\n\r\n  public DataTemplate ContentTemplate { get; set; }\r\n\r\n  public MenuItemCollection MenuItems { get; }\r\n\r\n  public static implicit operator ShellContent(TemplatedPage page);\r\n}\r\n```\r\n\r\nProperties:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| Content | The Content of a ShellContent. Usually a `ContentPage` or the `BindingContext` of the `Page` inflated by the `ContentTemplate` |\r\n| ContentTemplate | Used to dynamically inflate the content of the `ShellContent`. The `Content` property will be set as the `BindingContext` after inflation. |\r\n| MenuItems | The items to display in the Flyout when this ShellContent is the presented page |\r\n\r\n### SearchHandler\r\n```csharp\r\npublic class SearchHandler : BindableObject, ISearchHandlerController\r\n{\r\n  public static readonly BindableProperty ClearIconHelpTextProperty;\r\n  public static readonly BindableProperty ClearIconNameProperty;\r\n  public static readonly BindableProperty ClearIconProperty;\r\n  public static readonly BindableProperty ClearPlaceholderCommandParameterProperty;\r\n  public static readonly BindableProperty ClearPlaceholderCommandProperty;\r\n  public static readonly BindableProperty ClearPlaceholderEnabledProperty;\r\n  public static readonly BindableProperty ClearPlaceholderHelpTextProperty;\r\n  public static readonly BindableProperty ClearPlaceholderIconProperty;\r\n  public static readonly BindableProperty ClearPlaceholderNameProperty;\r\n  public static readonly BindableProperty CommandParameterProperty;\r\n  public static readonly BindableProperty CommandProperty;\r\n  public static readonly BindableProperty DisplayMemberNameProperty;\r\n  public static readonly BindableProperty IsSearchEnabledProperty;\r\n  public static readonly BindableProperty ItemsSourceProperty;\r\n  public static readonly BindableProperty ItemTemplateProperty;\r\n  public static readonly BindableProperty PlaceholderProperty;\r\n  public static readonly BindableProperty QueryIconHelpTextProperty;\r\n  public static readonly BindableProperty QueryIconNameProperty;\r\n  public static readonly BindableProperty QueryIconProperty;\r\n  public static readonly BindableProperty QueryProperty;\r\n  public static readonly BindableProperty SearchBoxVisibilityProperty;\r\n  public static readonly BindableProperty ShowsResultsProperty;\r\n\r\n  public ImageSource ClearIcon { get; set; }\r\n\r\n  public string ClearIconHelpText { get; set; }\r\n\r\n  public string ClearIconName { get; set; }\r\n\r\n  public ICommand ClearPlaceholderCommand { get; set; }\r\n\r\n  public object ClearPlaceholderCommandParameter { get; set; }\r\n\r\n  public bool ClearPlaceholderEnabled { get; set; }\r\n\r\n  public string ClearPlaceholderHelpText { get; set; }\r\n\r\n  public ImageSource ClearPlaceholderIcon { get; set; }\r\n\r\n  public string ClearPlaceholderName { get; set; }\r\n\r\n  public ICommand Command { get; set; }\r\n\r\n  public object CommandParameter { get; set; }\r\n\r\n  public string DisplayMemberName { get; set; }\r\n\r\n  public bool IsSearchEnabled { get; set; }\r\n\r\n  public IEnumerable ItemsSource { get; set; }\r\n\r\n  public DataTemplate ItemTemplate { get; set; }\r\n\r\n  public string Placeholder { get; set; }\r\n\r\n  public string Query { get; set; }\r\n\r\n  public ImageSource QueryIcon { get; set; }\r\n\r\n  public string QueryIconHelpText { get; set; }\r\n\r\n  public string QueryIconName { get; set; }\r\n\r\n  public SearchBoxVisiblity SearchBoxVisibility { get; set; }\r\n\r\n  public bool ShowsResults { get; set; }\r\n\r\n  protected virtual void OnClearPlaceholderClicked();\r\n\r\n  protected virtual void OnItemSelected(object item);\r\n\r\n  protected virtual void OnQueryChanged(string oldValue, string newValue);\r\n\r\n  protected virtual void OnQueryConfirmed();\r\n}\r\n```\r\n\r\nProperties:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| ClearIconHelpText | The accessible help text for the clear icon |\r\n| ClearIconNameProperty | The name of the clear icon for usage with screen readers |\r\n| ClearIcon | The icon displayed to clear the contents of the search box. |\r\n| ClearPlaceholderCommandParameter | The paramter for the `ClearPlaceholderCommand` |\r\n| ClearPlacehodlerCommand | The command to execute when the ClearPlaceholder icon is tapped |\r\n| ClearPlaceholderEnabled | The enabled state of the ClearPlaceholderIcon. Default is true. |\r\n| ClearPlaceholderHelpText | The accessible help text for the clear placeholder icon |\r\n| ClearPlaceholderIcon | The icon displayed in the `ClearIcon` location when the search box is empty. |\r\n| ClearPlaceholderName | The name of the clear placeholder icon for usage with screen readers |\r\n| CommandParameter | The parameter for the `Command` |\r\n| Command | The `ICommand` to execute when a query is confirmed\r\n| DisplayMemberPath | The name or path of the property that is displayed for each the data item in the `ItemsSource`. |\r\n| IsSearchEnabled | Controls the enabled state of the search box. |\r\n| ItemsSource | A collection of items to display in the suggestion area. |\r\n| ItemTemplate | A template for the items displayed in the suggestion area. |\r\n| Placeholder | A string to display when the search box is empty. |\r\n| QueryIconHelpTextProperty | The accessible help text for the query icon |\r\n| QueryIconNameProperty | The name of the query icon for usage with screen readers |\r\n| QueryIcon | The icon used to indicate to the user that search is available |\r\n| Query | The current string in the search box. |\r\n| SearchBoxVisibility | Defines the visibility of the search box in the `Shell`s chrome. |\r\n| ShowsResults | Determines if search results should be expected on text entry |\r\n\r\nProtected Methods:\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| OnClearPlaceholderClicked | Called whenever the ClearPlaceholder icon has been pressed. |\r\n| OnItemSelected | Called whenever a search result is pressed by the user |\r\n| OnQueryConfirmed | Called whenever the user pressed enter or confirms their entry in the search box. |\r\n| OnQueryChanged | Called when the `Query` is changed. |\r\n\r\n### SearchBoxVisiblity\r\n```csharp\r\npublic enum SearchBoxVisiblity\r\n{\r\n  Hidden,\r\n  Collapsable,\r\n  Expanded\r\n}\r\n```\r\n\r\n| Value | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| Hidden | The search box is not visible or accessible. |\r\n| Collapsable | The search box is hidden until the user performs an action to reveal it. |\r\n| Expanded | The search box is visible as a fully expanded entry. |\r\n\r\n### BackButtonBehavior\r\n```csharp\r\npublic class BackButtonBehavior : BindableObject\r\n{\r\n  public ImageSource IconOverride { get; set; }\r\n  public string TextOverride { get; set; }\r\n  public ICommand Command { get; set; }\r\n  public object CommandParameter { get; set; }\r\n}\r\n```\r\n\r\n| API | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| IconOverride | Changes the Icon used for the back button. |\r\n| TextOverride | Changes the Text used to indicate backwards navigation if text is used. |\r\n| Command | Provides a replacement command to invoke when the back button is pressed. |\r\n| CommandParameter | The command parameter used with `Command` |\r\n\r\n### FlyoutDisplayOptions\r\nDetermines how the `ShellGroupItem` should display in the FlyoutMenu.\r\n```csharp\r\n  public enum FlyoutDisplayOptions\r\n  {\r\n    AsSingleItem,\r\n    AsMultipleItems,\r\n  }\r\n```\r\n\r\n| Value | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| AsSingleItem | The `ShellGroupItem` will be visible as a single entry in the Flyout. |\r\n| AsMultipleItems | The `ShellGroupItem` will be visible as a group of items, one for each child in the Flyout. |\r\n\r\n### FlyoutHeaderBehavior\r\nControls the behavior of the FlyoutHeader when scrolling.\r\n```csharp\r\npublic enum FlyoutHeaderBehavior {\r\n  Default,\r\n  Fixed,\r\n  Scroll,\r\n  CollapseOnScroll,\r\n}\r\n```\r\n\r\n| Value | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| Default | Platform default behavior. |\r\n| Fixed | Header remains visible and unchanged at all times |\r\n| Scroll | Header scrolls out of view as user scrolls menu |\r\n| CollapseOnScroll | Header collapses to title only as user scrolls |\r\n\r\n### FlyoutBehavior\r\n```csharp\r\npublic enum FlyoutBehavior\r\n{\r\n  Disabled,\r\n  Flyout,\r\n  Locked\r\n}\r\n```\r\n\r\n| Value | Description |\r\n| -----------| ----------------------------------------------------------------------------------------------|\r\n| Disabled | The flyout cannot be acccessed by the user. |\r\n| Flyout | The Flyout is works as a normal flyout which can be open/closed by the user. |\r\n| Locked | The Flyout is locked out and cannot be closed by the user, it does not overalp content. |\r\n\r\n### DataTemplateExtension\r\nThis extension quickly converts a type into a ControlTemplate. This is useful for instances where the template would otherwise be specified as\r\n```xaml\r\n<ListView>\r\n  <ListView.ItemTemplate>\r\n    <DataTemplate>\r\n      <local:MyCell />\r\n    </DataTemplate>\r\n  </ListView.ItemTemplate>\r\n</ListView>\r\n```\r\n\r\nThis can then be condensed down to\r\n```xaml\r\n<ListView ItemTemplate=\"{DataTemplate local:MyCell}\" />\r\n```\r\n\r\n```csharp\r\npublic sealed class ControlTemplateExtension : IBindingExtension<ControlTemplate>\r\n```\r\n\r\n```csharp\r\npublic sealed class DataTemplateExtension : IBindingExtension<DataTemplate>\r\n```\r\n## Odds and Ends\r\n\r\n### What happens when you select a tab in Flyout which has been pushed to?\r\nThis is the equivalent of focusing the tab and calling PopToRoot on it.\r\n\r\n### What happens when I switch ShellItems and there are items on the backstack of a ShellContent of the old ShellItem\r\nIf the old ShellItem is templated, the back stack is lost. If the ShellItem is not templated the BackStack stays intact and when switching back to the old ShellItem the backstack will be properly reflected. Switching back may clear the backstack however as indicated in the above answer.\r\n\r\n# Effecient loading of pages\r\nA major problem with using the Shell is the ease by which a user can end up loading all pages at the start of their application run. This large frontloaded allocation can result in quite poor startup performance if a large number of content pages are needed. In order to fix this templating should be employed when possible.\r\n\r\n## Templated ShellContents\r\nTemplating shell tab items is the most granular form of templating available, it is fortunately also the easiest to do. Take the following shell.\r\n\r\n```xaml\r\n<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<MaterialShell xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n               xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n               xmlns:local=\"clr-namespace:MyStore\"\r\n               x:Class=\"MyStore.Shell\">\r\n\r\n  <ShellItem Title=\"My apps &amp; games\">\r\n    <local:UpdatesPage />\r\n    <local:InstalledPage />\r\n    <local:LibraryPage />\r\n  </ShellItem>\r\n\r\n  <ShellItem GroupBehavior=\"ShowTabs\">\r\n    <local:HomePage />\r\n    <local:GamesPage />\r\n    <local:MoviesTVPage />\r\n    <local:BooksPage />\r\n    <local:MusicPage />\r\n    <local:NewsstandPage />\r\n  </ShellItem>\r\n</MaterialShell>\r\n```\r\n\r\nWhen this Shell loads, all 9 pages will be inflated at once. This is because no templating is employed. To employ basic templating we can convert this into:\r\n\r\n```xaml\r\n<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<MaterialShell xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n               xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n               xmlns:local=\"clr-namespace:MyStore\"\r\n               x:Class=\"MyStore.Shell\">\r\n\r\n  <ShellItem Title=\"My apps &amp; games\">\r\n    <ShellContent Title=\"Updates\"        Icon=\"updates.png\" ContentTemplate=\"{DataTemplate local:UpdatesPage}\" />\r\n    <ShellContent Title=\"Installed Apps\" Icon=\"apps.png\"    ContentTemplate=\"{DataTemplate local:InstalledPage}\" />\r\n    <ShellContent Title=\"Library\"        Icon=\"library.png\" ContentTemplate=\"{DataTemplate local:LibraryPage}\" />\r\n  </ShellItem>\r\n\r\n  <ShellItem GroupBehavior=\"ShowTabs\">\r\n    <ShellContent Title=\"Home\"          Icon=\"updates.png\"   ContentTemplate=\"{DataTemplate local:HomePage}\" />\r\n    <ShellContent Title=\"Games\"         Icon=\"games.png\"     ContentTemplate=\"{DataTemplate local:GamesPage}\" />\r\n    <ShellContent Title=\"Movies and TV\" Icon=\"moviesTV.png\"  ContentTemplate=\"{DataTemplate local:MoviesTVPage}\" />\r\n    <ShellContent Title=\"Books\"         Icon=\"books.png\"     ContentTemplate=\"{DataTemplate local:BooksPage}\" />\r\n    <ShellContent Title=\"Music\"         Icon=\"music.png\"     ContentTemplate=\"{DataTemplate local:MusicPage}\" />\r\n    <ShellContent Title=\"Newsstand\"     Icon=\"newsstand.png\" ContentTemplate=\"{DataTemplate local:NewsstandPage}\" />\r\n  </ShellItem>\r\n</MaterialShell>\r\n```\r\n\r\nPages are now only loaded as needed and can be unloaded as needed as well. If needed the ShellItem's themselves can also be templated with a collection and a DataTemplateSelector which prevents even the ShellContents from having to be loaded eagerly, however this is largely unneeded and templating ShellItem is more useful for Shells that have ShellItems with large numbers of otherwise similar tabs. Templating the ShellContent should be the key area to provide templating for performance concerns.\r\n\r\n# Reconstructing the Google Play Store User Interface\r\nPlease note this is not intended to be a demo of the best way to code an application, but really the most concise format to shove together the UI for GPS. It also makes no attempt to virtualize the relevant pages by using ViewModels and DataTemplateSelector's. This means this would be quite bad performing as all pages would be loaded at app start. Reader is warned.\r\n\r\nAll page content is assumed to be working right, this is only to get the general idea of the chrome.\r\n## Shell.xaml\r\nA proper implementation of this would use ShellItems for every page and set the ItemsSource and ItemTemplate. This would allow each page to only be loaded once it is needed and unloaded when no longer needed.\r\n```xaml\r\n<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<MaterialShell xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n               xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n               xmlns:local=\"clr-namespace:MyStore\"\r\n               x:Class=\"MyStore.Shell\"\r\n               FlyoutHeaderBehavior=\"Fixed\"\r\n               FlyoutHeader=\"{x:Bind HeaderViewModel}\">\r\n  <MaterialShell.FlyoutHeaderTemplate>\r\n    <local:CircleImageAndLabelControl HeightRequest=\"350\" />\r\n  </MaterialShell.FlyoutHeaderTempalte>\r\n\r\n  <ShellItem Title=\"My apps &amp; games\">\r\n    <ShellItem.ShellAppearance>\r\n      <MaterialShellAppearance NavBarCollapseStyle=\"Full\">\r\n    </ShellItem.ShellAppearance>\r\n    <local:UpdatesPage />\r\n    <local:InstalledPage />\r\n    <local:LibraryPage />\r\n  </ShellItem>\r\n\r\n  <local:NotificationsPage Title=\"My notifications\" />\r\n\r\n  <local:SubscriptionsPage />\r\n\r\n  <ShellItem GroupBehavior=\"ShowTabs\">\r\n    <ShellItem.ShellAppearance>\r\n      <MaterialShellAppearance NavBarCollapseStyle=\"Full\" TabBarCollapseStyle=\"Full\" UseSwipeGesture=\"false\">\r\n    </ShellItem.ShellAppearance>\r\n    <local:HomePage />\r\n    <local:GamesPage />\r\n    <ShellContent Title=\"Movies &amp; TV\" Icon=\"moviesTV.png\" ContentTemplate=\"{DataTemplate local:MoviesTVPage}\">\r\n      <ShellContent.MenuItems>\r\n        <MenuItem Title=\"Open Movies &amp; TV app\" Command=\"{xBind MoviesTVAppCommand}\" />\r\n      </ShellContent.MenuItems>\r\n    </ShellContent>\r\n    <ShellContent Title=\"Books\" Icon=\"books.png\" ContentTemplate=\"{DataTemplate local:BooksPage}\">\r\n      <ShellContent.MenuItems>\r\n        <MenuItem Title=\"Open Books app\" Command=\"{xBind BooksAppCommand}\" />\r\n      </ShellContent.MenuItems>\r\n    </ShellContent>\r\n    <ShellContent Title=\"Music\" Icon=\"music.png\" ContentTemplate=\"{DataTemplate local:MusicPage}\">\r\n      <ShellContent.MenuItems>\r\n        <MenuItem Title=\"Open Music app\" Command=\"{xBind MusicAppCommand}\" />\r\n      </ShellContent.MenuItems>\r\n    </ShellContent>\r\n    <ShellContent Title=\"Newsstand\" Icon=\"newsstand.png\" ContentTemplate=\"{DataTemplate local:NewsstandPage}\">\r\n      <ShellContent.MenuItems>\r\n        <MenuItem Title=\"Open Newsstand app\" Command=\"{xBind NewsstandAppCommand}\" />\r\n      </ShellContent.MenuItems>\r\n  </ShellItem>\r\n\r\n  <local:AccountPage />\r\n\r\n  <MenuItem Title=\"Redeem\" Icon=\"redeem.png\" Command=\"{x:Bind RedeemCommand}\" />\r\n\r\n  <local:WishlistPage />\r\n\r\n  <MenuItem Title=\"Play Protect\" Icon=\"protect.png\" Command=\"{x:Bind NavigateCommand}\" CommandParameter=\"ProtectPage\" />\r\n\r\n  <MenuItem Title=\"Settings\" Icon=\"settings.png\" Command=\"{x:Bind SettingsCommand}\" CommandParameter=\"SettingsPage\" />\r\n\r\n  <MaterialShell.MenuItems>\r\n    <MenuItem Title=\"Help &amp; feedback\" Command=\"{x:Bind NavigateCommand}\" CommandParameter=\"HelpPage\" />\r\n    <MenuItem Title=\"Parent Guide\" Command=\"{x:Bind NavigateCommand}\" CommandParameter=\"ParentPage\" />\r\n    <MenuItem Title=\"Help &amp; feedback\" Command=\"{x:Bind UrlCommand}\" CommandParameter=\"http://support.google.com/whatever\" />\r\n  </MaterialShell.MenuItems>\r\n</MaterialShell>\r\n```\r\n\r\n## The store pages\r\n\r\n```xaml\r\n<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<ContentPage xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n             xmlns:local=\"clr-namespace:MyStore\"\r\n             x:Class=\"MyStore.HomePage\"\r\n             Title=\"Home\"\r\n             Icon=\"home.png\"\r\n             ShellAppearance.BackgroundColor=\"Green\">\r\n  <Label Text=\"Home content here\" />\r\n</ContentPage>\r\n```\r\n\r\n```xaml\r\n<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<ContentPage xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n             xmlns:local=\"clr-namespace:MyStore\"\r\n             x:Class=\"MyStore.MoviesTVPage\"\r\n             Title=\"Movies &amp; TV\"\r\n             Icon=\"movies.png\"\r\n             ShellAppearance.BackgroundColor=\"Red\">\r\n  <Label Text=\"Movies and TV content here\" />\r\n</ContentPage>\r\n```\r\n\r\nAnd to add the search bar.\r\n\r\n```csharp\r\npublic class HomePage : ContentPage\r\n{\r\n  public class HomeSearchHandler : SearchHandler\r\n  {\r\n    public HomeSearchHandler ()\r\n    {\r\n      SearchBoxVisibility = SearchBoxVisibility.Expanded;\r\n      IsSearchEnabled = true;\r\n      Placeholder = \"Google Play\";\r\n      CancelPlaceholderIcon = \"microphone.png\"\r\n    }\r\n\r\n    protected override void OnSearchConfirmed (string query)\r\n    \r\n{      // Navigate to search results page here\r\n    }\r\n    \r\n    protected override void OnSearchChanged (string oldValue, string newValue)\r\n    {\r\n    }\r\n\r\n    protected override void OnCancelPlaceholderPressed ()\r\n    {\r\n      // Trigger voice API here\r\n    }\r\n  }\r\n\r\n  public HomePage\r\n  {\r\n    Shell.SetSearchHandler (this, new HomeSearchHandler ());\r\n  }  \r\n}\r\n```\r\n\r\nAnd so on and so on setting the colors and the content correctly.\r\n\r\nFor pages like the Settings page where the flyout should not be accessible until the back button is pressed:\r\n\r\n```xaml\r\n<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<ContentPage xmlns=\"http://xamarin.com/schemas/2014/forms\"\r\n             xmlns:x=\"http://schemas.microsoft.com/winfx/2009/xaml\"\r\n             xmlns:local=\"clr-namespace:MyStore\"\r\n             x:Class=\"MyStore.SettingsPage\"\r\n             Title=\"Settings\"\r\n             Icon=\"settings.png\"\r\n             ShellAppearance.BackgroundColor=\"Grey\"\r\n             MaterialShell.FlyoutBehavior=\"Disabled\">\r\n  <Label Text=\"Settings content here\" />\r\n</ContentPage>\r\n```\r\n\r\n\r\n# TODO\r\n- [x] Add API for search box\r\n- [x] Add API for ContentSafeArea handling\r\n- [x] Add API for floating menu\r\n- [x] Add API for window menu items\r\n- [x] Add API for snackbar\r\n- [x] Add API for navigation interruption\r\n- [x] Add API for bottom sheet\r\n- [x] Add API to position FAB\r\n- [ ] Add stories to make navigation ideas clearer (partially done)\r\n- [x] Add LeftBarButton style API\r\n- [x] Add mechanism for getting Back Stack from ShellContent\r\n- [x] Add API for changing color of the ribbon based on selected tab\r\n- [x] Add optional suggestion support for SearchHandler\r\n- [x] Add support for configuring always expanded search bar vs search bar as icon\r\n- [x] Add API for getting the \"Current\" page from the MaterialShell class. Needed for some navigation scenarios.\r\n- [x] Add API for saving \"states\" to the back stack\r\n- [x] Add API to block flyout from coming out\r\n- [x] Add API for \"submenu\" items for ShellContent's ala GPS -> Music -> Open Music app\r\n- [x] Add API for CancelPlaceholder Command and Icon (usually used for microphone icon for voice search)\r\n- [x] Segue API\r\n- [x] Work out what to do with INavigation\r\n- [ ] Expand Bottom Sheet API to match Google Maps capabilities\r\n- [x] API to handle Flyout presentation\r\n- [ ] API to disable Flyout gesture when needed\r\n- [ ] Large title API\r\n- [ ] Transitions API\r\n\r\n# Issues\r\n\r\n## ISearchHandler [FIXED]\r\n\r\nThere is a lot this interface is doing and worse it's probably going to need to be expanded as time goes on. Therefor it stands to reason that it should probably instead be an abstract base class the user can implement. This unfortunate means yet another object allocation. However it maintains flexibility in the future. It is likely this change will happen.\r\n\r\n## Floating Menu\r\n\r\nThe attachment API is a bit heavy and perhaps too confusing for users. Worse it might not map very well to all platforms to make sure the attachment works with animations. More work is required to validate this API."},"comment":{"url":"https://api.github.com/repos/xamarin/Xamarin.Forms/issues/comments/396830487","html_url":"https://github.com/xamarin/Xamarin.Forms/issues/2415#issuecomment-396830487","issue_url":"https://api.github.com/repos/xamarin/Xamarin.Forms/issues/2415","id":396830487,"node_id":"MDEyOklzc3VlQ29tbWVudDM5NjgzMDQ4Nw==","user":{"login":"jassmith","id":30443,"node_id":"MDQ6VXNlcjMwNDQz","avatar_url":"https://avatars2.githubusercontent.com/u/30443?v=4","gravatar_id":"","url":"https://api.github.com/users/jassmith","html_url":"https://github.com/jassmith","followers_url":"https://api.github.com/users/jassmith/followers","following_url":"https://api.github.com/users/jassmith/following{/other_user}","gists_url":"https://api.github.com/users/jassmith/gists{/gist_id}","starred_url":"https://api.github.com/users/jassmith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jassmith/subscriptions","organizations_url":"https://api.github.com/users/jassmith/orgs","repos_url":"https://api.github.com/users/jassmith/repos","events_url":"https://api.github.com/users/jassmith/events{/privacy}","received_events_url":"https://api.github.com/users/jassmith/received_events","type":"User","site_admin":false},"created_at":"2018-06-13T06:39:56Z","updated_at":"2018-06-13T06:39:56Z","author_association":"MEMBER","body":"I'm all for adding these kinds of toast notifications to Shell, just trying to figure out how it should be done."}}
{"actor":{"display_login":"jassmith"}}