
Syncfusion Blazor Menu Bar
- 201 installs
- 4 repo stars
- Updated July 28, 2026
- syncfusion/blazor-ui-components-skills
Use syncfusion-blazor-menu-bar for development tasks
About
syncfusion-blazor-menu-bar: A skill for development. This provides functionality for development workflows.
- syncfusion-blazor-menu-bar
Syncfusion Blazor Menu Bar by the numbers
- 201 all-time installs (skills.sh)
- +13 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #1,962 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/blazor-ui-components-skills --skill syncfusion-blazor-menu-barAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 201 |
|---|---|
| repo stars | ★ 4 |
| Last updated | July 28, 2026 |
| Repository | syncfusion/blazor-ui-components-skills ↗ |
What it does
Use syncfusion-blazor-menu-bar for development tasks
Files
Implementing Syncfusion Blazor Menu Bar
When to Use This Skill
Use this skill when you need to:
- Create horizontal or vertical navigation menus in Blazor applications
- Add dropdown submenus with multiple nesting levels
- Display icons in menu items
- Handle user interactions with menu events
- Bind menu items to data sources
- Apply animations and custom styling to menus
- Build professional menu bars for web applications
Component Overview
The Syncfusion Blazor Menu Bar component provides a flexible, feature-rich menu system for navigation. It supports:
- Hierarchical structure: Multiple levels of nested menu items
- Data binding: Self-referential data source mapping
- Events: Comprehensive event handling (Created, OnOpen, OnClose, Opened, Closed, ItemSelected, OnItemRender)
- Styling: Icons, custom CSS, separators, and disabled states
- Animation: Multiple animation effects (SlideDown, ZoomIn, FadeIn, None)
- Orientation: Horizontal (default) or Vertical layout
- Customization: Rich API for dynamic menu management
Documentation and Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Installation and package setup (NuGet packages)
- Prerequisites and system requirements
- Blazor WebAssembly App creation
- Basic menu bar implementation
- Imports and service registration
- Theme stylesheet and script resources
Menu Items and Data Binding
📄 Read: references/menu-items-and-data-binding.md
- MenuItem structure and properties (Text, Url, Separator, Disabled)
- Creating hardcoded menu structures
- Self-referential data source binding
- MenuFieldSettings configuration (ItemId, ParentId, Text, Children)
- Custom MenuItem classes and data models
- Hierarchical menu creation patterns
Events and Interactions
📄 Read: references/events-and-interactions.md
- Available events (Created, OnItemRender, OnOpen, OnClose, Opened, Closed, ItemSelected)
- MenuEvents component setup
- Event handler implementation
- TValue specification requirements
- Capturing selected items and item data
- User interaction patterns
Icons and Styling
📄 Read: references/icons-and-styling.md
- Adding icons with IconCss property
- Icon positioning and placement
- CSS custom icons (content, unicode)
- Separators in menu items
- Custom CSS classes
- Navigation links with Url property
- Disabled menu items
Animation and Orientation
📄 Read: references/animation-and-orientation.md
- MenuAnimationSettings configuration
- Animation effects (SlideDown, ZoomIn, FadeIn, None)
- Duration customization
- Orientation property (Horizontal, Vertical)
- RTL support
- Responsive menu behavior
Advanced Scenarios and Customization
📄 Read: references/advanced-scenarios.md
- ShowItemOnClick property for click-based opening
- Add/Remove menu items dynamically
- Enable/Disable menu items
- Menu templates and custom rendering
- Performance considerations
- Common patterns and best practices
API Reference
📄 Read: references/api-reference.md
- Complete SfMenu component properties and methods
- MenuItem component properties and structure
- MenuAnimationSettings and MenuEffect enums
- Orientation enum (Horizontal, Vertical)
- MenuEvents and MenuEventArgs documentation
- MenuFieldSettings for data binding
- MenuTemplates for custom rendering
- Complete integration example
Quick Start Example
@using Syncfusion.Blazor.Navigations
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="File">
<MenuItems>
<MenuItem Text="Open"></MenuItem>
<MenuItem Text="Save"></MenuItem>
<MenuItem Text="Exit"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="Edit">
<MenuItems>
<MenuItem Text="Cut"></MenuItem>
<MenuItem Text="Copy"></MenuItem>
<MenuItem Text="Paste"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="Help"></MenuItem>
</MenuItems>
</SfMenu>Common Patterns
Pattern 1: Simple Hardcoded Menu
Use direct MenuItem components for small, static menus. This is the simplest approach and requires no data binding setup.
Pattern 2: Data-Bound Menu from List
Use MenuFieldSettings to bind a List<T> to your menu. Perfect for dynamic menus sourced from databases or APIs.
Pattern 3: Self-Referential Data
Map ParentId relationships in flat data to create hierarchical menus. Ideal for category/subcategory structures.
Pattern 4: Event-Driven Menus
Use MenuEvents to respond to user actions (Created, ItemSelected, OnOpen, OnClose). Essential for tracking user navigation.
Pattern 5: Styled and Animated Menus
Combine IconCss, MenuAnimationSettings, and Orientation for visually appealing, professional menus.
Key Properties
| Property | Purpose | Common Values |
|---|---|---|
TValue | Generic type for menu items | MenuItem, custom classes |
Orientation | Menu layout direction | Horizontal (default), Vertical |
ShowItemOnClick | Open submenus on click instead of hover | true, false (default) |
MenuAnimationSettings | Animation configuration | SlideDown, ZoomIn, FadeIn |
MenuFieldSettings | Data binding field mappings | ItemId, Text, ParentId, Children |
MenuEvents | Event handlers | Created, OnOpen, ItemSelected, etc. |
Next Steps
1. Setup: Start with the Getting Started reference for installation 2. Create: Choose a menu structure (hardcoded, data-bound, or hierarchical) 3. Enhance: Add events, styling, and animations as needed 4. Test: Verify menu navigation and interactions work correctly
Advanced Scenarios and Customization
Table of Contents
- Click-Based Menu Opening
- Dynamic Menu Item Management
- Custom Templates
- Menu Item Selection Patterns
- Performance Optimization
- Common Patterns and Best Practices
Click-Based Menu Opening
By default, submenus open on hover. Use ShowItemOnClick to require click-based opening:
Basic Click Opening
<SfMenu TValue="MenuItem" ShowItemOnClick="true">
<MenuItems>
<MenuItem Text="File">
<MenuItems>
<MenuItem Text="New"></MenuItem>
<MenuItem Text="Open"></MenuItem>
<MenuItem Text="Save"></MenuItem>
<MenuItem Text="Exit"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="Edit">
<MenuItems>
<MenuItem Text="Cut"></MenuItem>
<MenuItem Text="Copy"></MenuItem>
<MenuItem Text="Paste"></MenuItem>
</MenuItems>
</MenuItem>
</MenuItems>
</SfMenu>Behavior: Click "File" to open submenu, click again to close
Use Cases for Click Opening
- Touch devices: Better UX for mobile/tablet
- Accessibility: Easier for keyboard navigation
- Desktop apps: Familiar behavior for Windows/Office-style menus
Conditional Click Opening
<SfMenu TValue="MenuItem" ShowItemOnClick="@isClickMode">
<!-- Menu items -->
</SfMenu>
<button @onclick="@(() => isClickMode = !isClickMode)">
Toggle: @(isClickMode ? "Click Mode" : "Hover Mode")
</button>
@code {
private bool isClickMode = false;
}Dynamic Menu Item Management
Adding Menu Items
Add items after menu creation using component reference:
@using Syncfusion.Blazor.Navigations
<button @onclick="AddMenuItem">Add New Item</button>
<button @onclick="RemoveMenuItem">Remove Last Item</button>
<SfMenu Items="@MenuItems" @ref="MenuRef">
<MenuFieldSettings Text="@nameof(MenuItem.Text)" Children="@nameof(MenuItem.SubItems)"></MenuFieldSettings>
</SfMenu>
@code {
private SfMenu<MenuItem> MenuRef;
public class MenuItem
{
public string Text { get; set; }
public List<MenuItem> SubItems { get; set; }
}
public List<MenuItem> MenuItems = new List<MenuItem>
{
new MenuItem { Text = "File", SubItems = new List<MenuItem>
{
new MenuItem { Text = "Open" },
new MenuItem { Text = "Save" }
}},
new MenuItem { Text = "Edit" }
};
private void AddMenuItem()
{
MenuItems.Add(new MenuItem
{
Text = $"Item {MenuItems.Count + 1}",
SubItems = new List<MenuItem>()
});
StateHasChanged();
}
private void RemoveMenuItem()
{
if (MenuItems.Count > 0)
{
MenuItems.RemoveAt(MenuItems.Count - 1);
StateHasChanged();
}
}
}Removing Menu Items
private void RemoveItem(MenuItem item)
{
MenuItems.Remove(item);
StateHasChanged();
}Enabling/Disabling Items
<SfMenu Items="@MenuItems">
<MenuFieldSettings Text="Text" Disabled="IsDisabled" Children="SubItems"></MenuFieldSettings>
</SfMenu>
@code {
public class MenuItem
{
public string Text { get; set; }
public bool IsDisabled { get; set; }
public List<MenuItem> SubItems { get; set; }
}
public List<MenuItem> MenuItems = new List<MenuItem>
{
new MenuItem { Text = "File", IsDisabled = false },
new MenuItem { Text = "Edit", IsDisabled = true },
new MenuItem { Text = "Undo", IsDisabled = @(!canUndo) }
};
private bool canUndo = false;
private void UpdateUndoState()
{
canUndo = true;
StateHasChanged();
}
}Add/Remove on Event
private void OnItemSelected(MenuEventArgs<MenuItem> args)
{
if (args.Item.Text == "Add Report")
{
var newReport = new MenuItem
{
Text = $"Report {DateTime.Now:HH:mm:ss}"
};
MenuItems.Add(newReport);
StateHasChanged();
}
}Custom Templates
Menu Item Template
Customize menu item rendering:
@using Syncfusion.Blazor.Navigations
<SfMenu Items="@MenuItems">
<MenuFieldSettings Text="Text" Children="SubItems"></MenuFieldSettings>
<MenuTemplates TValue="MenuItem">
<Template>
@{
var item = context as MenuItem;
<div style="display: flex; justify-content: space-between; align-items: center;">
<span>@item.Text</span>
@if (item.HasNew)
{
<span style="background: red; color: white; padding: 2px 6px; border-radius: 3px; font-size: 12px;">NEW</span>
}
</div>
}
</Template>
</MenuTemplates>
</SfMenu>
@code {
public class MenuItem
{
public string Text { get; set; }
public bool HasNew { get; set; }
public List<MenuItem> SubItems { get; set; }
}
public List<MenuItem> MenuItems = new List<MenuItem>
{
new MenuItem { Text = "Features", HasNew = true, SubItems = new List<MenuItem>() },
new MenuItem { Text = "Documentation", HasNew = false, SubItems = new List<MenuItem>() }
};
}Complex Template with Icons and Badge
<MenuTemplates TValue="MenuItem">
<Template>
@{
var item = context as MenuItem;
<div class="custom-menu-item">
<i class="@item.IconClass"></i>
<span class="item-text">@item.Text</span>
@if (item.BadgeCount > 0)
{
<span class="badge">@item.BadgeCount</span>
}
</div>
}
</Template>
</MenuTemplates>
<style>
.custom-menu-item {
display: flex;
align-items: center;
gap: 10px;
}
.item-text {
flex: 1;
}
.badge {
background: #ff5722;
color: white;
padding: 2px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
}
</style>Menu Item Selection Patterns
Get Selected Item
private MenuItem selectedItem;
private void OnItemSelected(MenuEventArgs<MenuItem> args)
{
selectedItem = args.Item;
Console.WriteLine($"Selected: {selectedItem.Text}");
}Track Selection History
@page "/menu-history"
@using Syncfusion.Blazor.Navigations
<h3>Selection History</h3>
<ul>
@foreach (var item in selectionHistory.Take(5))
{
<li>@item</li>
}
</ul>
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="Item 1"></MenuItem>
<MenuItem Text="Item 2"></MenuItem>
<MenuItem Text="Item 3"></MenuItem>
</MenuItems>
<MenuEvents TValue="MenuItem" ItemSelected="OnSelectItem"></MenuEvents>
</SfMenu>
@code {
private Stack<string> selectionHistory = new Stack<string>();
private void OnSelectItem(MenuEventArgs<MenuItem> args)
{
selectionHistory.Push(args.Item.Text);
if (selectionHistory.Count > 10)
{
selectionHistory.Pop(); // Keep last 10 items
}
}
}Multi-Selection (Custom Logic)
@page "/menu-multiselect"
<h3>Selected Items (@selectedItems.Count)</h3>
<ul>
@foreach (var item in selectedItems)
{
<li>@item</li>
}
</ul>
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="Item 1"></MenuItem>
<MenuItem Text="Item 2"></MenuItem>
<MenuItem Text="Item 3"></MenuItem>
</MenuItems>
<MenuEvents TValue="MenuItem" ItemSelected="OnSelectMultiple"></MenuEvents>
</SfMenu>
@code {
private HashSet<string> selectedItems = new HashSet<string>();
private void OnSelectMultiple(MenuEventArgs<MenuItem> args)
{
string itemText = args.Item.Text;
// Toggle selection (custom multi-select logic)
if (selectedItems.Contains(itemText))
{
selectedItems.Remove(itemText);
}
else
{
selectedItems.Add(itemText);
}
}
}Performance Optimization
Lazy Loading Submenus
Load submenu data only when parent item opens:
@page "/lazy-loading"
@using Syncfusion.Blazor.Navigations
<SfMenu Items="@MenuItems">
<MenuFieldSettings Text="Text" Children="SubItems"></MenuFieldSettings>
<MenuEvents TValue="MenuItem" OnOpen="OnOpenSubmenu"></MenuEvents>
</SfMenu>
@code {
public class MenuItem
{
public string Text { get; set; }
public List<MenuItem> SubItems { get; set; }
public bool IsLoaded { get; set; }
}
public List<MenuItem> MenuItems = new List<MenuItem>
{
new MenuItem { Text = "Reports", IsLoaded = false, SubItems = new List<MenuItem>() },
new MenuItem { Text = "Analytics", IsLoaded = false, SubItems = new List<MenuItem>() }
};
private async Task OnOpenSubmenu(MenuEventArgs<MenuItem> args)
{
var item = args.Item as MenuItem;
if (!item.IsLoaded && item.SubItems.Count == 0)
{
// Load data on first open
item.SubItems = await LoadSubmenusAsync(item.Text);
item.IsLoaded = true;
}
}
private async Task<List<MenuItem>> LoadSubmenusAsync(string parentName)
{
await Task.Delay(500); // Simulate API call
return new List<MenuItem>
{
new MenuItem { Text = $"{parentName} - Sub1" },
new MenuItem { Text = $"{parentName} - Sub2" }
};
}
}Virtualization for Large Lists
// For very large menus, consider virtualizing the list
// Syncfusion components have built-in virtualization support
private List<MenuItem> GetVirtualizedMenuItems(int startIndex, int count)
{
return allMenuItems.Skip(startIndex).Take(count).ToList();
}Common Patterns and Best Practices
Pattern 1: Breadcrumb-Style Menu
<SfMenu TValue="MenuItem" ShowItemOnClick="true">
<MenuItems>
<MenuItem Text="Dashboard"></MenuItem>
<MenuItem Text="Settings">
<MenuItems>
<MenuItem Text="Profile"></MenuItem>
<MenuItem Text="Security"></MenuItem>
<MenuItem Text="Preferences"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="Help">
<MenuItems>
<MenuItem Text="Documentation"></MenuItem>
<MenuItem Text="Support"></MenuItem>
</MenuItems>
</MenuItem>
</MenuItems>
</SfMenu>Pattern 2: Command Menu (Context Action)
private void OnItemSelected(MenuEventArgs<MenuItem> args)
{
var command = args.Item.Text;
switch (command)
{
case "Save":
SaveDocument();
break;
case "Export":
ExportDocument();
break;
case "Print":
PrintDocument();
break;
}
}Pattern 3: Role-Based Menu Visibility
@using Syncfusion.Blazor.Navigations
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="Public Section"></MenuItem>
@if (userRole == "Admin")
{
<MenuItem Text="Admin Panel">
<MenuItems>
<MenuItem Text="Users"></MenuItem>
<MenuItem Text="Roles"></MenuItem>
</MenuItems>
</MenuItem>
}
@if (userRole != "Guest")
{
<MenuItem Text="Profile"></MenuItem>
}
</MenuItems>
</SfMenu>
@code {
private string userRole = "User"; // From authentication context
}Pattern 4: Search Within Menu
<input type="text" placeholder="Search menu..." @oninput="@FilterMenu" />
<SfMenu Items="@FilteredMenuItems">
<MenuFieldSettings Text="Text" Children="SubItems"></MenuFieldSettings>
</SfMenu>
@code {
private List<MenuItem> allMenuItems;
private List<MenuItem> FilteredMenuItems;
private void FilterMenu(ChangeEventArgs e)
{
string searchTerm = e.Value?.ToString()?.ToLower() ?? "";
FilteredMenuItems = allMenuItems
.Where(item => item.Text.ToLower().Contains(searchTerm))
.ToList();
}
}Pattern 5: Menu with Analytics
private void OnItemSelected(MenuEventArgs<MenuItem> args)
{
// Track menu usage
var analyticsEvent = new
{
EventType = "MenuItemSelected",
ItemText = args.Item.Text,
Timestamp = DateTime.UtcNow,
UserId = GetCurrentUserId()
};
LogAnalytics(analyticsEvent);
}Best Practices
1. Keep menus shallow: Limit nesting to 2-3 levels for usability 2. Logical grouping: Group related items together 3. Consistent naming: Use clear, descriptive item labels 4. Performance: Lazy-load large submenus 5. Accessibility: Ensure keyboard navigation works 6. Mobile testing: Test on various screen sizes 7. Feedback: Provide visual feedback on item hover/selection 8. Documentation: Document custom menu structure for team
Animation and Orientation
Table of Contents
- Menu Animations
- MenuAnimationSettings Configuration
- Animation Effects
- Menu Orientation
- RTL Support
- Responsive Behavior
Menu Animations
Animations enhance user experience by providing visual feedback when opening and closing submenus. The Blazor Menu Bar supports multiple animation effects with configurable duration.
Basic Animation Setup
<SfMenu TValue="MenuItem">
<MenuAnimationSettings Effect="MenuEffect.SlideDown" Duration="800"></MenuAnimationSettings>
<MenuItems>
<MenuItem Text="File">
<MenuItems>
<MenuItem Text="Open"></MenuItem>
<MenuItem Text="Save"></MenuItem>
</MenuItems>
</MenuItem>
</MenuItems>
</SfMenu>Animation Without Effects
Disable animation for faster performance:
<MenuAnimationSettings Effect="MenuEffect.None"></MenuAnimationSettings>MenuAnimationSettings Configuration
The MenuAnimationSettings component controls animation behavior:
<MenuAnimationSettings
Effect="MenuEffect.SlideDown"
Duration="600"
Easing="ease-in-out">
</MenuAnimationSettings>Properties
| Property | Type | Description | Default |
|---|---|---|---|
Effect | MenuEffect enum | Animation effect type | SlideDown |
Duration | double | Animation duration in milliseconds | 400 |
Setting Animations
<SfMenu TValue="MenuItem">
<MenuAnimationSettings Effect="MenuEffect.ZoomIn" Duration="500"></MenuAnimationSettings>
<MenuItems>
<!-- Menu items -->
</MenuItems>
</SfMenu>Animation Effects
1. SlideDown (Default)
Submenu slides down when opening:
<MenuAnimationSettings Effect="MenuEffect.SlideDown" Duration="400"></MenuAnimationSettings>Best for: Traditional menu applications, desktop interfaces
2. ZoomIn
Submenu zooms in from center:
<MenuAnimationSettings Effect="MenuEffect.ZoomIn" Duration="300"></MenuAnimationSettings>Best for: Modern UIs, web applications
3. FadeIn
Submenu fades in smoothly:
<MenuAnimationSettings Effect="MenuEffect.FadeIn" Duration="600"></MenuAnimationSettings>Best for: Subtle, minimalist designs
4. None
No animation, instant appearance:
<MenuAnimationSettings Effect="MenuEffect.None"></MenuAnimationSettings>Best for: Performance-critical applications, accessibility requirements
Choosing Animation Duration
- Fast animations (200-300ms): Creates snappy, responsive feel
- Medium animations (400-600ms): Balanced visual feedback
- Slow animations (800-1000ms): Emphasizes visual transitions
<!-- Fast -->
<MenuAnimationSettings Effect="MenuEffect.SlideDown" Duration="250"></MenuAnimationSettings>
<!-- Medium -->
<MenuAnimationSettings Effect="MenuEffect.ZoomIn" Duration="500"></MenuAnimationSettings>
<!-- Slow -->
<MenuAnimationSettings Effect="MenuEffect.FadeIn" Duration="800"></MenuAnimationSettings>Menu Orientation
Horizontal Orientation (Default)
Menu items display left to right:
<SfMenu TValue="MenuItem" Orientation="Syncfusion.Blazor.Navigations.Orientation.Horizontal">
<MenuItems>
<MenuItem Text="File"></MenuItem>
<MenuItem Text="Edit"></MenuItem>
<MenuItem Text="View"></MenuItem>
<MenuItem Text="Help"></MenuItem>
</MenuItems>
</SfMenu>Layout: [File] [Edit] [View] [Help]
Use Case: Traditional menu bar at top of applications
Vertical Orientation
Menu items stack vertically:
<SfMenu TValue="MenuItem" Orientation="Syncfusion.Blazor.Navigations.Orientation.Vertical">
<MenuItems>
<MenuItem Text="Dashboard"></MenuItem>
<MenuItem Text="Products"></MenuItem>
<MenuItem Text="Reports"></MenuItem>
<MenuItem Text="Settings"></MenuItem>
<MenuItem Text="Logout"></MenuItem>
</MenuItems>
</SfMenu>Layout:
Dashboard
Products
Reports
Settings
LogoutUse Case: Sidebar navigation menus
Vertical Menu with Submenus
<SfMenu TValue="MenuItem" Orientation="Syncfusion.Blazor.Navigations.Orientation.Vertical">
<MenuItems>
<MenuItem Text="Admin">
<MenuItems>
<MenuItem Text="Users"></MenuItem>
<MenuItem Text="Roles"></MenuItem>
<MenuItem Text="Permissions"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="Settings">
<MenuItems>
<MenuItem Text="General"></MenuItem>
<MenuItem Text="Security"></MenuItem>
</MenuItems>
</MenuItem>
</MenuItems>
</SfMenu>Responsive Orientation
Switch orientation based on screen size:
@using Syncfusion.Blazor.Navigations
<SfMenu TValue="MenuItem" Orientation="@currentOrientation">
<MenuItems>
<!-- Menu items -->
</MenuItems>
</SfMenu>
@code {
private Orientation currentOrientation = Orientation.Horizontal;
protected override void OnInitialized()
{
// Check screen size and set orientation
AdjustOrientation();
}
private void AdjustOrientation()
{
// In a real app, use JavaScript interop to detect screen size
// For now, defaulting to horizontal
currentOrientation = Orientation.Horizontal;
}
}RTL Support
Right-to-Left (RTL) support for languages like Arabic, Hebrew, and Urdu:
Enabling RTL
<SfMenu TValue="MenuItem" EnableRtl="true">
<MenuItems>
<MenuItem Text="ملف">
<MenuItems>
<MenuItem Text="فتح"></MenuItem>
<MenuItem Text="حفظ"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="تحرير"></MenuItem>
</MenuItems>
</SfMenu>RTL with Other Properties
<SfMenu TValue="MenuItem"
EnableRtl="true"
Orientation="Syncfusion.Blazor.Navigations.Orientation.Vertical">
<MenuItems>
<!-- RTL vertical menu items -->
</MenuItems>
</SfMenu>Detecting RTL from Application State
@page "/menu-rtl"
@using Syncfusion.Blazor.Navigations
<SfMenu TValue="MenuItem" EnableRtl="@isRtl">
<MenuItems>
<MenuItem Text="@(isRtl ? "ملف" : "File")"></MenuItem>
<MenuItem Text="@(isRtl ? "تحرير" : "Edit")"></MenuItem>
</MenuItems>
</SfMenu>
<button @onclick="ToggleRtl">Toggle RTL</button>
@code {
private bool isRtl = false;
private void ToggleRtl()
{
isRtl = !isRtl;
}
}Responsive Behavior
Mobile Considerations
Menu Bar should adapt to different screen sizes:
<style>
@media (max-width: 768px) {
.e-menu {
width: 100%;
}
.e-menu .e-menu-item {
padding: 10px 15px;
font-size: 14px;
}
}
@media (max-width: 480px) {
.e-menu .e-menu-item {
padding: 8px 10px;
font-size: 12px;
}
.e-menu .e-icons {
display: none; /* Hide icons on very small screens */
}
}
</style>Hamburger Menu Pattern
Convert horizontal menu to vertical with hamburger toggle on mobile:
@page "/responsive-menu"
@using Syncfusion.Blazor.Navigations
<style>
.menu-toggle {
display: none;
background: none;
border: none;
font-size: 24px;
cursor: pointer;
}
@media (max-width: 768px) {
.menu-toggle {
display: block;
}
.e-menu {
display: @(showMenu ? "block" : "none");
width: 100%;
position: absolute;
top: 50px;
left: 0;
background: white;
border: 1px solid #ddd;
}
}
</style>
<button class="menu-toggle" @onclick="@(() => showMenu = !showMenu)">☰</button>
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="Home"></MenuItem>
<MenuItem Text="Products"></MenuItem>
<MenuItem Text="Services"></MenuItem>
<MenuItem Text="Contact"></MenuItem>
</MenuItems>
</SfMenu>
@code {
private bool showMenu = true;
}Mobile-First Approach
<SfMenu TValue="MenuItem"
Orientation="@GetOrientation()"
@ref="MenuRef">
<MenuAnimationSettings Effect="MenuEffect.SlideDown" Duration="300"></MenuAnimationSettings>
<MenuItems>
<!-- Menu items -->
</MenuItems>
</SfMenu>
@code {
private SfMenu<MenuItem> MenuRef;
private int screenWidth = 0;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// Get screen width via JavaScript interop
screenWidth = 768; // Default
}
}
private Orientation GetOrientation()
{
return screenWidth < 768
? Orientation.Vertical
: Orientation.Horizontal;
}
}Best Practices
1. Animation Performance: Disable animations on low-end devices or performance-critical applications 2. Duration Consistency: Keep animation durations consistent across your application 3. Orientation Choice: Use vertical for sidebars, horizontal for top navigation 4. Mobile Testing: Test menu behavior on various screen sizes 5. RTL Completeness: Ensure all content is properly translated for RTL languages 6. Accessibility: Verify animations don't cause issues for users with motion sensitivity 7. Performance: Profile animation impact on slower devices
Syncfusion Blazor Menu Bar API Reference
Overview
The Syncfusion Blazor Menu Bar (SfMenu) component provides a flexible, hierarchical navigation menu system with support for data binding, events, animations, and extensive customization options. It enables developers to create horizontal and vertical menus with nested submenus, icons, and dynamic item management.
---
SfMenu Component
Properties
| Property | Type | Default | Accepted Values | Description | Reference |
|---|---|---|---|---|---|
TValue | Generic Type | - | Any | Generic type parameter for menu items | View |
Items | IEnumerable<TValue> | null | List of items | Data source for the menu items | View |
Orientation | Orientation | Horizontal | Horizontal, Vertical | Menu layout direction | Orientation Enum |
ShowItemOnClick | bool | false | true, false | Open submenus on click instead of hover | View |
EnableRtl | bool | false | true, false | Enable right-to-left (RTL) layout for Arabic/Hebrew languages | View |
MenuAnimationSettings | MenuAnimationSettings | - | - | Animation configuration for submenu display | MenuAnimationSettings |
CssClass | string | null | CSS class names | Custom CSS classes to apply to the menu | View |
HtmlAttributes | Dictionary<string, object> | null | - | Additional HTML attributes for the component | View |
Methods
| Method | Parameters | Return Type | Description | Reference |
|---|---|---|---|---|
Add | TValue item | void | Add a new menu item to the menu at runtime | See Dynamic Item Management |
Remove | TValue item | void | Remove a menu item from the menu | See Dynamic Item Management |
RefreshAsync | (none) | Task | Refresh the menu component and re-render all items | View |
Example - Dynamic Item Management:
<SfMenu Items="@MenuItems" @ref="MenuRef">
<MenuFieldSettings Text="Text" Children="SubItems"></MenuFieldSettings>
</SfMenu>
@code {
SfMenu<MenuItem> MenuRef;
// Add item
private void AddItem()
{
MenuRef.Items.Add(new MenuItem { Text = "New Item" });
}
// Remove item
private void RemoveItem(MenuItem item)
{
MenuRef.Items.Remove(item);
}
}---
MenuItem Component
Properties
| Property | Type | Default | Accepted Values | Description | Reference |
|---|---|---|---|---|---|
Text | string | null | Any string | Display text for the menu item | View |
IconCss | string | null | CSS class names | Icon CSS class to display before/after the text | Icons Reference |
Url | string | null | Valid URL path | Navigation URL for the menu item | View |
Separator | bool | false | true, false | Display a horizontal separator line | View |
Disabled | bool | false | true, false | Disable the menu item from interaction | View |
Items | IEnumerable<MenuItem> | null | List of MenuItem | Child menu items (submenus) | View |
Example - MenuItem Usage:
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="File" IconCss="e-icons e-file">
<MenuItems>
<MenuItem Text="Open" IconCss="e-icons e-open"></MenuItem>
<MenuItem Text="Save" IconCss="e-icons e-save"></MenuItem>
<MenuItem Separator="true"></MenuItem>
<MenuItem Text="Exit"></MenuItem>
</MenuItems>
</MenuItem>
</MenuItems>
</SfMenu>---
MenuFieldSettings Component
Properties
| Property | Type | Default | Accepted Values | Description | Reference |
|---|---|---|---|---|---|
ItemId | string | "Id" | Property name | Maps the unique identifier field of data source | Data Binding Reference |
Text | string | "Text" | Property name | Maps the text field of data source for display | View |
ParentId | string | "ParentId" | Property name | Maps the parent ID field for hierarchical data | View |
Children | string | "Children" | Property name | Maps the child collection property name | View |
Url | string | "Url" | Property name | Maps the URL navigation property | View |
IconCss | string | "IconCss" | Property name | Maps the icon CSS class property | View |
Disabled | string | "Disabled" | Property name | Maps the disabled state property | View |
Separator | string | "Separator" | Property name | Maps the separator indicator property | View |
Example - Self-Referential Data Binding:
<SfMenu Items="@MenuItems">
<MenuFieldSettings ItemId="Id" Text="Text" ParentId="ParentId"></MenuFieldSettings>
</SfMenu>
@code {
public class MenuItem
{
public string Id { get; set; }
public string Text { get; set; }
public string ParentId { get; set; }
}
public List<MenuItem> MenuItems = new List<MenuItem>
{
new MenuItem { Id = "1", Text = "File", ParentId = null },
new MenuItem { Id = "2", Text = "Open", ParentId = "1" },
new MenuItem { Id = "3", Text = "Save", ParentId = "1" }
};
}---
MenuAnimationSettings Component
Properties
| Property | Type | Default | Accepted Values | Description | Reference |
|---|---|---|---|---|---|
Effect | MenuEffect | SlideDown | None, SlideDown, ZoomIn, FadeIn | Animation effect when opening/closing submenus | MenuEffect Enum |
Duration | double | 400 | 0-∞ | Animation duration in milliseconds | View |
Example - Animation Configuration:
<SfMenu TValue="MenuItem">
<MenuAnimationSettings Effect="MenuEffect.ZoomIn" Duration="600"></MenuAnimationSettings>
<MenuItems>
<!-- Menu items -->
</MenuItems>
</SfMenu>---
MenuEffect Enum
Fields
| Field | Description | Value |
|---|---|---|
None | No animation effect; menu appears instantly | 0 |
SlideDown | Menu slides down when opening | 1 |
ZoomIn | Menu zooms in from center | 2 |
FadeIn | Menu fades in gradually | 3 |
---
Orientation Enum
Fields
| Field | Description | Value |
|---|---|---|
Horizontal | Menu items display horizontally (left to right) | 0 |
Vertical | Menu items stack vertically (top to bottom) | 1 |
Example - Orientation Usage:
<!-- Horizontal (default) -->
<SfMenu TValue="MenuItem" Orientation="Orientation.Horizontal">
<!-- Menu items -->
</SfMenu>
<!-- Vertical -->
<SfMenu TValue="MenuItem" Orientation="Orientation.Vertical">
<!-- Menu items -->
</SfMenu>---
MenuEvents Component
Properties
| Property | Type | Description | Reference |
|---|---|---|---|
Created | EventCallback | Fires after the Menu Bar is successfully created and initialized | View |
OnItemRender | EventCallback<MenuEventArgs<TValue>> | Fires while rendering each menu item; can be used to customize items | View |
OnOpen | EventCallback<MenuEventArgs<TValue>> | Fires before opening a submenu; can be cancelled | View |
OnClose | EventCallback<MenuEventArgs<TValue>> | Fires before closing a submenu; can be cancelled | View |
Opened | EventCallback<MenuEventArgs<TValue>> | Fires after a submenu has been successfully opened | View |
Closed | EventCallback<MenuEventArgs<TValue>> | Fires after a submenu has been successfully closed | View |
ItemSelected | EventCallback<MenuEventArgs<TValue>> | Fires when a menu item is selected/clicked by the user | View |
Example - Event Handling:
<SfMenu TValue="MenuItem">
<MenuItems>
<!-- Menu items -->
</MenuItems>
<MenuEvents TValue="MenuItem"
Created="OnCreated"
ItemSelected="OnItemSelected"
OnOpen="OnOpen"
Opened="OnOpened"
OnClose="OnClose"
Closed="OnClosed">
</MenuEvents>
</SfMenu>
@code {
private void OnCreated()
{
Console.WriteLine("Menu created");
}
private void OnItemSelected(MenuEventArgs<MenuItem> args)
{
Console.WriteLine($"Selected: {args.Item.Text}");
}
private void OnOpen(MenuEventArgs<MenuItem> args)
{
// args.Cancel = true; // Prevent opening if needed
Console.WriteLine($"Opening: {args.Item.Text}");
}
private void OnOpened(MenuEventArgs<MenuItem> args)
{
Console.WriteLine($"Opened: {args.Item.Text}");
}
private void OnClose(MenuEventArgs<MenuItem> args)
{
Console.WriteLine($"Closing: {args.Item.Text}");
}
private void OnClosed(MenuEventArgs<MenuItem> args)
{
Console.WriteLine($"Closed: {args.Item.Text}");
}
}---
MenuEventArgs Component
Properties
| Property | Type | Description | Reference |
|---|---|---|---|
Item | TValue | The menu item that triggered the event | View |
Cancel | bool | Set to true to cancel the operation (valid for OnOpen and OnClose events) | View |
Example - Using MenuEventArgs:
private void OnOpen(MenuEventArgs<MenuItem> args)
{
var selectedItem = args.Item;
var itemText = selectedItem.Text;
// Prevent opening if item is locked
if (selectedItem.Disabled)
{
args.Cancel = true;
}
}---
MenuTemplates Component
Properties
| Property | Type | Description | Reference |
|---|---|---|---|
Template | RenderFragment<TValue> | Custom template for rendering menu items | View |
Example - Custom Menu Item Template:
<SfMenu Items="@MenuItems">
<MenuFieldSettings Text="Text" Children="SubItems"></MenuFieldSettings>
<MenuTemplates TValue="MenuItem">
<Template>
@{
var item = context as MenuItem;
<div style="display: flex; justify-content: space-between; align-items: center;">
<span>@item.Text</span>
@if (item.HasBadge)
{
<span style="background: red; color: white; padding: 2px 6px; border-radius: 3px;">
@item.BadgeCount
</span>
}
</div>
}
</Template>
</MenuTemplates>
</SfMenu>---
Complete Integration Example
@page "/menu-example"
@using Syncfusion.Blazor.Navigations
<SfMenu TValue="MenuItemModel"
Items="@MenuItems"
Orientation="Orientation.Horizontal"
ShowItemOnClick="false"
EnableRtl="false"
@ref="MenuRef">
<MenuAnimationSettings Effect="MenuEffect.SlideDown" Duration="400"></MenuAnimationSettings>
<MenuFieldSettings
ItemId="Id"
Text="Text"
IconCss="IconClass"
ParentId="ParentId"
Children="SubItems">
</MenuFieldSettings>
<MenuEvents TValue="MenuItemModel"
Created="OnCreated"
OnItemRender="OnItemRender"
OnOpen="OnOpen"
OnClose="OnClose"
Opened="OnOpened"
Closed="OnClosed"
ItemSelected="OnItemSelected">
</MenuEvents>
</SfMenu>
@code {
SfMenu<MenuItemModel> MenuRef;
public class MenuItemModel
{
public string Id { get; set; }
public string Text { get; set; }
public string IconClass { get; set; }
public string ParentId { get; set; }
public List<MenuItemModel> SubItems { get; set; }
}
public List<MenuItemModel> MenuItems = new List<MenuItemModel>
{
new MenuItemModel
{
Id = "1",
Text = "File",
IconClass = "e-icons e-file",
ParentId = null,
SubItems = new List<MenuItemModel>
{
new MenuItemModel { Id = "2", Text = "Open", ParentId = "1" },
new MenuItemModel { Id = "3", Text = "Save", ParentId = "1" }
}
}
};
private void OnCreated()
{
Console.WriteLine("Menu initialized");
}
private void OnItemRender(MenuEventArgs<MenuItemModel> args)
{
Console.WriteLine($"Rendering: {args.Item.Text}");
}
private void OnOpen(MenuEventArgs<MenuItemModel> args)
{
Console.WriteLine($"Opening: {args.Item.Text}");
}
private void OnClose(MenuEventArgs<MenuItemModel> args)
{
Console.WriteLine($"Closing: {args.Item.Text}");
}
private void OnOpened(MenuEventArgs<MenuItemModel> args)
{
Console.WriteLine($"Opened: {args.Item.Text}");
}
private void OnClosed(MenuEventArgs<MenuItemModel> args)
{
Console.WriteLine($"Closed: {args.Item.Text}");
}
private void OnItemSelected(MenuEventArgs<MenuItemModel> args)
{
Console.WriteLine($"Selected: {args.Item.Text}");
}
}---
Additional Resources
- Getting Started Reference
- Menu Items and Data Binding
- Events and Interactions
- Icons and Styling
- Animation and Orientation
- Advanced Scenarios
---
Notes
- TValue Required: The
TValueparameter must be specified for all event handlers inMenuEvents - MenuFieldSettings: Use custom property mappings when your data model doesn't follow the default naming conventions
- Performance: For large menu structures, consider lazy-loading submenus with the
OnOpenevent - Accessibility: Ensure keyboard navigation works by properly structuring menu hierarchy
- RTL Support: The
EnableRtlproperty automatically mirrors the menu layout for RTL languages
Events and Interactions
Table of Contents
- MenuEvents Component Overview
- Available Events
- Event Handler Implementation
- Capturing Event Data
- Event Handling Patterns
MenuEvents Component Overview
The MenuEvents component provides event handlers for user interactions with the Menu Bar. All events must be defined within a single MenuEvents component.
Basic Syntax
<SfMenu TValue="MenuItem">
<MenuItems>
<!-- Menu items here -->
</MenuItems>
<MenuEvents TValue="MenuItem"
Created="OnCreated"
OnItemRender="OnItemRender"
OnOpen="OnOpen"
OnClose="OnClose"
Opened="OnOpened"
Closed="OnClosed"
ItemSelected="OnItemSelected">
</MenuEvents>
</SfMenu>
@code {
private void OnCreated() { }
private void OnItemRender() { }
private void OnOpen() { }
private void OnClose() { }
private void OnOpened() { }
private void OnClosed() { }
private void OnItemSelected(MenuEventArgs<MenuItem> args) { }
}Important: TValue Specification
When using events, the TValue parameter must be specified in the MenuEvents component and match the SfMenu TValue:
<!-- ❌ Incorrect: Missing TValue in MenuEvents -->
<MenuEvents Created="OnCreated"></MenuEvents>
<!-- ✅ Correct: TValue specified -->
<MenuEvents TValue="MenuItem" Created="OnCreated"></MenuEvents>Available Events
1. Created Event
Triggered once the Menu Bar has been successfully created and initialized.
Use Case: Initialize menu state, load data, or perform setup operations
<MenuEvents TValue="MenuItem" Created="OnMenuCreated"></MenuEvents>
@code {
private void OnMenuCreated()
{
Console.WriteLine("Menu Bar created successfully");
// Load initial data, set default selections, etc.
}
}2. OnItemRender Event
Triggered while rendering each individual menu item.
Use Case: Customize item appearance, apply conditional styling, or modify item properties before rendering
<MenuEvents TValue="MenuItem" OnItemRender="OnRenderItem"></MenuEvents>
@code {
private void OnRenderItem(MenuEventArgs<MenuItem> args)
{
// Customize items based on conditions
if (args.Item.Text == "Premium")
{
args.Item.IconCss = "e-icons e-star";
}
}
}3. OnOpen Event
Triggered before opening a submenu.
Use Case: Prevent certain submenus from opening, load data on demand, or validate user permissions
<MenuEvents TValue="MenuItem" OnOpen="OnOpenSubmenu"></MenuEvents>
@code {
private void OnOpenSubmenu(MenuEventArgs<MenuItem> args)
{
Console.WriteLine($"Opening: {args.Item.Text}");
// Check permissions, load submenu data, etc.
// To prevent opening, set: args.Cancel = true;
}
}4. OnClose Event
Triggered before closing a submenu.
Use Case: Save unsaved changes, validate selections, or clean up resources
<MenuEvents TValue="MenuItem" OnClose="OnCloseSubmenu"></MenuEvents>
@code {
private void OnCloseSubmenu(MenuEventArgs<MenuItem> args)
{
Console.WriteLine($"Closing: {args.Item.Text}");
// Save state, clean up, etc.
}
}5. Opened Event
Triggered after a submenu has been successfully opened.
Use Case: Focus elements, trigger animations, or perform post-open operations
<MenuEvents TValue="MenuItem" Opened="OnSubmenuOpened"></MenuEvents>
@code {
private void OnSubmenuOpened(MenuEventArgs<MenuItem> args)
{
Console.WriteLine($"Submenu opened: {args.Item.Text}");
// Perform animations or updates after opening
}
}6. Closed Event
Triggered after a submenu has been successfully closed.
Use Case: Clean up resources, update UI state, or perform post-close operations
<MenuEvents TValue="MenuItem" Closed="OnSubmenuClosed"></MenuEvents>
@code {
private void OnSubmenuClosed(MenuEventArgs<MenuItem> args)
{
Console.WriteLine($"Submenu closed: {args.Item.Text}");
}
}7. ItemSelected Event
Triggered when a menu item is selected/clicked by the user.
Use Case: Navigate to pages, execute commands, or respond to user selections
<MenuEvents TValue="MenuItem" ItemSelected="OnSelectItem"></MenuEvents>
@code {
private void OnSelectItem(MenuEventArgs<MenuItem> args)
{
string selectedText = args.Item.Text;
string selectedUrl = args.Item.Url;
Console.WriteLine($"Selected: {selectedText}");
// Handle navigation, command execution, etc.
}
}Event Handler Implementation
Basic Event Handler
@code {
private void OnItemSelected(MenuEventArgs<MenuItem> args)
{
var item = args.Item;
Console.WriteLine($"Item: {item.Text}");
}
}Async Event Handler
@code {
private async Task OnItemSelectedAsync(MenuEventArgs<MenuItem> args)
{
var item = args.Item;
await ProcessSelection(item);
}
private async Task ProcessSelection(MenuItem item)
{
// Async operations
await Task.Delay(100);
}
}Event Handler with State Updates
@page "/menu-events"
@using Syncfusion.Blazor.Navigations
<div>
<p>Selected Item: @selectedItemText</p>
<p>Event Triggered: @lastEventName</p>
</div>
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="File">
<MenuItems>
<MenuItem Text="Open"></MenuItem>
<MenuItem Text="Save"></MenuItem>
<MenuItem Text="Exit"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="Edit">
<MenuItems>
<MenuItem Text="Cut"></MenuItem>
<MenuItem Text="Copy"></MenuItem>
</MenuItems>
</MenuItem>
</MenuItems>
<MenuEvents TValue="MenuItem"
ItemSelected="OnItemSelected"
OnOpen="OnOpen"
Closed="OnClosed">
</MenuEvents>
</SfMenu>
@code {
private string selectedItemText = "None";
private string lastEventName = "Waiting for event...";
private void OnItemSelected(MenuEventArgs<MenuItem> args)
{
selectedItemText = args.Item.Text;
lastEventName = "ItemSelected";
}
private void OnOpen(MenuEventArgs<MenuItem> args)
{
lastEventName = $"Opening: {args.Item.Text}";
}
private void OnClosed(MenuEventArgs<MenuItem> args)
{
lastEventName = $"Closed: {args.Item.Text}";
}
}Capturing Event Data
MenuEventArgs Properties
The MenuEventArgs<TValue> contains:
| Property | Type | Description |
|---|---|---|
Item | TValue | The menu item that triggered the event |
Cancel | bool | Set to true to cancel the operation (OnOpen, OnClose) |
Accessing Item Information
private void OnItemSelected(MenuEventArgs<MenuItem> args)
{
// Access item properties
string text = args.Item.Text;
string iconCss = args.Item.IconCss;
string url = args.Item.Url;
bool isDisabled = args.Item.Disabled;
bool isSeparator = args.Item.Separator;
}Canceling Operations
private void OnOpen(MenuEventArgs<MenuItem> args)
{
// Prevent "Admin" submenu from opening
if (args.Item.Text == "Admin")
{
args.Cancel = true;
Console.WriteLine("Admin menu is locked");
}
}Event Handling Patterns
Pattern 1: Navigation on Selection
private void OnItemSelected(MenuEventArgs<MenuItem> args)
{
if (!string.IsNullOrEmpty(args.Item.Url))
{
// Navigation handled by Url property
// Or programmatically:
NavigationManager.NavigateTo(args.Item.Url);
}
}Pattern 2: Dynamic Menu Loading
private async Task OnOpen(MenuEventArgs<MenuItem> args)
{
if (args.Item.Text == "Reports" && !isReportsLoaded)
{
// Load reports dynamically on first open
await LoadReports();
isReportsLoaded = true;
}
}
private async Task LoadReports()
{
// Fetch data from API
await Task.Delay(500);
}Pattern 3: User Feedback
private string toastMessage = "";
private bool showToast = false;
private void OnItemSelected(MenuEventArgs<MenuItem> args)
{
toastMessage = $"You selected: {args.Item.Text}";
showToast = true;
// Auto-hide toast after 3 seconds
Task.Delay(3000).ContinueWith(_ =>
{
showToast = false;
StateHasChanged();
});
}Pattern 4: Permission-Based Menu Access
private void OnOpen(MenuEventArgs<MenuItem> args)
{
var userRole = GetUserRole();
var allowedItems = new[] { "Public", "User" };
if (!allowedItems.Contains(args.Item.Text) && userRole != "Admin")
{
args.Cancel = true;
Console.WriteLine("Access denied");
}
}
private string GetUserRole()
{
// Fetch from authentication context
return "User";
}Pattern 5: Multi-Event Tracking
<div>
<h3>Event Log</h3>
@foreach (var entry in eventLog)
{
<div>@entry</div>
}
</div>
<SfMenu TValue="MenuItem">
<!-- Menu items -->
<MenuEvents TValue="MenuItem"
Created="LogEvent_Created"
OnOpen="LogEvent_OnOpen"
OnClose="LogEvent_OnClose"
ItemSelected="LogEvent_ItemSelected">
</MenuEvents>
</SfMenu>
@code {
private List<string> eventLog = new();
private void LogEvent_Created()
{
AddLog("Menu created");
}
private void LogEvent_OnOpen(MenuEventArgs<MenuItem> args)
{
AddLog($"Opening: {args.Item.Text}");
}
private void LogEvent_OnClose(MenuEventArgs<MenuItem> args)
{
AddLog($"Closing: {args.Item.Text}");
}
private void LogEvent_ItemSelected(MenuEventArgs<MenuItem> args)
{
AddLog($"Selected: {args.Item.Text}");
}
private void AddLog(string message)
{
eventLog.Insert(0, $"[{DateTime.Now:HH:mm:ss}] {message}");
if (eventLog.Count > 10) eventLog.RemoveAt(10); // Keep last 10
}
}Best Practices
1. Always specify TValue: Ensure MenuEvents has TValue matching SfMenu 2. Avoid expensive operations: Don't perform heavy computations in OnItemRender (fires frequently) 3. Use async when needed: Use async Task for operations that might take time 4. Cancel carefully: Only cancel OnOpen/OnClose when necessary for security/validation 5. Manage state: Call StateHasChanged() if event handlers modify component state 6. Error handling: Wrap event handlers in try-catch for production code
Getting Started with Blazor Menu Bar
Table of Contents
- System Requirements
- Creating a Blazor App
- Installing NuGet Packages
- Configuring Imports and Services
- Adding Theme Resources
- Creating Your First Menu
System Requirements
Before you begin, ensure your system meets these requirements:
- Visual Studio 2022 or later
- Visual Studio Code with .NET extensions
- .NET SDK 7.0 or later
- A modern web browser
Refer to official System requirements for Blazor components for complete details.
Creating a Blazor App
Using Visual Studio
1. Open Visual Studio 2022 2. Click Create a new project 3. Select Blazor WebAssembly App template 4. Configure project name and location 5. Choose ASP.NET Core Hosted or Standalone
Alternatively, use the Syncfusion Blazor Extension for Visual Studio to create a project with pre-configured Syncfusion packages.
Using Visual Studio Code
Create a Blazor WebAssembly App with the following terminal command:
dotnet new blazorwasm -o BlazorMenuBarApp
cd BlazorMenuBarAppUsing .NET CLI
dotnet new blazorwasm -o BlazorMenuBarApp
cd BlazorMenuBarAppInstalling NuGet Packages
You need two essential packages for Menu Bar functionality:
Via Package Manager Console (Visual Studio)
Install-Package Syncfusion.Blazor.Navigations
Install-Package Syncfusion.Blazor.ThemesVia .NET CLI
dotnet add package Syncfusion.Blazor.Navigations
dotnet add package Syncfusion.Blazor.Themes
dotnet restorePackage Details
- Syncfusion.Blazor.Navigations: Contains Menu Bar, Accordion, Tabs, Sidebar, and other navigation components
- Syncfusion.Blazor.Themes: Provides CSS theme files (bootstrap5, material, fabric, tailwind, etc.)
All Syncfusion Blazor packages are available on nuget.org
Configuring Imports and Services
Step 1: Update _Imports.razor
Open ~/_Imports.razor and add the required namespaces:
@using Syncfusion.Blazor
@using Syncfusion.Blazor.NavigationsStep 2: Register Syncfusion Service
Open ~/Program.cs and register the Syncfusion Blazor service:
using Syncfusion.Blazor;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
// Register Syncfusion Blazor Service
builder.Services.AddSyncfusionBlazor();
await builder.Build().RunAsync();Adding Theme Resources
Include Stylesheet and Script
Open ~/index.html and add the theme stylesheet and script references in the <head> section:
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Blazor Menu Bar</title>
<!-- Syncfusion Blazor Bootstrap5 Theme -->
<link href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />
<!-- Syncfusion Blazor Core Script -->
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>
<link href="app.css" rel="stylesheet" />
</head>Available Theme Options
Syncfusion provides multiple themes. Choose one by changing the stylesheet:
bootstrap5.css- Modern Bootstrap 5 themematerial.css- Material Design themefabric.css- Microsoft Fabric themetailwind.css- Tailwind CSS themefluent.css- Microsoft Fluent UI theme
For more information, see Blazor Themes documentation.
Creating Your First Menu
Basic Menu Structure
Add the following code to your ~/Pages/Index.razor file:
@page "/"
@using Syncfusion.Blazor.Navigations
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="File">
<MenuItems>
<MenuItem Text="Open"></MenuItem>
<MenuItem Text="Save"></MenuItem>
<MenuItem Separator="true"></MenuItem>
<MenuItem Text="Exit"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="Edit">
<MenuItems>
<MenuItem Text="Cut"></MenuItem>
<MenuItem Text="Copy"></MenuItem>
<MenuItem Text="Paste"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="View">
<MenuItems>
<MenuItem Text="Toolbars"></MenuItem>
<MenuItem Text="Zoom"></MenuItem>
<MenuItem Text="Full Screen"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="Help"></MenuItem>
</MenuItems>
</SfMenu>Key Components
- `SfMenu`: Main container component with
TValuespecifying the data type - `MenuItems`: Container for menu item collection
- `MenuItem`: Individual menu item with
Textproperty - Nested `MenuItems`: Submenus under parent MenuItem
Understanding TValue
The TValue property specifies the data type for menu items. For simple menus, use the built-in MenuItem class. For complex scenarios with data binding, use your custom class.
Verification
Run your application:
dotnet runNavigate to https://localhost:xxxx in your browser. You should see a horizontal menu bar with File, Edit, View, and Help items. Hover over items with submenus to see the dropdown appear.
Next Steps
1. Add Icons: Use IconCss property to display icons 2. Handle Events: Implement MenuEvents to respond to user interactions 3. Bind Data: Use MenuFieldSettings for dynamic menu creation 4. Customize Appearance: Apply custom CSS and animations 5. Advanced Scenarios: Explore multi-level nesting and templates
Troubleshooting
Menu not appearing?
- Verify NuGet packages are installed:
dotnet restore - Check that Syncfusion service is registered in
Program.cs - Ensure theme stylesheet is linked in
index.html - Verify namespaces are imported in
_Imports.razor
Styling issues?
- Confirm the correct theme CSS is referenced
- Check for conflicting CSS rules
- Inspect browser developer tools for theme file loading
Build errors?
- Ensure all NuGet packages have matching versions
- Clean and rebuild:
dotnet clean && dotnet build - Update to latest package versions if needed
Icons and Styling
Table of Contents
- Adding Icons to Menu Items
- Icon Positioning
- Custom CSS Icons
- Separators and Disabled Items
- Navigation Links
- CSS Customization
Adding Icons to Menu Items
Using IconCss Property
The IconCss property adds an icon to a menu item by applying CSS classes:
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="File" IconCss="e-icons e-file">
<MenuItems>
<MenuItem Text="Open" IconCss="e-icons e-open"></MenuItem>
<MenuItem Text="Save" IconCss="e-icons e-save"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="Edit" IconCss="e-icons e-edit">
<MenuItems>
<MenuItem Text="Cut" IconCss="e-icons e-cut"></MenuItem>
<MenuItem Text="Copy" IconCss="e-icons e-copy"></MenuItem>
<MenuItem Text="Paste" IconCss="e-icons e-paste"></MenuItem>
</MenuItems>
</MenuItem>
</MenuItems>
</SfMenu>Syncfusion Icon Library
Syncfusion provides a built-in icon library. Use e-icons class combined with specific icon classes:
Common Icons:
e-file- File icone-open- Open/folder icone-save- Save/disk icone-cut- Cut icone-copy- Copy icone-paste- Paste icone-edit- Edit/pencil icone-delete- Delete/trash icone-home- Home icone-search- Search/magnifying glass icone-settings- Settings/gear icone-star- Star icone-user- User/person icone-print- Print icone-download- Download icone-upload- Upload icon
Icon Size and Styling
Control icon appearance with CSS classes:
<style>
/* Make icons larger */
.e-icons::before {
font-size: 18px;
}
/* Custom icon color */
.e-menu .e-menu-item.icon-red .e-icons::before {
color: red;
}
</style>
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="Critical" IconCss="e-icons e-delete icon-red"></MenuItem>
</MenuItems>
</SfMenu>Icon Positioning
Default Position (Left)
By default, icons appear to the left of text:
<MenuItem Text="File" IconCss="e-icons e-file"></MenuItem>
<!-- Output: [Icon] File -->Custom Icon Positioning with CSS
Position icons to the right or apply custom styling:
<style>
/* Position icons to the right */
.e-menu .e-menu-item.right-icon .e-icons {
order: 2;
margin-left: 10px;
margin-right: 0;
}
.e-menu .e-menu-item.right-icon {
flex-direction: row-reverse;
}
</style>
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="Settings" IconCss="e-icons e-settings right-icon"></MenuItem>
</MenuItems>
</SfMenu>Custom CSS Icons
Creating Custom Icon Classes
Define custom icons using CSS content property:
<style>
.custom-icon::before {
content: '\e7cb'; /* Unicode character for icon */
font-family: 'e_icons';
font-size: 16px;
}
.e-home::before {
content: '\e700';
}
.e-file::before {
content: '\e7cb';
}
.e-edit::before {
content: '\e78f';
}
.e-open::before {
content: '\e70f';
}
.e-save::before {
content: '\e74d';
}
.e-cut::before {
content: '\e73f';
}
.e-copy::before {
content: '\e77b';
}
.e-paste::before {
content: '\e739';
}
.e-delete::before {
content: '\e71d';
}
</style>
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="File" IconCss="e-file"></MenuItem>
<MenuItem Text="Edit" IconCss="e-edit"></MenuItem>
<MenuItem Text="Delete" IconCss="e-delete"></MenuItem>
</MenuItems>
</SfMenu>Using Font Awesome Icons
Integrate Font Awesome for extended icon choices:
<!-- Include Font Awesome in index.html -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"><SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="Home" IconCss="fas fa-home"></MenuItem>
<MenuItem Text="Settings" IconCss="fas fa-cog"></MenuItem>
<MenuItem Text="Users" IconCss="fas fa-users"></MenuItem>
<MenuItem Text="Logout" IconCss="fas fa-sign-out-alt"></MenuItem>
</MenuItems>
</SfMenu>Separators and Disabled Items
Adding Separators
Separators are visual dividers between menu items:
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="New"></MenuItem>
<MenuItem Text="Open"></MenuItem>
<MenuItem Text="Save"></MenuItem>
<MenuItem Separator="true"></MenuItem>
<MenuItem Text="Exit"></MenuItem>
</MenuItems>
</SfMenu>Disabling Menu Items
Disable items that should not be interactive:
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="Undo"></MenuItem>
<MenuItem Text="Redo" Disabled="true"></MenuItem>
<MenuItem Separator="true"></MenuItem>
<MenuItem Text="Cut" Disabled="@(!isTextSelected)"></MenuItem>
<MenuItem Text="Copy"></MenuItem>
<MenuItem Text="Paste"></MenuItem>
</MenuItems>
</SfMenu>
@code {
private bool isTextSelected = false;
}Conditional Disabling
<SfMenu Items="@MenuList">
<MenuFieldSettings Text="Text" Children="SubItems"></MenuFieldSettings>
</SfMenu>
@code {
public class MenuModel
{
public string Text { get; set; }
public bool Disabled { get; set; }
public List<MenuModel> SubItems { get; set; }
}
public List<MenuModel> MenuList = new List<MenuModel>
{
new MenuModel { Text = "File", SubItems = new List<MenuModel>
{
new MenuModel { Text = "Open", Disabled = false },
new MenuModel { Text = "Recent", Disabled = true } // Disabled
}}
};
}Navigation Links
Adding URLs to Menu Items
Use the Url property to make menu items navigate to different pages:
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="Products" Url="/products"></MenuItem>
<MenuItem Text="Services" Url="/services"></MenuItem>
<MenuItem Text="About">
<MenuItems>
<MenuItem Text="Company" Url="/about/company"></MenuItem>
<MenuItem Text="Team" Url="/about/team"></MenuItem>
</MenuItems>
</MenuItem>
</MenuItems>
</SfMenu>External Links
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="Documentation" Url="https://docs.example.com" Target="_blank"></MenuItem>
<MenuItem Text="GitHub" Url="https://github.com/example" Target="_blank"></MenuItem>
</MenuItems>
</SfMenu>Programmatic Navigation
Combine Url with event handling for custom navigation:
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="Dashboard"></MenuItem>
<MenuItem Text="Reports"></MenuItem>
</MenuItems>
<MenuEvents TValue="MenuItem" ItemSelected="OnSelectItem"></MenuEvents>
</SfMenu>
@inject NavigationManager NavigationManager
@code {
private void OnSelectItem(MenuEventArgs<MenuItem> args)
{
if (!string.IsNullOrEmpty(args.Item.Url))
{
NavigationManager.NavigateTo(args.Item.Url);
}
}
}CSS Customization
Custom Menu Styling
<style>
/* Custom menu background */
.e-menu {
background-color: #f0f0f0;
}
/* Custom menu item styling */
.e-menu .e-menu-item {
padding: 12px 20px;
border-radius: 4px;
}
/* Hover effect */
.e-menu .e-menu-item:hover {
background-color: #e0e0e0;
transition: background-color 0.3s ease;
}
/* Active/selected item */
.e-menu .e-menu-item.e-selected {
background-color: #007bff;
color: white;
}
/* Icon spacing */
.e-menu .e-menu-item .e-icons {
margin-right: 8px;
}
/* Submenu styling */
.e-menu.e-contextmenu,
.e-menu .e-menu {
background-color: white;
border: 1px solid #ddd;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
</style>
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="File" IconCss="e-file"></MenuItem>
<MenuItem Text="Edit" IconCss="e-edit"></MenuItem>
</MenuItems>
</SfMenu>Theme Variables
Customize colors using CSS variables:
<style>
:root {
--menu-bg: #f5f5f5;
--menu-hover-bg: #e8e8e8;
--menu-text: #333;
--menu-icon-size: 16px;
}
.e-menu {
background-color: var(--menu-bg);
color: var(--menu-text);
}
.e-menu .e-menu-item:hover {
background-color: var(--menu-hover-bg);
}
.e-menu .e-icons::before {
font-size: var(--menu-icon-size);
}
</style>Dark Mode Support
<style>
@media (prefers-color-scheme: dark) {
.e-menu {
background-color: #2d2d2d;
color: #f0f0f0;
}
.e-menu .e-menu-item:hover {
background-color: #404040;
}
.e-menu.e-contextmenu,
.e-menu .e-menu {
background-color: #1e1e1e;
border-color: #444;
}
}
</style>Best Practices
1. Consistent Icon Usage: Use icons consistently across your menu 2. Icon Clarity: Choose clear, recognizable icons 3. Color Contrast: Ensure adequate contrast between text and background 4. Accessibility: Provide text labels alongside icons 5. Performance: Use icon fonts rather than individual SVG/image files 6. Responsive Design: Test icon display on different screen sizes 7. Separation: Use separators to group related menu items logically
Menu Items and Data Binding
Table of Contents
- MenuItem Component
- Basic Menu Structure
- Hardcoded vs Data-Bound Menus
- Self-Referential Data Binding
- MenuFieldSettings Configuration
- Custom Data Models
- Multilevel Nesting
MenuItem Component
The MenuItem component represents a single menu item. Key properties include:
| Property | Type | Description |
|---|---|---|
Text | string | Display text for the menu item |
Url | string | Navigation URL for the menu item |
IconCss | string | CSS class for icon display |
Separator | bool | Display a separator line below item |
Disabled | bool | Disable the menu item |
Items | IEnumerable<MenuItem> | Child menu items (submenus) |
Basic MenuItem Example
<MenuItem Text="File" IconCss="e-icons e-file">
<MenuItems>
<MenuItem Text="Open"></MenuItem>
<MenuItem Text="Save"></MenuItem>
</MenuItems>
</MenuItem>Basic Menu Structure
Creating a Hardcoded Menu
For simple, static menus, define MenuItem components directly:
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="Home"></MenuItem>
<MenuItem Text="About">
<MenuItems>
<MenuItem Text="Company"></MenuItem>
<MenuItem Text="Team"></MenuItem>
<MenuItem Text="Careers"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="Services">
<MenuItems>
<MenuItem Text="Consulting"></MenuItem>
<MenuItem Text="Development"></MenuItem>
<MenuItem Text="Support"></MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="Contact"></MenuItem>
</MenuItems>
</SfMenu>MenuItem Hierarchy
Menus support unlimited nesting levels. Each MenuItem can contain its own MenuItems collection:
<MenuItem Text="Products">
<MenuItems>
<MenuItem Text="Category A">
<MenuItems>
<MenuItem Text="Product A1"></MenuItem>
<MenuItem Text="Product A2">
<MenuItems>
<MenuItem Text="Variant A2-1"></MenuItem>
<MenuItem Text="Variant A2-2"></MenuItem>
</MenuItems>
</MenuItem>
</MenuItems>
</MenuItem>
<MenuItem Text="Category B"></MenuItem>
</MenuItems>
</MenuItem>Hardcoded vs Data-Bound Menus
When to Use Hardcoded Menus
Advantages:
- Simple implementation for small menus
- No database queries or external data needed
- Directly visible in component markup
- Suitable for navigation menus that rarely change
Example:
<SfMenu TValue="MenuItem">
<MenuItems>
<MenuItem Text="File">
<MenuItems>
<MenuItem Text="New"></MenuItem>
<MenuItem Text="Open"></MenuItem>
</MenuItems>
</MenuItem>
</MenuItems>
</SfMenu>When to Use Data-Bound Menus
Advantages:
- Dynamic menu generation from lists, databases, or APIs
- Data-driven updates without code changes
- Suitable for large menu structures
- Supports filtering and transformations
Example:
<SfMenu Items="@MenuList">
<MenuFieldSettings Text="@nameof(MenuModel.Label)" Children="@nameof(MenuModel.SubItems)"></MenuFieldSettings>
</SfMenu>
@code {
public List<MenuModel> MenuList = new List<MenuModel>
{
new MenuModel { Label = "Home" },
new MenuModel { Label = "Products", SubItems = new List<MenuModel> { ... } }
};
}Self-Referential Data Binding
Self-referential data structures use a flat list with ParentId relationships to build hierarchies.
Data Model
public class MenuItem
{
public string Id { get; set; }
public string Text { get; set; }
public string ParentId { get; set; } // Links to parent's Id
}Self-Referential Binding Example
@using Syncfusion.Blazor.Navigations
<SfMenu Items="@MenuItems">
<MenuFieldSettings ItemId="Id" Text="Text" ParentId="ParentId"></MenuFieldSettings>
</SfMenu>
@code {
public List<MenuItem> MenuItems = new List<MenuItem>
{
new MenuItem { Id = "1", Text = "Events", ParentId = null },
new MenuItem { Id = "2", Text = "Movies", ParentId = null },
new MenuItem { Id = "3", Text = "Directory", ParentId = null },
// Submenus under Events (ParentId = "1")
new MenuItem { Id = "4", Text = "Conferences", ParentId = "1" },
new MenuItem { Id = "5", Text = "Music", ParentId = "1" },
new MenuItem { Id = "6", Text = "Workshops", ParentId = "1" },
// Submenus under Movies (ParentId = "2")
new MenuItem { Id = "7", Text = "Now Showing", ParentId = "2" },
new MenuItem { Id = "8", Text = "Coming Soon", ParentId = "2" },
// Sub-submenus under Music (ParentId = "5")
new MenuItem { Id = "9", Text = "Pop", ParentId = "5" },
new MenuItem { Id = "10", Text = "Folk", ParentId = "5" },
new MenuItem { Id = "11", Text = "Classical", ParentId = "5" }
};
public class MenuItem
{
public string Id { get; set; }
public string Text { get; set; }
public string ParentId { get; set; }
}
}Advantages of Self-Referential Data
- Stores hierarchical data in a single flat list
- Easy to save to databases (single table)
- Flexible parent-child relationships
- Supports unlimited nesting levels
MenuFieldSettings Configuration
The MenuFieldSettings component maps data source properties to Menu Bar fields:
<MenuFieldSettings
ItemId="Id"
Text="Label"
ParentId="ParentId"
Children="SubMenu"
Url="Link"
IconCss="Icon"
Separator="IsSeparator">
</MenuFieldSettings>Common Property Mappings
| Setting | Purpose | Data Property |
|---|---|---|
ItemId | Unique identifier | Id, ItemId |
Text | Display label | Text, Label, Name |
ParentId | Parent relationship | ParentId, Parent, PId |
Children | Nested items collection | Items, SubMenu, SubItems |
Url | Navigation link | Url, Link, NavigationUrl |
IconCss | Icon CSS class | IconCss, Icon, CssClass |
Separator | Separator indicator | Separator, IsSeparator |
Example: Mapping Custom Properties
public class CustomMenuData
{
public int ItemKey { get; set; } // Maps to ItemId
public string Label { get; set; } // Maps to Text
public int? ParentKey { get; set; } // Maps to ParentId
public List<CustomMenuData> ChildItems { get; set; } // Maps to Children
public string NavigationPath { get; set; } // Maps to Url
}<MenuFieldSettings
ItemId="ItemKey"
Text="Label"
ParentId="ParentKey"
Children="ChildItems"
Url="NavigationPath">
</MenuFieldSettings>Custom Data Models
Create custom models that match your data structure:
public class CategoryMenu
{
public string CategoryId { get; set; }
public string CategoryName { get; set; }
public string CategoryIcon { get; set; }
public List<ProductMenu> Products { get; set; }
}
public class ProductMenu
{
public string ProductId { get; set; }
public string ProductName { get; set; }
public string ProductUrl { get; set; }
}Using Custom Models with Hierarchical Data
<SfMenu Items="@Categories">
<MenuFieldSettings
Text="CategoryName"
IconCss="CategoryIcon"
Children="Products">
</MenuFieldSettings>
</SfMenu>
@code {
public List<CategoryMenu> Categories = new List<CategoryMenu>
{
new CategoryMenu
{
CategoryId = "1",
CategoryName = "Electronics",
CategoryIcon = "e-icons e-gadget",
Products = new List<ProductMenu>
{
new ProductMenu { ProductId = "1", ProductName = "Laptop", ProductUrl = "/products/1" },
new ProductMenu { ProductId = "2", ProductName = "Phone", ProductUrl = "/products/2" }
}
}
};
}Multilevel Nesting
The Menu Bar supports unlimited nesting levels:
<SfMenu Items="@MenuData">
<MenuFieldSettings Text="Name" Children="SubMenus"></MenuFieldSettings>
</SfMenu>
@code {
public class MenuNode
{
public string Name { get; set; }
public List<MenuNode> SubMenus { get; set; }
}
public List<MenuNode> MenuData = new List<MenuNode>
{
new MenuNode
{
Name = "Fashion",
SubMenus = new List<MenuNode>
{
new MenuNode
{
Name = "Men",
SubMenus = new List<MenuNode>
{
new MenuNode { Name = "Shirts" },
new MenuNode { Name = "Pants" }
}
},
new MenuNode
{
Name = "Women",
SubMenus = new List<MenuNode>
{
new MenuNode { Name = "Dresses" },
new MenuNode { Name = "Skirts" }
}
}
}
}
};
}Best Practices
1. Use consistent data structure: Keep all items at same hierarchy level using same properties 2. Unique identifiers: Use unique ItemId values for ParentId mapping 3. Null handling: Set ParentId to null for root-level items 4. Property naming: Use meaningful names in MenuFieldSettings mappings 5. Lazy loading: For large menus, consider loading data on demand