[Core] Added RootPage to NavigationPage (#464)

* d

* removed whitespace

* Using ArgumentNullException

* changes
This commit is contained in:
adrianknight89 2017-02-02 09:35:23 -06:00 коммит произвёл Rui Marinho
Родитель 750b0346cc
Коммит 070f1dcdb5
3 изменённых файлов: 170 добавлений и 22 удалений

Просмотреть файл

@ -14,6 +14,7 @@ namespace Xamarin.Forms.Core.UnitTests
{
NavigationPage nav = new NavigationPage ();
Assert.IsNull(nav.RootPage);
Assert.IsNull (nav.CurrentPage);
Label child = new Label {Text = "Label"};
@ -21,7 +22,9 @@ namespace Xamarin.Forms.Core.UnitTests
await nav.Navigation.PushAsync (childRoot);
Assert.AreSame (childRoot, nav.CurrentPage);
Assert.AreSame(childRoot, nav.RootPage);
Assert.AreSame(childRoot, nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
}
[Test]
@ -40,16 +43,26 @@ namespace Xamarin.Forms.Core.UnitTests
bool fired = false;
nav.Popped += (sender, e) => fired = true;
Assert.AreSame(childRoot, nav.RootPage);
Assert.AreNotSame(childRoot2, nav.RootPage);
Assert.AreNotSame(nav.RootPage, nav.CurrentPage);
var popped = await nav.Navigation.PopAsync ();
Assert.True (fired);
Assert.AreSame (childRoot, nav.CurrentPage);
Assert.AreSame(childRoot, nav.RootPage);
Assert.AreSame(childRoot, nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
Assert.AreEqual (childRoot2, popped);
await nav.PopAsync ();
var last = await nav.Navigation.PopAsync ();
Assert.IsNull (last);
Assert.IsNotNull(nav.RootPage);
Assert.IsNotNull(nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
}
[Test]
@ -57,6 +70,7 @@ namespace Xamarin.Forms.Core.UnitTests
{
NavigationPage nav = new NavigationPage ();
Assert.IsNull(nav.RootPage);
Assert.IsNull (nav.CurrentPage);
Label child = new Label {Text = "Label"};
@ -64,7 +78,9 @@ namespace Xamarin.Forms.Core.UnitTests
await nav.PushAsync (childRoot);
Assert.AreSame (childRoot, nav.CurrentPage);
Assert.AreSame (childRoot, nav.RootPage);
Assert.AreSame(childRoot, nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
}
[Test]
@ -96,10 +112,15 @@ namespace Xamarin.Forms.Core.UnitTests
bool fired = false;
nav.Pushed += (sender, e) => fired = true;
Assert.AreSame(childRoot, nav.RootPage);
Assert.AreSame(childRoot, nav.CurrentPage);
await nav.PushAsync (childRoot);
Assert.False (fired);
Assert.AreEqual (childRoot, nav.CurrentPage);
Assert.AreSame(childRoot, nav.RootPage);
Assert.AreSame(childRoot, nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
}
[Test]
@ -184,7 +205,9 @@ namespace Xamarin.Forms.Core.UnitTests
nav.PopToRootAsync ();
Assert.True (signaled);
Assert.AreEqual (root, nav.CurrentPage);
Assert.AreSame (root, nav.RootPage);
Assert.AreSame(root, nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
}
[Test]
@ -209,7 +232,9 @@ namespace Xamarin.Forms.Core.UnitTests
Assert.AreEqual (2, poppedChildren.Count);
Assert.Contains (child1, poppedChildren);
Assert.Contains (child2, poppedChildren);
Assert.AreEqual (root, nav.CurrentPage);
Assert.AreSame(root, nav.RootPage);
Assert.AreSame(root, nav.CurrentPage);
Assert.AreSame(nav.RootPage, nav.CurrentPage);
}
[Test]
@ -458,6 +483,72 @@ namespace Xamarin.Forms.Core.UnitTests
Assert.False (result);
}
[Test]
public void TestInsertPage()
{
var root = new ContentPage { Title = "Root" };
var newPage = new ContentPage();
var navPage = new NavigationPage(root);
navPage.Navigation.InsertPageBefore(newPage, navPage.RootPage);
Assert.AreSame(newPage, navPage.RootPage);
Assert.AreNotSame(newPage, navPage.CurrentPage);
Assert.AreNotSame(navPage.RootPage, navPage.CurrentPage);
Assert.AreSame(root, navPage.CurrentPage);
Assert.Throws<ArgumentException>(() =>
{
navPage.Navigation.InsertPageBefore(new ContentPage(), new ContentPage());
});
Assert.Throws<ArgumentException>(() =>
{
navPage.Navigation.InsertPageBefore(navPage.RootPage, navPage.CurrentPage);
});
Assert.Throws<ArgumentNullException>(() =>
{
navPage.Navigation.InsertPageBefore(null, navPage.CurrentPage);
});
Assert.Throws<ArgumentNullException>(() =>
{
navPage.Navigation.InsertPageBefore(new ContentPage(), null);
});
}
[Test]
public async void TestRemovePage()
{
var root = new ContentPage { Title = "Root" };
var newPage = new ContentPage();
var navPage = new NavigationPage(root);
await navPage.PushAsync(newPage);
navPage.Navigation.RemovePage(root);
Assert.AreSame(newPage, navPage.RootPage);
Assert.AreSame(newPage, navPage.CurrentPage);
Assert.AreSame(navPage.RootPage, navPage.CurrentPage);
Assert.AreNotSame(root, navPage.CurrentPage);
Assert.Throws<ArgumentException>(() =>
{
navPage.Navigation.RemovePage(root);
});
Assert.Throws<InvalidOperationException>(() =>
{
navPage.Navigation.RemovePage(newPage);
});
Assert.Throws<ArgumentNullException>(() =>
{
navPage.Navigation.RemovePage(null);
});
}
[Test (Description = "CurrentPage should not be set to null when you attempt to pop the last page")]
[Property ("Bugzilla", 28335)]
public async Task CurrentPageNotNullPoppingRoot()

Просмотреть файл

@ -28,7 +28,10 @@ namespace Xamarin.Forms
static readonly BindablePropertyKey CurrentPagePropertyKey = BindableProperty.CreateReadOnly("CurrentPage", typeof(Page), typeof(NavigationPage), null);
public static readonly BindableProperty CurrentPageProperty = CurrentPagePropertyKey.BindableProperty;
static readonly BindablePropertyKey RootPagePropertyKey = BindableProperty.CreateReadOnly(nameof(RootPage), typeof(Page), typeof(NavigationPage), null);
public static readonly BindableProperty RootPageProperty = RootPagePropertyKey.BindableProperty;
public NavigationPage()
{
_platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<NavigationPage>>(() => new PlatformConfigurationRegistry<NavigationPage>(this));
@ -92,6 +95,12 @@ namespace Xamarin.Forms
private set { SetValue(CurrentPagePropertyKey, value); }
}
public Page RootPage
{
get { return (Page)GetValue(RootPageProperty); }
private set { SetValue(RootPagePropertyKey, value); }
}
public static string GetBackButtonTitle(BindableObject page)
{
return (string)page.GetValue(BackButtonTitleProperty);
@ -304,8 +313,14 @@ namespace Xamarin.Forms
void InsertPageBefore(Page page, Page before)
{
if (page == null)
throw new ArgumentNullException($"{nameof(page)} cannot be null.");
if (before == null)
throw new ArgumentNullException($"{nameof(before)} cannot be null.");
if (!PageController.InternalChildren.Contains(before))
throw new ArgumentException("before must be a child of the NavigationPage", "before");
throw new ArgumentException($"{nameof(before)} must be a child of the NavigationPage", nameof(before));
if (PageController.InternalChildren.Contains(page))
throw new ArgumentException("Cannot insert page which is already in the navigation stack");
@ -316,6 +331,9 @@ namespace Xamarin.Forms
int index = PageController.InternalChildren.IndexOf(before);
PageController.InternalChildren.Insert(index, page);
if (index == 0)
RootPage = page;
// Shouldn't be required?
if (Width > 0 && Height > 0)
ForceLayout();
@ -326,15 +344,13 @@ namespace Xamarin.Forms
if (((INavigationPageController)this).StackDepth == 1)
return;
var root = (Page)PageController.InternalChildren.First();
var childrenToRemove = PageController.InternalChildren.ToArray().Where(c => c != root);
foreach (var child in childrenToRemove)
Element[] childrenToRemove = PageController.InternalChildren.Skip(1).ToArray();
foreach (Element child in childrenToRemove)
PageController.InternalChildren.Remove(child);
CurrentPage = root;
CurrentPage = RootPage;
var args = new NavigationRequestedEventArgs(root, animated);
var args = new NavigationRequestedEventArgs(RootPage, animated);
EventHandler<NavigationRequestedEventArgs> requestPopToRoot = PopToRootRequestedInternal;
if (requestPopToRoot != null)
@ -345,8 +361,7 @@ namespace Xamarin.Forms
await args.Task;
}
if (PoppedToRoot != null)
PoppedToRoot(this, new PoppedToRootEventArgs(root, childrenToRemove.OfType<Page>().ToList()));
PoppedToRoot?.Invoke(this, new PoppedToRootEventArgs(RootPage, childrenToRemove.OfType<Page>().ToList()));
}
async Task PushAsyncInner(Page page, bool animated)
@ -367,24 +382,29 @@ namespace Xamarin.Forms
await args.Task;
}
if (Pushed != null)
Pushed(this, args);
Pushed?.Invoke(this, args);
}
void PushPage(Page page)
{
PageController.InternalChildren.Add(page);
if (PageController.InternalChildren.Count == 1)
RootPage = page;
CurrentPage = page;
}
void RemovePage(Page page)
{
if (page == CurrentPage && ((INavigationPageController)this).StackDepth <= 1)
if (page == null)
throw new ArgumentNullException($"{nameof(page)} cannot be null.");
if (page == CurrentPage && CurrentPage == RootPage)
throw new InvalidOperationException("Cannot remove root page when it is also the currently displayed page.");
if (page == CurrentPage)
{
Log.Warning("NavigationPage", "RemovePage called for CurrentPage object. This can result in undesired behavior, consider called PopAsync instead.");
Log.Warning("NavigationPage", "RemovePage called for CurrentPage object. This can result in undesired behavior, consider calling PopAsync instead.");
PopAsync();
return;
}
@ -393,10 +413,11 @@ namespace Xamarin.Forms
throw new ArgumentException("Page to remove must be contained on this Navigation Page");
EventHandler<NavigationRequestedEventArgs> handler = RemovePageRequestedInternal;
if (handler != null)
handler(this, new NavigationRequestedEventArgs(page, true));
handler?.Invoke(this, new NavigationRequestedEventArgs(page, true));
PageController.InternalChildren.Remove(page);
if (RootPage == page)
RootPage = (Page)PageController.InternalChildren.First();
}
void SafePop()

Просмотреть файл

@ -226,6 +226,42 @@
</remarks>
</Docs>
</Member>
<Member MemberName="RootPage">
<MemberSignature Language="C#" Value="public Xamarin.Forms.Page RootPage { get; }" />
<MemberSignature Language="ILAsm" Value=".property instance class Xamarin.Forms.Page RootPage" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>Xamarin.Forms.Page</ReturnType>
</ReturnValue>
<Docs>
<summary>
The <see cref="T:Xamarin.Forms.Page" /> that is the root of the navigation stack.
</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="RootPageProperty">
<MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty RootPageProperty;" />
<MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty RootPageProperty" />
<MemberType>Field</MemberType>
<AssemblyInfo>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>Xamarin.Forms.BindableProperty</ReturnType>
</ReturnValue>
<Docs>
<summary>
Identifies the <see cref="P:Xamarin.Forms.NavigationPage.RootPage" /> property.
</summary>
<remarks>
</remarks>
</Docs>
</Member>
<Member MemberName="GetBackButtonTitle">
<MemberSignature Language="C#" Value="public static string GetBackButtonTitle (Xamarin.Forms.BindableObject page);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig string GetBackButtonTitle(class Xamarin.Forms.BindableObject page) cil managed" />