Esempio n. 1
0
        public virtual void AddChild(MC.Element child, int physicalSiblingIndex)
        {
            if (child is null)
            {
                throw new ArgumentNullException(nameof(child));
            }

            MC.ShellItem itemToAdd = child switch
            {
                MC.TemplatedPage childAsTemplatedPage => childAsTemplatedPage,       // Implicit conversion
                         MC.ShellContent childAsShellContent => childAsShellContent, // Implicit conversion
                         MC.ShellSection childAsShellSection => childAsShellSection, // Implicit conversion
                         MC.MenuItem childAsMenuItem => childAsMenuItem,             // Implicit conversion
                         MC.ShellItem childAsShellItem => childAsShellItem,
                         _ => throw new NotSupportedException($"Handler of type '{GetType().FullName}' representing element type '{TargetElement?.GetType().FullName ?? "<null>"}' doesn't support adding a child (child type is '{child.GetType().FullName}').")
            };

            if (ShellControl.Items.Count >= physicalSiblingIndex)
            {
                ShellControl.Items.Insert(physicalSiblingIndex, itemToAdd);
            }
            else
            {
                Debug.WriteLine($"WARNING: {nameof(AddChild)} called with {nameof(physicalSiblingIndex)}={physicalSiblingIndex}, but ShellControl.Items.Count={ShellControl.Items.Count}");
                ShellControl.Items.Add(itemToAdd);
            }
        }
Esempio n. 2
0
 private MC.ShellContent GetContentForChild(MC.Element child)
 {
     return(child switch
     {
         MC.TemplatedPage childAsTemplatedPage => GetContentForTemplatePage(childAsTemplatedPage),
         MC.ShellContent childAsShellContent => childAsShellContent,
         _ => null
     });
Esempio n. 3
0
 private MC.ShellSection GetSectionForElement(MC.Element child)
 {
     return(child switch
     {
         MC.TemplatedPage childAsTemplatedPage => GetSectionForTemplatedPage(childAsTemplatedPage),
         MC.ShellContent childAsShellContent => GetSectionForContent(childAsShellContent),
         MC.ShellSection childAsShellSection => childAsShellSection,
         _ => null
     });
Esempio n. 4
0
 private MC.ShellItem GetItemForElement(MC.Element child)
 {
     return(child switch
     {
         MC.TemplatedPage childAsTemplatedPage => GetItemForTemplatedPage(childAsTemplatedPage),
         MC.ShellContent childAsShellContent => GetItemForContent(childAsShellContent),
         MC.ShellSection childAsShellSection => GetItemForSection(childAsShellSection),
         MC.MenuItem childAsMenuItem => GetItemForMenuItem(childAsMenuItem),
         MC.ShellItem childAsShellItem => childAsShellItem,
         _ => null
     });
Esempio n. 5
0
        public virtual void RemoveChild(MC.Element child)
        {
            if (child is null)
            {
                throw new ArgumentNullException(nameof(child));
            }

            MC.ShellContent contentToRemove = GetContentForChild(child)
                                              ?? throw new NotSupportedException($"Handler of type '{GetType().FullName}' representing element type '{TargetElement?.GetType().FullName ?? "<null>"}' doesn't support removing a child (child type is '{child.GetType().FullName}').");

            ShellSectionControl.Items.Remove(contentToRemove);
        }
 private static ElementHandler CreateHandler(MC.Element parent, MobileBlazorBindingsRenderer renderer)
 {
     return(parent switch
     {
         MC.ContentPage contentPage => new ContentPageHandler(renderer, contentPage),
         MC.ContentView contentView => new ContentViewHandler(renderer, contentView),
         MC.Label label => new LabelHandler(renderer, label),
         MC.FlyoutPage flyoutPage => new FlyoutPageHandler(renderer, flyoutPage),
         MC.ScrollView scrollView => new ScrollViewHandler(renderer, scrollView),
         MC.ShellContent shellContent => new ShellContentHandler(renderer, shellContent),
         MC.Shell shell => new ShellHandler(renderer, shell),
         MC.ShellItem shellItem => new ShellItemHandler(renderer, shellItem),
         MC.ShellSection shellSection => new ShellSectionHandler(renderer, shellSection),
         MC.TabbedPage tabbedPage => new TabbedPageHandler(renderer, tabbedPage),
         _ => new ElementHandler(renderer, parent),
     });
        public ShellContentHandler(NativeComponentRenderer renderer, MC.ShellContent shellContentControl) : base(renderer, shellContentControl)
        {
            ShellContentControl = shellContentControl ?? throw new ArgumentNullException(nameof(shellContentControl));

            Initialize(renderer);
        }
Esempio n. 8
0
        public static ShellNavigationState GetNavigationState(ShellItem shellItem, ShellSection shellSection, ShellContent shellContent, IReadOnlyList <Page> sectionStack, IReadOnlyList <Page> modalStack)
        {
            List <string> routeStack = new List <string>();

            bool stackAtRoot         = sectionStack == null || sectionStack.Count <= 1;
            bool hasUserDefinedRoute =
                (Routing.IsUserDefined(shellItem)) ||
                (Routing.IsUserDefined(shellSection)) ||
                (Routing.IsUserDefined(shellContent));

            if (shellItem != null)
            {
                var shellItemRoute = shellItem.Route;
                routeStack.Add(shellItemRoute);

                if (shellSection != null)
                {
                    var shellSectionRoute = shellSection.Route;
                    routeStack.Add(shellSectionRoute);

                    if (shellContent != null)
                    {
                        var shellContentRoute = shellContent.Route;
                        routeStack.Add(shellContentRoute);
                    }

                    if (!stackAtRoot)
                    {
                        for (int i = 1; i < sectionStack.Count; i++)
                        {
                            var page = sectionStack[i];
                            routeStack.AddRange(ShellUriHandler.CollapsePath(Routing.GetRoute(page), routeStack, hasUserDefinedRoute));
                        }
                    }

                    if (modalStack != null && modalStack.Count > 0)
                    {
                        for (int i = 0; i < modalStack.Count; i++)
                        {
                            var topPage = modalStack[i];

                            routeStack.AddRange(ShellUriHandler.CollapsePath(Routing.GetRoute(topPage), routeStack, hasUserDefinedRoute));

                            for (int j = 1; j < topPage.Navigation.NavigationStack.Count; j++)
                            {
                                routeStack.AddRange(ShellUriHandler.CollapsePath(Routing.GetRoute(topPage.Navigation.NavigationStack[j]), routeStack, hasUserDefinedRoute));
                            }
                        }
                    }
                }
            }

            if (routeStack.Count > 0)
            {
                routeStack.Insert(0, "/");
            }

            return(new ShellNavigationState(String.Join("/", routeStack), true));
        }
Esempio n. 9
0
        public async Task GoToAsync(ShellNavigationParameters shellNavigationParameters)
        {
            if (shellNavigationParameters.PagePushing != null)
            {
                Routing.RegisterImplicitPageRoute(shellNavigationParameters.PagePushing);
            }

            var  state   = shellNavigationParameters.TargetState ?? new ShellNavigationState(Routing.GetRoute(shellNavigationParameters.PagePushing), false);
            bool?animate = shellNavigationParameters.Animated;
            bool enableRelativeShellRoutes        = shellNavigationParameters.EnableRelativeShellRoutes;
            ShellNavigatingEventArgs deferredArgs = shellNavigationParameters.DeferredArgs;

            var  navigationRequest = ShellUriHandler.GetNavigationRequest(_shell, state.FullLocation, enableRelativeShellRoutes, shellNavigationParameters: shellNavigationParameters);
            bool isRelativePopping = ShellUriHandler.IsTargetRelativePop(shellNavigationParameters);

            ShellNavigationSource source = CalculateNavigationSource(_shell, _shell.CurrentState, navigationRequest);

            // If the deferredArgs are non null that means we are processing a delayed navigation
            // so the user has indicated they want to go forward with navigation
            // This scenario only comes up from UI iniated navigation (i.e. switching tabs)
            if (deferredArgs == null)
            {
                var navigatingArgs = ProposeNavigation(source, state, _shell.CurrentState != null, animate ?? true);

                if (navigatingArgs != null)
                {
                    bool accept = !navigatingArgs.NavigationDelayedOrCancelled;
                    if (navigatingArgs.DeferredTask != null)
                    {
                        accept = await navigatingArgs.DeferredTask;
                    }

                    if (!accept)
                    {
                        return;
                    }
                }
            }

            Routing.RegisterImplicitPageRoutes(_shell);

            _accumulateNavigatedEvents = true;

            var uri         = navigationRequest.Request.FullUri;
            var queryString = navigationRequest.Query;
            var queryData   = ParseQueryString(queryString);

            ApplyQueryAttributes(_shell, queryData, false, false);

            var shellItem           = navigationRequest.Request.Item;
            var shellSection        = navigationRequest.Request.Section;
            var currentShellSection = _shell.CurrentItem?.CurrentItem;
            var nextActiveSection   = shellSection ?? shellItem?.CurrentItem;

            ShellContent shellContent       = navigationRequest.Request.Content;
            bool         modalStackPreBuilt = false;

            // If we're replacing the whole stack and there are global routes then build the navigation stack before setting the shell section visible
            if (navigationRequest.Request.GlobalRoutes.Count > 0 &&
                nextActiveSection != null &&
                navigationRequest.StackRequest == NavigationRequest.WhatToDoWithTheStack.ReplaceIt)
            {
                modalStackPreBuilt = true;

                bool?isAnimated = (nextActiveSection != currentShellSection) ? false : animate;
                await nextActiveSection.GoToAsync(navigationRequest, queryData, isAnimated, isRelativePopping);
            }

            if (shellItem != null)
            {
                ApplyQueryAttributes(shellItem, queryData, navigationRequest.Request.Section == null, false);
                bool navigatedToNewShellElement = false;

                if (shellSection != null && shellContent != null)
                {
                    ApplyQueryAttributes(shellContent, queryData, navigationRequest.Request.GlobalRoutes.Count == 0, isRelativePopping);
                    if (shellSection.CurrentItem != shellContent)
                    {
                        shellSection.SetValueFromRenderer(ShellSection.CurrentItemProperty, shellContent);
                        navigatedToNewShellElement = true;
                    }
                }

                if (shellSection != null)
                {
                    ApplyQueryAttributes(shellSection, queryData, navigationRequest.Request.Content == null, false);
                    if (shellItem.CurrentItem != shellSection)
                    {
                        shellItem.SetValueFromRenderer(ShellItem.CurrentItemProperty, shellSection);
                        navigatedToNewShellElement = true;
                    }
                }

                if (_shell.CurrentItem != shellItem)
                {
                    _shell.SetValueFromRenderer(Shell.CurrentItemProperty, shellItem);
                    navigatedToNewShellElement = true;
                }

                if (!modalStackPreBuilt && currentShellSection?.Navigation.ModalStack.Count > 0)
                {
                    // - navigating to new shell element so just pop everything
                    // - or route contains no global route requests
                    if (navigatedToNewShellElement || navigationRequest.Request.GlobalRoutes.Count == 0)
                    {
                        // remove all non visible pages first so the transition just smoothly goes from
                        // currently visible modal to base page
                        if (navigationRequest.Request.GlobalRoutes.Count == 0)
                        {
                            for (int i = currentShellSection.Stack.Count - 1; i >= 1; i--)
                            {
                                currentShellSection.Navigation.RemovePage(currentShellSection.Stack[i]);
                            }
                        }

                        await currentShellSection.PopModalStackToPage(null, animate);
                    }
                }

                if (navigationRequest.Request.GlobalRoutes.Count > 0 && navigationRequest.StackRequest != NavigationRequest.WhatToDoWithTheStack.ReplaceIt)
                {
                    // TODO get rid of this hack and fix so if there's a stack the current page doesn't display
                    await Device.InvokeOnMainThreadAsync(() =>
                    {
                        return(_shell.CurrentItem.CurrentItem.GoToAsync(navigationRequest, queryData, animate, isRelativePopping));
                    });
                }
                else if (navigationRequest.Request.GlobalRoutes.Count == 0 &&
                         navigationRequest.StackRequest == NavigationRequest.WhatToDoWithTheStack.ReplaceIt &&
                         currentShellSection?.Navigation?.NavigationStack?.Count > 1)
                {
                    // TODO get rid of this hack and fix so if there's a stack the current page doesn't display
                    await Device.InvokeOnMainThreadAsync(() =>
                    {
                        return(_shell.CurrentItem.CurrentItem.GoToAsync(navigationRequest, queryData, animate, isRelativePopping));
                    });
                }
            }
            else
            {
                await _shell.CurrentItem.CurrentItem.GoToAsync(navigationRequest, queryData, animate, isRelativePopping);
            }

            _accumulateNavigatedEvents = false;

            // this can be null in the event that no navigation actually took place!
            if (_accumulatedEvent != null)
            {
                HandleNavigated(_accumulatedEvent);
            }
        }