summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.WP8/NavigationPageRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.WP8/NavigationPageRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.WP8/NavigationPageRenderer.cs209
1 files changed, 209 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.WP8/NavigationPageRenderer.cs b/Xamarin.Forms.Platform.WP8/NavigationPageRenderer.cs
new file mode 100644
index 00000000..6f290107
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/NavigationPageRenderer.cs
@@ -0,0 +1,209 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ public class NavigationPageRenderer : VisualElementRenderer<NavigationPage, FrameworkElement>
+ {
+ Page _currentRoot;
+ bool _isRemoving;
+
+ public NavigationPageRenderer()
+ {
+ AutoPackage = false;
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
+ {
+ base.OnElementChanged(e);
+
+ Debug.WriteLine("Warning, Windows Phone backend does not support NavigationPage, falling back to global navigation.");
+
+ Action init = () =>
+ {
+ Element.PushRequested += PageOnPushed;
+ Element.PopRequested += PageOnPopped;
+ Element.PopToRootRequested += PageOnPoppedToRoot;
+ Element.RemovePageRequested += RemovePageRequested;
+ Element.InsertPageBeforeRequested += ElementOnInsertPageBeforeRequested;
+ Element.PropertyChanged += OnElementPropertyChanged;
+
+ var platform = (Platform)Element.Platform;
+ Element.ContainerArea = new Rectangle(new Point(0, 0), platform.Size);
+
+ platform.SizeChanged += (sender, args) => Element.ContainerArea = new Rectangle(new Point(0, 0), platform.Size);
+
+ List<Page> stack = GetStack();
+ if (stack.Count > 0)
+ UpdateRootPage(stack);
+ else
+ return;
+
+ Device.BeginInvokeOnMainThread(() =>
+ {
+ for (var i = 0; i < stack.Count; i++)
+ PageOnPushed(this, new NavigationRequestedEventArgs(stack[i], false, i != 0));
+ });
+ };
+
+ if (Element.Platform == null)
+ Element.PlatformSet += (sender, args) => init();
+ else
+ init();
+
+ Loaded += (sender, args) => Element.SendAppearing();
+ Unloaded += OnUnloaded;
+ }
+
+ void ElementOnInsertPageBeforeRequested(object sender, NavigationRequestedEventArgs eventArgs)
+ {
+ if (Element.Platform == null)
+ return;
+ var platform = Element.Platform as Platform;
+ if (platform != null)
+ ((INavigation)platform).InsertPageBefore(eventArgs.Page, eventArgs.BeforePage);
+
+ List<Page> stack = GetStack();
+ stack.Insert(stack.IndexOf(eventArgs.BeforePage), eventArgs.Page);
+
+ UpdateRootPage(stack);
+ }
+
+ List<Page> GetStack()
+ {
+ int count = Element.InternalChildren.Count;
+ var stack = new List<Page>(count);
+ for (var i = 0; i < count; i++)
+ stack.Add((Page)Element.InternalChildren[i]);
+
+ return stack;
+ }
+
+ void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName != "Parent" || Element.RealParent != null)
+ return;
+
+ var platform = Element.Platform as Platform;
+
+ if (platform == null)
+ return;
+
+ for (var i = 0; i < Element.LogicalChildren.Count; i++)
+ {
+ var page = Element.LogicalChildren[i] as Page;
+ if (page != null)
+ platform.RemovePage(page, false);
+ }
+ }
+
+ void OnUnloaded(object sender, RoutedEventArgs args)
+ {
+ Element.SendDisappearing();
+ }
+
+ void PageOnPopped(object sender, NavigationRequestedEventArgs eventArg)
+ {
+ if (Element.Platform == null)
+ return;
+ var platform = Element.Platform as Platform;
+ if (platform != null)
+ eventArg.Task = platform.Pop(Element, eventArg.Animated).ContinueWith((t, o) => true, null);
+ }
+
+ void PageOnPoppedToRoot(object sender, NavigationRequestedEventArgs eventArgs)
+ {
+ if (Element.Platform == null)
+ return;
+ var platform = Element.Platform as Platform;
+ if (platform != null)
+ eventArgs.Task = platform.PopToRoot(Element, eventArgs.Animated).ContinueWith((t, o) => true, null);
+ }
+
+ void PageOnPushed(object sender, NavigationRequestedEventArgs e)
+ {
+ if (Element.Platform == null)
+ return;
+ var platform = Element.Platform as Platform;
+ if (platform != null)
+ {
+ if (e.Page == Element.StackCopy.LastOrDefault())
+ e.Page.IgnoresContainerArea = true;
+ e.Task = platform.PushCore(e.Page, Element, e.Animated, e.Realize).ContinueWith((t, o) => true, null);
+ }
+ }
+
+ void RemovePageRequested(object sender, NavigationRequestedEventArgs eventArgs)
+ {
+ if (Element.Platform == null)
+ return;
+ var platform = Element.Platform as Platform;
+ if (platform != null)
+ ((INavigation)platform).RemovePage(eventArgs.Page);
+
+ List<Page> stack = GetStack();
+ stack.Remove(eventArgs.Page);
+ _isRemoving = true;
+ UpdateRootPage(stack);
+ _isRemoving = false;
+ }
+
+ void UpdateRootPage(IReadOnlyList<Page> stack)
+ {
+ Page first = stack.FirstOrDefault();
+ if (first == _currentRoot)
+ return;
+
+ if (Children.Count > 0)
+ {
+ var renderer = Children[0] as IVisualElementRenderer;
+ if (renderer != null)
+ {
+ Children.RemoveAt(0);
+
+ var page = renderer.Element as Page;
+ if (page != null)
+ page.IgnoresContainerArea = false;
+
+ if (!stack.Contains(renderer.Element))
+ Platform.SetRenderer(renderer.Element, null);
+ }
+ }
+
+ _currentRoot = first;
+
+ if (first == null)
+ return;
+
+ first.IgnoresContainerArea = true;
+
+ IVisualElementRenderer firstRenderer = Platform.GetRenderer(first);
+ if (firstRenderer == null)
+ {
+ firstRenderer = Platform.CreateRenderer(first);
+ Platform.SetRenderer(first, firstRenderer);
+ }
+ var uiElement = (UIElement)firstRenderer;
+ var platform = Element.Platform as Platform;
+ Canvas canvas = platform?.GetCanvas();
+
+ //We could be swapping the visible page,
+ //so let's make sure we remove it
+ if (canvas.Children.Contains(uiElement))
+ canvas.Children.Remove(uiElement);
+ Children.Add(uiElement);
+
+ // we removed the previous root page, and the new root page is the one being presented
+ // at this time there's only 1 page now on the stack (the navigationpage with root)
+ // we need to update the platform to set this root page as the visible again
+ bool updateRoot = Element.CurrentPage == first && _isRemoving;
+ if (updateRoot)
+ platform.SetCurrent(Element, false);
+ }
+ }
+} \ No newline at end of file