Items & Overflow
Items are declared on the page, not on the navigation page — the same shape Page.ToolbarItems
already has, so a page can be moved between hosts without any of it changing.
<ContentPage xmlns:shiny="http://shiny.net/maui/controls" Title="Inbox">
<shiny:ShinyNav.LeftItems> <shiny:NavBarItem Icon="menu" Command="{Binding OpenDrawerCommand}" /> </shiny:ShinyNav.LeftItems>
<shiny:ShinyNav.RightItems> <shiny:NavBarItem Icon="search" Command="{Binding SearchCommand}" /> <shiny:NavBarItem Icon="bell" Badge="3" Command="{Binding AlertsCommand}" /> <shiny:NavBarItem Text="Mark all read" Icon="check" Order="Secondary" Command="{Binding MarkAllCommand}" /> <shiny:NavBarItem IsSeparator="True" Order="Secondary" /> <shiny:NavBarItem Text="Delete all" Icon="trash" Order="Secondary" IsDestructive="True" Command="{Binding DeleteCommand}" /> </shiny:ShinyNav.RightItems></ContentPage>NavBarItem is a ToolbarItem
Section titled “NavBarItem is a ToolbarItem”It derives from ToolbarItem, so everything you already know keeps its meaning:
| Inherited | Meaning |
|---|---|
Text |
the label |
IconImageSource |
a bitmap or font glyph |
Command / CommandParameter |
run on tap |
Clicked |
raised on tap, after the command |
IsEnabled |
a disabled item is dimmed and untappable |
IsDestructive |
drawn in the theme’s error colour |
Order |
Default/Primary on the bar, Secondary in the overflow menu |
Priority |
orders items within their side |
And it adds:
| Added | Meaning |
|---|---|
Icon |
a built-in motion icon name — search, bell, trash… |
IconSource / IconPathData / Motion |
explicit motion artwork, a raw 24×24 SVG path, and which motion it plays |
IconColor |
tints this item’s motion artwork |
Badge / BadgeColor |
a corner badge — "" is a dot, null is nothing |
Display |
Auto (icon when there is one), Icon, Text, IconAndText |
IsVisible |
hides the item without removing it from the collection |
IsSeparator |
a divider — in the menu only |
Tag |
whatever identifies the item to your handler; Text is not unique |
Because both collections are typed IList<ToolbarItem>, a plain <ToolbarItem> drops into either
one unchanged.
Badges
Section titled “Badges”Badge is a NavBarItem property, but a badge is not something you should have to change an item’s
type to get. ShinyNav.Badge and ShinyNav.BadgeColor are the attached form, and they work on
any ToolbarItem — including the plain ones a page already had:
<ContentPage.ToolbarItems> <ToolbarItem Text="Drafts" shiny:ShinyNav.Badge="{Binding DraftCount}" /></ContentPage.ToolbarItems>The rules are the same either way: "" draws a dot, null draws nothing, and BadgeColor
unset follows the theme’s error colour. Both attached properties can also be set on a NavBarItem,
where its own Badge wins while it is non-null — so attaching one never silently overrides what the
item already says.
A badged item that overflows keeps its badge on its menu row, and the overflow button itself draws a dot while anything behind it is badged, so a count does not vanish just because the bar ran out of room. It is a dot rather than a number because the button stands for several items, and summing badges that may not all be numbers would invent a total nobody asked for.
What overflows
Section titled “What overflows”Two rules, in this order:
Order="Secondary"folds an item into that side’s overflow menu, however much room the bar has.- Anything past
MaxVisibleItems(default 3, per side) folds in behind it.
Set MaxVisibleItems="0" (or any value ≤ 0) for no limit, and then only Secondary items overflow.
Each side gets its own overflow button, and a side with nothing to overflow gets none.
OverflowIcon names a motion icon to draw instead of the default three-dot glyph. MenuTemplate
replaces the card’s contents wholesale while the bar keeps the backdrop, the anchoring and the
open/close animation; its binding context is the collection that overflowed.
Open a menu yourself:
ShinyNavigationPage.GetNavBar(page)?.OpenMenu(NavBarSide.Right);Binding to items
Section titled “Binding to items”An attached-property collection has no parent, so nothing would ordinarily hand its items a binding
context and every {Binding} on one would silently resolve against null. ShinyNavigationPage
seeds the page’s binding context onto them as an inherited context, so bindings work and an
explicit BindingContext on an item still wins.
Item properties are bindable, so nothing about the collection has to change for the bar to redraw:
// the bar rebuilds itself off the item's own PropertyChangedalertsItem.Badge = unread == 0 ? null : unread.ToString();
// and the attached form is bindable in exactly the same wayShinyNav.SetBadge(draftsToolbarItem, drafts == 0 ? null : drafts.ToString());Reacting to a tap
Section titled “Reacting to a tap”Three ways, all live at once:
item.Command = new Command(...); // on the itemitem.Clicked += (s, e) => { ... }; // on the itemnav.NavBarItemInvoked += (s, e) => { ... }; // on the navigation page, for any of its barsbar.ItemInvoked += (s, e) => { ... }; // on one barThe bar invokes an item through IMenuItemController.Activate() — the same call a native toolbar
makes — so an item behaves identically whether it was drawn here or by the platform.


