Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

Commit 83e7c68

Browse files
authored
[Shell] Fix Shell to better handle delayed setting of Items (#11973) fixes #11769
* Fix Shell to better handle delayed setting of Items * Update ShellRenderer.cs * Update ShellUriHandlerTests.cs
1 parent 4024292 commit 83e7c68

File tree

9 files changed

+153
-10
lines changed

9 files changed

+153
-10
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.ObjectModel;
4+
using System.Text;
5+
using Xamarin.Forms.CustomAttributes;
6+
using Xamarin.Forms.Internals;
7+
8+
9+
#if UITEST
10+
using Xamarin.UITest;
11+
using NUnit.Framework;
12+
using Xamarin.Forms.Core.UITests;
13+
#endif
14+
15+
namespace Xamarin.Forms.Controls.Issues
16+
{
17+
[Preserve(AllMembers = true)]
18+
[Issue(IssueTracker.Github, 11769, "[Bug] Shell throws exception when delay adding Shell Content", issueTestNumber: 2)]
19+
#if UITEST
20+
[NUnit.Framework.Category(Core.UITests.UITestCategories.Github10000)]
21+
[NUnit.Framework.Category(UITestCategories.Shell)]
22+
#endif
23+
24+
public class Issue11769_DelayedShellContent : TestShell
25+
{
26+
protected override void Init()
27+
{
28+
Items.Add(new FlyoutItem()
29+
{
30+
Items =
31+
{
32+
new Tab()
33+
}
34+
});
35+
36+
Device.InvokeOnMainThreadAsync(() =>
37+
{
38+
var shellContent = new ShellContent()
39+
{
40+
Content = new ContentPage()
41+
{
42+
Content = new Label() { Text = "Success" }
43+
}
44+
};
45+
46+
Items[0].Items[0].Items.Add(shellContent);
47+
});
48+
}
49+
50+
#if UITEST
51+
[Test]
52+
public void DelayedAddingOfShellContentDoesntCrash()
53+
{
54+
RunningApp.WaitForElement("Success");
55+
}
56+
#endif
57+
}
58+
59+
[Preserve(AllMembers = true)]
60+
[Issue(IssueTracker.Github, 11769, "[Bug] Shell throws exception when delay adding Shell Section", issueTestNumber: 1)]
61+
#if UITEST
62+
[NUnit.Framework.Category(Core.UITests.UITestCategories.Github10000)]
63+
[NUnit.Framework.Category(UITestCategories.Shell)]
64+
#endif
65+
66+
public class Issue11769_DelayedShellSection : TestShell
67+
{
68+
protected override void Init()
69+
{
70+
Items.Add(new FlyoutItem());
71+
Device.InvokeOnMainThreadAsync(() =>
72+
{
73+
var tab = new Tab()
74+
{
75+
Items =
76+
{
77+
new ShellContent()
78+
{
79+
Content = new ContentPage()
80+
{
81+
Content = new Label() { Text = "Success" }
82+
}
83+
}
84+
}
85+
};
86+
87+
Items[0].Items.Add(tab);
88+
});
89+
}
90+
91+
#if UITEST
92+
[Test]
93+
public void DelayedAddingOfShellSectionDoesntCrash()
94+
{
95+
RunningApp.WaitForElement("Success");
96+
}
97+
#endif
98+
}
99+
100+
[Preserve(AllMembers = true)]
101+
[Issue(IssueTracker.Github, 11769, "[Bug] Shell throws exception when delay adding Shell Item", issueTestNumber: 0)]
102+
#if UITEST
103+
[NUnit.Framework.Category(Core.UITests.UITestCategories.Github10000)]
104+
[NUnit.Framework.Category(UITestCategories.Shell)]
105+
#endif
106+
107+
public class Issue11769_DelayedShellItem : TestShell
108+
{
109+
protected override void Init()
110+
{
111+
Device.InvokeOnMainThreadAsync(() =>
112+
{
113+
var page = AddBottomTab("Success");
114+
page.Content = new Label() { Text = "Success" };
115+
});
116+
}
117+
118+
#if UITEST
119+
[Test]
120+
public void DelayedAddingOfShellItemDoesntCrash()
121+
{
122+
RunningApp.WaitForElement("Success");
123+
}
124+
#endif
125+
}
126+
}

Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
</Compile>
2727
<Compile Include="$(MSBuildThisFileDirectory)Issue10744.cs" />
2828
<Compile Include="$(MSBuildThisFileDirectory)Issue10909.cs" />
29+
<Compile Include="$(MSBuildThisFileDirectory)Issue11769.cs" />
2930
<Compile Include="$(MSBuildThisFileDirectory)Issue8613.cs" />
3031
<Compile Include="$(MSBuildThisFileDirectory)Issue9137.cs" />
3132
<Compile Include="$(MSBuildThisFileDirectory)Issue8691.cs" />
@@ -2248,4 +2249,4 @@
22482249
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
22492250
</EmbeddedResource>
22502251
</ItemGroup>
2251-
</Project>
2252+
</Project>

Xamarin.Forms.Core.UnitTests/ShellUriHandlerTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,6 @@ public async Task RelativeNavigationWithRoute()
379379

380380
}
381381

382-
383382
[Test]
384383
public async Task ConvertToStandardFormat()
385384
{

Xamarin.Forms.Core/Shell/Shell.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,7 @@ async void SetCurrentItem()
802802
try
803803
{
804804
var location = CurrentState.Location;
805-
var navRequest = ShellUriHandler.GetNavigationRequest(this, ((ShellNavigationState)location).FullLocation, false);
805+
var navRequest = ShellUriHandler.GetNavigationRequest(this, ((ShellNavigationState)location).FullLocation, false, false);
806806

807807
if (navRequest != null)
808808
{

Xamarin.Forms.Core/Shell/ShellUriHandler.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public static Uri ConvertToStandardFormat(string routeScheme, string routeHost,
7979
return new Uri(uri);
8080
}
8181

82-
internal static NavigationRequest GetNavigationRequest(Shell shell, Uri uri, bool enableRelativeShellRoutes = false)
82+
internal static NavigationRequest GetNavigationRequest(Shell shell, Uri uri, bool enableRelativeShellRoutes = false, bool throwNavigationErrorAsException = true)
8383
{
8484
uri = FormatUri(uri, shell);
8585
// figure out the intent of the Uri
@@ -97,7 +97,12 @@ internal static NavigationRequest GetNavigationRequest(Shell shell, Uri uri, boo
9797

9898

9999
if (possibleRouteMatches.Count == 0)
100-
throw new ArgumentException($"unable to figure out route for: {uri}", nameof(uri));
100+
{
101+
if(throwNavigationErrorAsException)
102+
throw new ArgumentException($"unable to figure out route for: {uri}", nameof(uri));
103+
104+
return null;
105+
}
101106
else if (possibleRouteMatches.Count > 1)
102107
{
103108
string[] matches = new string[possibleRouteMatches.Count];
@@ -109,8 +114,11 @@ internal static NavigationRequest GetNavigationRequest(Shell shell, Uri uri, boo
109114
}
110115

111116
string matchesFound = String.Join(",", matches);
112-
throw new ArgumentException($"Ambiguous routes matched for: {uri} matches found: {matchesFound}", nameof(uri));
113117

118+
if (throwNavigationErrorAsException)
119+
throw new ArgumentException($"Ambiguous routes matched for: {uri} matches found: {matchesFound}", nameof(uri));
120+
121+
return null;
114122
}
115123

116124
var theWinningRoute = possibleRouteMatches[0];

Xamarin.Forms.Platform.UAP/Shell/ShellItemRenderer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ internal void SetShellContext(ShellRenderer context)
9898
internal void NavigateToShellItem(ShellItem newItem, bool animate)
9999
{
100100
UnhookEvents(ShellItem);
101+
102+
if (newItem?.CurrentItem?.CurrentItem == null)
103+
return;
104+
101105
ShellItem = newItem;
102106

103107
if (newItem.CurrentItem == null)

Xamarin.Forms.Platform.UAP/Shell/ShellRenderer.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,9 @@ void OnShellNavigated(object sender, ShellNavigatedEventArgs e)
259259

260260
void UpdateToolBar()
261261
{
262+
if (SelectedItem == null)
263+
return;
264+
262265
if(_shell.Navigation.NavigationStack.Count > 1)
263266
{
264267
IsBackEnabled = true;

Xamarin.Forms.Platform.UAP/Shell/ShellSectionRenderer.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ public ShellSectionRenderer()
4444

4545
void OnShellSectionRendererSizeChanged(object sender, Windows.UI.Xaml.SizeChangedEventArgs e)
4646
{
47-
Page.ContainerArea = new Rectangle(0, 0, e.NewSize.Width, e.NewSize.Height);
47+
if(Page != null)
48+
Page.ContainerArea = new Rectangle(0, 0, e.NewSize.Width, e.NewSize.Height);
4849
}
4950

5051
void OnMenuItemInvoked(Microsoft.UI.Xaml.Controls.NavigationView sender, Microsoft.UI.Xaml.Controls.NavigationViewItemInvokedEventArgs args)

Xamarin.Forms.Platform.iOS/Renderers/ShellRenderer.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ public virtual void SetElementSize(Size size)
109109
public override void ViewDidLayoutSubviews()
110110
{
111111
base.ViewDidLayoutSubviews();
112-
_currentShellItemRenderer.ViewController.View.Frame = View.Bounds;
112+
if(_currentShellItemRenderer != null)
113+
_currentShellItemRenderer.ViewController.View.Frame = View.Bounds;
113114

114115
SetElementSize(new Size(View.Bounds.Width, View.Bounds.Height));
115116
}
@@ -284,7 +285,7 @@ void SetupCurrentShellItem()
284285
{
285286
if (Shell.CurrentItem == null)
286287
{
287-
throw new InvalidOperationException("Shell CurrentItem should not be null");
288+
return;
288289
}
289290
else if (_currentShellItemRenderer == null)
290291
{
@@ -314,4 +315,4 @@ public void Dispose()
314315
}
315316
}
316317
}
317-
}
318+
}

0 commit comments

Comments
 (0)