Install
$ agentstack add skill-davidortinau-maui-skills-maui-shell-navigation ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
.NET MAUI Shell Navigation
Key decisions
ContentTemplate — always use it
Always use ContentTemplate with DataTemplate so pages are created on demand. Using Content directly creates all pages during Shell init, hurting startup time.
Passing data — prefer IQueryAttributable over QueryProperty
IQueryAttributable gives you all parameters in one call and works on ViewModels:
public class AnimalDetailsViewModel : ObservableObject, IQueryAttributable
{
public void ApplyQueryAttributes(IDictionary query)
{
if (query.TryGetValue("id", out var id))
AnimalId = id.ToString();
}
}
For complex objects, use ShellNavigationQueryParameters to avoid serializing:
var parameters = new ShellNavigationQueryParameters
{
{ "animal", selectedAnimal }
};
await Shell.Current.GoToAsync("animaldetails", parameters);
Guarding navigation — async deferral pattern
Use GetDeferral() for async checks (e.g., "save unsaved changes?"):
protected override async void OnNavigating(ShellNavigatingEventArgs args)
{
base.OnNavigating(args);
if (hasUnsavedChanges && args.Source == ShellNavigationSource.Pop)
{
var deferral = args.GetDeferral();
bool discard = await ShowConfirmationDialog();
if (!discard)
args.Cancel();
deferral.Complete();
}
}
Common gotchas
- Duplicate route names —
Routing.RegisterRoutethrowsArgumentException
if a route name is already registered or matches a visual hierarchy route. Every route must be unique across the entire app.
- Relative routes require registration — you cannot
GoToAsync("somepage")
unless somepage was registered with Routing.RegisterRoute. Visual hierarchy pages use absolute // routes instead.
- Pages are created on demand — when using
ContentTemplate, the page
constructor runs only on first navigation. Don't assume pages exist at startup.
- Tab.Stack is read-only — you cannot manipulate the navigation stack directly;
use GoToAsync for all navigation changes.
- GoToAsync is async — always await it — fire-and-forget navigation causes
race conditions and can silently fail: ```csharp // ❌ Fire-and-forget — race conditions Shell.Current.GoToAsync("details");
// ✅ Always await await Shell.Current.GoToAsync("details"); ```
- Route hierarchy matters — absolute routes must match the full path through
the visual hierarchy (//FlyoutItem/Tab/ShellContent). Getting the path wrong produces silent no-ops, not exceptions.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: davidortinau
- Source: davidortinau/maui-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.