
Syncfusion Blazor Dashboard Layout
- 215 installs
- 4 repo stars
- Updated July 28, 2026
- syncfusion/blazor-ui-components-skills
Use syncfusion-blazor-dashboard-layout for development tasks
About
syncfusion-blazor-dashboard-layout: A skill for development. This provides functionality for development workflows.
- syncfusion-blazor-dashboard-layout
Syncfusion Blazor Dashboard Layout by the numbers
- 215 all-time installs (skills.sh)
- +14 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,845 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/blazor-ui-components-skills --skill syncfusion-blazor-dashboard-layoutAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 215 |
|---|---|
| repo stars | ★ 4 |
| Last updated | July 28, 2026 |
| Repository | syncfusion/blazor-ui-components-skills ↗ |
What it does
Use syncfusion-blazor-dashboard-layout for development tasks
Files
Implementing Dashboard Layout with Syncfusion Blazor
The Syncfusion Blazor Dashboard Layout component provides a comprehensive solution for building responsive, interactive dashboards. This skill guides you through creating flexible panel-based layouts with advanced features including drag-and-drop, resizing, state persistence, and adaptive responsive design.
When to Use This Skill
Use this skill when you need to:
- Create dashboard or grid-based panel layouts
- Enable users to rearrange panels through drag-and-drop
- Allow panel resizing with size constraints
- Build responsive layouts that adapt to different screen sizes
- Save and restore user layout configurations
- Create complex multi-panel displays with headers and dynamic content
- Customize panel styling and appearance
- Prevent panel overlapping in dynamic scenarios
Component Overview
SfDashboardLayout creates a grid-based dashboard where panels represent resizable, draggable containers organized on a configurable grid. Key capabilities:
- Grid-based positioning using Row and Column properties
- Flexible sizing with width (SizeX) and height (SizeY) in cell units
- Size constraints with MinSizeX, MaxSizeX, MinSizeY, MaxSizeY properties
- Drag-and-drop with automatic collision handling and panel pushing
- Resizing with customizable resize handles in multiple directions
- Floating panels that automatically move up to fill empty spaces
- State persistence to localStorage with programmatic save/load/reset
- Templates for headers and dynamic content
- Responsive design with media query breakpoints for mobile adaptation
- Cell-based grid with configurable columns, cell aspect ratio, and spacing
Documentation and Navigation Guide
Getting Started 📄 references/getting-started.md
- Setting up Dashboard Layout in WebAssembly and Server apps
- NuGet package installation (Syncfusion.Blazor.Layouts, Syncfusion.Blazor.Themes)
- Configuring namespaces and Syncfusion services
- Adding stylesheet and script resources
- Creating first dashboard with basic panels
Core Layout Configuration 📄 references/panel-positioning-sizing.md
- Panel Row and Column positioning
- Setting panel dimensions with SizeX and SizeY
- Min/Max size constraints (MinSizeX, MaxSizeX, MinSizeY, MaxSizeY)
- Panel ID management and unique identification
- Understanding cell-based grid system
Interactive Features 📄 references/drag-drop-functionality.md
- Enabling drag-and-drop rearrangement
- Automatic collision detection and panel pushing
- Customizing drag handles with DraggableHandle property
- Using CSS selectors for drag-handle targeting
- Placeholder visualization during drag operations
📄 references/resizing-floating-panels.md
- Enabling panel resizing with AllowResizing property
- Customizing resize directions with ResizableHandles property
- Floating panels with AllowFloating to utilize empty space
- Floating behavior and automatic upward panel movement
Grid Configuration & Styling 📄 references/grid-configuration-styling.md
- Configuring grid with Columns property
- Cell aspect ratio with CellAspectRatio property
- Cell spacing with CellSpacing property (row and column gaps)
- Visualizing grid with ShowGridLines property
- CSS customization of panel headers, content, and backgrounds
- CSS classes: .e-panel-header, .e-panel-content, .e-resize
Responsive & Adaptive Design 📄 references/responsive-adaptive-design.md
- Built-in responsive support for different screen sizes
- MediaQuery property for custom breakpoints
- Automatic stacking layout at low resolutions (default 600px)
- Mobile-friendly configurations
- Responsive behavior without manual configuration
Panel Templates & Headers 📄 references/panel-templates-headers.md
- HeaderTemplate for panel titles and headers
- ContentTemplate for panel main content
- CssClass property for custom styling
- Rendering HTML and components within panels
- Empty space rendering prevention
State Management & Persistence 📄 references/state-persistence.md
- Enabling persistence with EnablePersistence property
- localStorage integration for automatic save/restore
- GetPersistDataAsync for retrieving current state as string
- SetPersistDataAsync for restoring saved state
- ResetPersistDataAsync for clearing saved state
- Component ID requirement for persistence
API Reference 📄 references/api-reference.md
- Complete SfDashboardLayout component API documentation
- All 14 properties with types, defaults, and accepted values
- All 11 methods with parameters, return types, and descriptions
- All 8 events with argument types and usage examples
- DashboardLayoutPanel component properties (17 total)
- PanelModel class properties for programmatic panel data
- Event argument classes with complete examples
- ResizableHandle enumeration with all 8 direction values
- Working code examples for every property and method
- Cross-references to related documentation
Advanced Scenarios & Troubleshooting 📄 references/advanced-scenarios.md
- Preventing panel overlap with unique IDs in dynamic rendering
- All panels at same position configuration
- Performance optimization for complex layouts
- Complex multi-panel display patterns
- Troubleshooting common issues and edge cases
Quick Start Example
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout CellSpacing="@(new double[]{10, 10})" Columns="5">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<HeaderTemplate><div>Panel 1</div></HeaderTemplate>
<ContentTemplate><div>Your content here</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<HeaderTemplate><div>Panel 2</div></HeaderTemplate>
<ContentTemplate><div>Your content here</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=2 Column=3>
<HeaderTemplate><div>Panel 3</div></HeaderTemplate>
<ContentTemplate><div>Your content here</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-header {
background-color: rgba(0, 0, 0, .1);
text-align: center;
}
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>Common Patterns
Basic 3-Panel Dashboard
<SfDashboardLayout CellSpacing="@(new double[]{10, 10})" Columns="6">
<DashboardLayoutPanels>
<DashboardLayoutPanel SizeX=2>
<HeaderTemplate><div>Metrics</div></HeaderTemplate>
<ContentTemplate><div>250,000</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 Column=2>
<HeaderTemplate><div>Users</div></HeaderTemplate>
<ContentTemplate><div>45,200</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 Column=4>
<HeaderTemplate><div>Revenue</div></HeaderTemplate>
<ContentTemplate><div>$125,000</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>With Drag-Drop and Resizing
<SfDashboardLayout CellSpacing="@(new double[]{10, 10})"
Columns="6"
AllowDragging="true"
AllowResizing="true">
<!-- Panel definitions -->
</SfDashboardLayout>Responsive Mobile Layout
<SfDashboardLayout CellSpacing="@(new double[]{10, 10})"
Columns="5"
MediaQuery="max-width:600px">
<!-- Automatically stacks to single column below 600px -->
</SfDashboardLayout>State Persistence Pattern
<SfDashboardLayout ID="dashboard" EnablePersistence="true" CellSpacing="@(new double[]{10, 10})">
<!-- Automatically saves to localStorage on changes -->
</SfDashboardLayout>Key Properties Reference
| Property | Purpose | Common Values |
|---|---|---|
| Columns | Number of grid cells per row | 4, 5, 6, 12 |
| Row | Panel vertical position (0-based) | 0, 1, 2, ... |
| Column | Panel horizontal position (0-based) | 0, 1, 2, ... |
| SizeX | Panel width in cells | 1, 2, 3, ... |
| SizeY | Panel height in cells | 1, 2, 3, ... |
| MinSizeX/MinSizeY | Minimum size constraints | 1, 2, ... |
| MaxSizeX/MaxSizeY | Maximum size constraints | null (unlimited) or specific value |
| CellSpacing | Gap between panels (row, column) | [10, 10], [20, 20] |
| CellAspectRatio | Height-to-width ratio | 1, 2, 0.5 |
| AllowDragging | Enable panel rearrangement | true, false |
| AllowResizing | Enable panel resizing | true, false |
| AllowFloating | Auto-fill empty spaces | true, false |
| DraggableHandle | CSS selector for drag area | ".e-panel-header" |
| ResizableHandles | Resize directions | "e" (east), "south-east", etc. |
| MediaQuery | Mobile breakpoint | "max-width:600px" |
| EnablePersistence | Save state to localStorage | true, false |
| ID | Unique component ID (required for persistence) | "dashboard", "layout1" |
Use Case Examples
Data Analytics Dashboard Use dashboard grid with Charts, Grids, and metrics panels. Enable resizing so users can focus on important metrics.
Admin Control Panel Combine multiple Syncfusion components (grids, charts, forms) in panels. Persist layout so admin preferences are remembered.
SEO Monitoring Dashboard Display analytics metrics and charts using dashboard grid. Use floating panels to automatically optimize space as panels are moved.
Personal Workspace Let users customize their layout completely with drag-drop, resizing, and persistence to create their ideal workspace.
Responsive Mobile Dashboard Design for desktop, automatically adapts to single-column stacked layout on mobile using MediaQuery breakpoints.
Advanced Scenarios and Troubleshooting
Table of Contents
- Preventing Panel Overlap
- All Panels at Same Position
- Performance Optimization
- Complex Layout Patterns
- SEO Analysis Dashboard
- Troubleshooting Guide
Preventing Panel Overlap
The Panel Overlap Problem
Panel overlap occurs only when multiple panels are assigned the same `Id` property. When you don't explicitly set IDs, the Dashboard Layout component automatically generates unique IDs internally, so there is no overlap issue.
Overlapping panels occur with duplicate IDs:
- Panel 1:
Id="panel" - Panel 2:
Id="panel"← Same ID causes overlap at Row = 0, Column = 0
@using Syncfusion.Blazor.Layouts
<!-- ❌ WRONG - Duplicate IDs will cause overlap -->
<SfDashboardLayout CellSpacing="@(new double[]{20, 20})" Columns="4">
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel"> <!-- Duplicate ID -->
<ContentTemplate><div>Panel 1</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Id="panel"> <!-- Same ID causes overlap -->
<ContentTemplate><div>Panel 2</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>Solution: Use Unique IDs or Auto-Generated IDs
Option 1: Assign unique `Id` values explicitly
@using Syncfusion.Blazor.Layouts
<!-- ✅ CORRECT - Each panel has unique ID -->
<SfDashboardLayout CellSpacing="@(new double[]{20, 20})" Columns="4">
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel-1">
<ContentTemplate><div>Panel 1</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Id="panel-2" Row="0" Column="1">
<ContentTemplate><div>Panel 2</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Id="panel-3" Row="0" Column="2">
<ContentTemplate><div>Panel 3</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>Dynamic Panel Generation with Unique IDs
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout CellSpacing="@(new double[]{20, 20})" Columns="4">
<DashboardLayoutPanels>
@foreach (var panel in PanelItems)
{
<DashboardLayoutPanel
Id="@panel.Id"
Row="@panel.Row"
Column="@panel.Column">
<ContentTemplate>
<div class="panel-content">@panel.Content</div>
</ContentTemplate>
</DashboardLayoutPanel>
}
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
public class PanelModel
{
public string Id { get; set; }
public int Row { get; set; } = 0;
public int Column { get; set; } = 0;
public string Content { get; set; }
}
private List<PanelModel> PanelItems = new List<PanelModel>
{
new PanelModel { Id = "panel1", Row = 0, Column = 0, Content = "Panel 1" },
new PanelModel { Id = "panel2", Row = 0, Column = 1, Content = "Panel 2" },
new PanelModel { Id = "panel3", Row = 0, Column = 2, Content = "Panel 3" },
new PanelModel { Id = "panel4", Row = 1, Column = 0, Content = "Panel 4" },
new PanelModel { Id = "panel5", Row = 1, Column = 1, Content = "Panel 5" },
new PanelModel { Id = "panel6", Row = 1, Column = 2, Content = "Panel 6" }
};
}
<style>
.panel-content {
text-align: center;
margin-top: 10px;
font-size: 18px;
font-weight: 500;
}
</style>Best Practices:
- Always assign unique IDs to dynamically generated panels
- Use descriptive IDs (e.g., "panel-sales", "panel-metrics")
- Include the ID in your data model
- Never duplicate ID values
- Consider using GUIDs for system-generated panels
All Panels at Same Position
Scenario: Dynamic Multi-Panel Display
Sometimes you may want to display all panels starting at the same default position (Row=0, Column=0) and let them automatically arrange:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{20, 20})"
Columns="4"
AllowFloating="true">
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel-1">
<ContentTemplate><div>Panel 1</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Id="panel-2">
<ContentTemplate><div>Panel 2</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Id="panel-3">
<ContentTemplate><div>Panel 3</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Id="panel-4">
<ContentTemplate><div>Panel 4</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
padding: 10px;
}
</style>With AllowFloating="true":
- Panels automatically arrange in available space
- No overlap occurs
- Grid flows left-to-right, top-to-bottom
- Optimal space utilization
Performance Optimization
Handling Large Panel Counts
For dashboards with many panels, optimize performance:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
Columns="6"
AllowFloating="true">
<DashboardLayoutPanels>
@foreach (var panel in VisiblePanels) <!-- Only render visible panels -->
{
<DashboardLayoutPanel
Id="@panel.Id"
Row="@panel.Row"
Column="@panel.Column"
SizeX="@panel.SizeX"
SizeY="@panel.SizeY">
<ContentTemplate>
<div>@panel.Content</div>
</ContentTemplate>
</DashboardLayoutPanel>
}
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
private List<PanelData> AllPanels = new();
private List<PanelData> VisiblePanels => AllPanels.Take(20).ToList(); // Limit rendered panels
public class PanelData
{
public string Id { get; set; }
public int Row { get; set; }
public int Column { get; set; }
public int SizeX { get; set; } = 1;
public int SizeY { get; set; } = 1;
public string Content { get; set; }
}
}Virtual Scrolling Pattern
For extremely large dashboards, implement lazy loading:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
Columns="6">
<DashboardLayoutPanels>
@foreach (var panel in LoadedPanels)
{
<DashboardLayoutPanel
Id="@panel.Id"
Row="@panel.Row"
Column="@panel.Column">
<ContentTemplate>
<div>@panel.Content</div>
</ContentTemplate>
</DashboardLayoutPanel>
}
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
private List<PanelData> LoadedPanels = new();
private int LoadCount = 0;
protected override async Task OnInitializedAsync()
{
// Load initial set of panels
await LoadMorePanels();
}
private async Task LoadMorePanels()
{
const int BatchSize = 10;
for (int i = 0; i < BatchSize; i++)
{
LoadedPanels.Add(new PanelData
{
Id = $"panel-{LoadCount++}",
Content = $"Panel {LoadCount}"
});
}
await Task.Delay(100); // Simulate load time
}
public class PanelData
{
public string Id { get; set; }
public int Row { get; set; }
public int Column { get; set; }
public string Content { get; set; }
}
}Performance Tips
Do:
- ✅ Limit initial panel count
- ✅ Use OnChange events sparingly
- ✅ Implement lazy loading for large datasets
- ✅ Cache panel data
- ✅ Use trackBy in loops
Avoid:
- ❌ Recreating all panels on every render
- ❌ Heavy calculations in ContentTemplate
- ❌ Binding to rapidly changing properties
- ❌ Loading all panels upfront
Complex Layout Patterns
Responsive Multi-Section Dashboard
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{15, 15})"
Columns="12"
MediaQuery="max-width:768px"
AllowDragging="true"
AllowResizing="true">
<DashboardLayoutPanels>
<!-- Header: Full width metrics -->
<DashboardLayoutPanel SizeX=12 Id="header-metrics">
<HeaderTemplate><div>Key Performance Indicators</div></HeaderTemplate>
<ContentTemplate>
<div style="display:flex; gap:10px;">
<div style="flex:1;">Revenue: $1.2M</div>
<div style="flex:1;">Profit: $450K</div>
<div style="flex:1;">Growth: +25%</div>
<div style="flex:1;">Efficiency: 92%</div>
</div>
</ContentTemplate>
</DashboardLayoutPanel>
<!-- Main content: 2 columns on desktop, 1 on mobile -->
<DashboardLayoutPanel SizeX=6 Row=1 Id="main-chart">
<HeaderTemplate><div>Sales Trend</div></HeaderTemplate>
<ContentTemplate><div>Chart here</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=6 Row=1 Column=6 Id="revenue-chart">
<HeaderTemplate><div>Revenue Distribution</div></HeaderTemplate>
<ContentTemplate><div>Chart here</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Secondary: 3 columns on desktop, full width on mobile -->
<DashboardLayoutPanel SizeX=4 Row=2 Id="region-data">
<HeaderTemplate><div>By Region</div></HeaderTemplate>
<ContentTemplate><div>Regional metrics</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=4 Row=2 Column=4 Id="product-data">
<HeaderTemplate><div>By Product</div></HeaderTemplate>
<ContentTemplate><div>Product metrics</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=4 Row=2 Column=8 Id="segment-data">
<HeaderTemplate><div>By Segment</div></HeaderTemplate>
<ContentTemplate><div>Segment metrics</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Footer: Full width details -->
<DashboardLayoutPanel SizeX=12 Row=3 Id="detail-table">
<HeaderTemplate><div>Detailed Report</div></HeaderTemplate>
<ContentTemplate><div>Detailed data table</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>SEO Analysis Dashboard
Real-World Complex Dashboard Example
This comprehensive example demonstrates how to build a professional SEO (Search Engine Optimization) data analysis dashboard by integrating multiple Syncfusion Blazor components within the Dashboard Layout component. This showcases:
- Multi-component integration: Sidebar, AccumulationChart, Chart, and Grid components
- Advanced templating: Complex HeaderTemplate and ContentTemplate usage
- Data visualization: Multiple chart types (Pie, Doughnut, Column, SplineArea)
- Responsive design: Sidebar docking and responsive panel arrangement
- CSS customization: Custom styling for cards and visualization
- Icon integration: Custom icon implementation from Syncfusion icon library
@using Syncfusion.Blazor.Charts
@using Syncfusion.Blazor.Layouts
@using Syncfusion.Blazor.Navigations
<div class="control-section">
<div class="col-lg-12 col-sm-12 col-md-12" id="sidebar-section">
<div id="head">
<div class="header">
<div class="menu"><span class="e-icons expand"></span></div>
<div class="searchContent">
<div class="analysis">SEO Analysis Dashboard</div>
</div>
<div class="right-content">
<div class="information">
<span class="e-avatar e-avatar-medium e-avatar-circle image"></span>
<div class="text-content">John</div>
</div>
</div>
</div>
</div>
<!-- sidebar element declaration -->
<SfSidebar ID="dockSidebar" DockSize="60px" EnableDock="true" Type="SidebarType.Over" CloseOnDocumentClick="true" Target="#target">
<ChildContent>
<div class="content-area">
<div class="dock">
<ul>
<li class="sidebar-item"><span class="e-icons home"></span></li>
<li class="sidebar-item filterHover">
<span class="e-icons filter"></span>
</li>
<li class="sidebar-item">
<span class="e-icons analyticsChart"></span>
</li>
<li class="sidebar-item"><span class="e-icons settings"></span></li>
<li class="sidebar-item">
<span class="e-icons analytics"></span>
</li>
</ul>
</div>
</div>
</ChildContent>
</SfSidebar>
<!-- end of sidebar element -->
<!-- main content declaration -->
<div id="target">
<div class="sidebar-content">
<div class="dashboardParent">
<SfDashboardLayout @ref="dashboardObject" CellSpacing="@CellSpacing" Columns="@Columns" CellAspectRatio="@Ratio">
<DashboardLayoutPanels>
<!-- KPI Cards -->
<DashboardLayoutPanel SizeX="2" SizeY="1" Row="0" Column="0">
<ContentTemplate>
<div class="card">
<span class="e-icons session"></span>
<div class="card-content text">Session</div>
<div class="card-content number">124,444</div>
</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX="2" SizeY="1" Row="0" Column="2">
<ContentTemplate>
<div class="card">
<span class="e-icons profile"></span>
<div class="card-content text">Users</div>
<div class="card-content number">64,496</div>
</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX="2" SizeY="1" Row="0" Column="4">
<ContentTemplate>
<div class="card">
<span class="e-icons views"></span>
<div class="card-content text">Views</div>
<div class="card-content number">442,278</div>
</div>
</ContentTemplate>
</DashboardLayoutPanel>
<!-- Active Visitors Chart -->
<DashboardLayoutPanel SizeX="2" SizeY="2" Row="1" Column="0">
<HeaderTemplate>
<div>Active Visitors</div>
</HeaderTemplate>
<ContentTemplate>
<SfAccumulationChart Theme="@Theme" Height="100%" Width="100%" EnableSmartLabels="true" SelectionMode="AccumulationSelectionMode.Point">
<AccumulationChartLegendSettings Visible="true" Position="@Syncfusion.Blazor.Charts.LegendPosition.Bottom"></AccumulationChartLegendSettings>
<AccumulationChartTooltipSettings Enable="true" Header="<b>${point.x}</b>" Format="Composition : <b>${point.y}%</b>"></AccumulationChartTooltipSettings>
<AccumulationChartSeriesCollection>
<AccumulationChartSeries DataSource="@VisitorData" XName="Device" YName="Amount" Radius="100%" InnerRadius="35%" Name="Revenue" Palettes="@(new string[] { "#357cd2", "#00bdae", "#e36593" })">
<AccumulationDataLabelSettings Visible="true" Name="text" Position="AccumulationLabelPosition.Inside">
<AccumulationChartDataLabelFont FontWeight="600" Color="white" Size="14px"></AccumulationChartDataLabelFont>
</AccumulationDataLabelSettings>
</AccumulationChartSeries>
</AccumulationChartSeriesCollection>
</SfAccumulationChart>
</ContentTemplate>
</DashboardLayoutPanel>
<!-- Visitors by Type Chart -->
<DashboardLayoutPanel SizeX="4" SizeY="2" Row="1" Column="2">
<HeaderTemplate>
<div>Visitors By Type</div>
</HeaderTemplate>
<ContentTemplate>
<SfChart Theme="@Theme" Height="100%" Width="100%">
<ChartMargin Top="30"></ChartMargin>
<ChartArea><ChartAreaBorder Width="0"></ChartAreaBorder></ChartArea>
<ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.Category" Interval="1">
<ChartAxisMajorGridLines Width="0"></ChartAxisMajorGridLines>
</ChartPrimaryXAxis>
<ChartPrimaryYAxis>
<ChartAxisLineStyle Width="0"></ChartAxisLineStyle>
<ChartAxisMajorTickLines Width="0"></ChartAxisMajorTickLines>
</ChartPrimaryYAxis>
<ChartSeriesCollection>
<ChartSeries DataSource="@DesktopVisitData" Fill="#e36593" XName="Month" YName="Visits" Name="Desktop" Type="ChartSeriesType.Column" Width="2"></ChartSeries>
<ChartSeries DataSource="@MobileVisitData" Fill="#00bdae" XName="Month" YName="Visits" Name="Mobile" Type="ChartSeriesType.Column" Width="2"></ChartSeries>
<ChartSeries DataSource="@TabletVisitData" Fill="#357cd2" XName="Month" YName="Visits" Name="Tablet" Type="ChartSeriesType.Column" Width="2"></ChartSeries>
</ChartSeriesCollection>
<ChartTooltipSettings Enable="true"></ChartTooltipSettings>
<ChartLegendSettings Visible="true"></ChartLegendSettings>
</SfChart>
</ContentTemplate>
</DashboardLayoutPanel>
<!-- Usage Statistics -->
<DashboardLayoutPanel SizeX="2" SizeY="2" Row="3" Column="4">
<HeaderTemplate>
<div>Usage Statistics</div>
</HeaderTemplate>
<ContentTemplate>
<SfAccumulationChart Theme="@Theme" Height="100%" Width="100%" EnableSmartLabels="true" SelectionMode="AccumulationSelectionMode.Point">
<AccumulationChartLegendSettings Visible="true" Position="@Syncfusion.Blazor.Charts.LegendPosition.Bottom"></AccumulationChartLegendSettings>
<AccumulationChartSeriesCollection>
<AccumulationChartSeries DataSource="@UsageDataValue" XName="Device" YName="Count" Radius="100%" InnerRadius="0%" Name="Usage" Explode="true" ExplodeIndex="2" ExplodeOffset="10%" Palettes="@(new string[] { "#357cd2", "#00bdae", "#e36593" })">
<AccumulationDataLabelSettings Visible="true" Name="Text" Position="AccumulationLabelPosition.Inside">
<AccumulationChartDataLabelFont FontWeight="600"></AccumulationChartDataLabelFont>
</AccumulationDataLabelSettings>
</AccumulationChartSeries>
</AccumulationChartSeriesCollection>
</SfAccumulationChart>
</ContentTemplate>
</DashboardLayoutPanel>
<!-- Traffic History Chart -->
<DashboardLayoutPanel SizeX="4" SizeY="2" Row="3" Column="0">
<HeaderTemplate>
<div>Traffic History</div>
</HeaderTemplate>
<ContentTemplate>
<SfChart Theme="@Theme" Height="100%" Width="100%">
<ChartArea><ChartAreaBorder Width="0"></ChartAreaBorder></ChartArea>
<ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.DateTime" LabelFormat="MMM" IntervalType="IntervalType.Months" EdgeLabelPlacement="EdgeLabelPlacement.Shift">
<ChartAxisMajorGridLines Width="0"></ChartAxisMajorGridLines>
</ChartPrimaryXAxis>
<ChartPrimaryYAxis LabelFormat="{value}" Minimum="0" Maximum="4" Interval="1">
<ChartAxisLineStyle Width="0"></ChartAxisLineStyle>
<ChartAxisMajorTickLines Width="0"></ChartAxisMajorTickLines>
</ChartPrimaryYAxis>
<ChartLegendSettings Visible="true"></ChartLegendSettings>
<ChartSeriesCollection>
<ChartSeries DataSource="@TrafficData" Name="Jan" XName="Period" Opacity="0.5" YName="TrafficRate" Type="ChartSeriesType.SplineArea" Fill="rgb(239, 183, 202)"></ChartSeries>
<ChartSeries DataSource="@TrafficData1" Name="Feb" XName="Period" Opacity="0.5" YName="TrafficRate" Type="ChartSeriesType.SplineArea" Fill="rgb(0, 189, 174)"></ChartSeries>
</ChartSeriesCollection>
</SfChart>
</ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
</div>
</div>
</div>
</div>
</div>
@code {
SfDashboardLayout dashboardObject;
double[] CellSpacing = new double[] { 5, 5 };
int Columns = 6;
double Ratio = 100 / 85;
private Syncfusion.Blazor.Theme Theme { get; set; }
public List<VisitorsData> VisitorData = new List<VisitorsData>
{
new VisitorsData { Amount = 900, Device = "Tablet" },
new VisitorsData { Amount = 1200, Device = "Desktop" },
new VisitorsData { Amount = 600, Device = "Mobile" }
};
public List<UsageData> UsageDataValue = new List<UsageData>
{
new UsageData { Count = 37, Device = "Desktop", Text = "60%" },
new UsageData { Count = 17, Device = "Mobile", Text = "10%" },
new UsageData { Count = 19, Device = "Tablet", Text = "20%" }
};
public List<VisitsCountData> MobileVisitData = new List<VisitsCountData>
{
new VisitsCountData { Visits = 37, Month = "Jan" },
new VisitsCountData { Visits = 23, Month = "Feb" },
new VisitsCountData { Visits = 18, Month = "Mar" }
};
public List<VisitsCountData> TabletVisitData = new List<VisitsCountData>
{
new VisitsCountData { Visits = 38, Month = "Jan" },
new VisitsCountData { Visits = 17, Month = "Feb" },
new VisitsCountData { Visits = 26, Month = "Mar" }
};
public List<VisitsCountData> DesktopVisitData = new List<VisitsCountData>
{
new VisitsCountData { Visits = 46, Month = "Jan" },
new VisitsCountData { Visits = 27, Month = "Feb" },
new VisitsCountData { Visits = 26, Month = "Mar" }
};
public List<TrafficDataModel> TrafficData = new List<TrafficDataModel>
{
new TrafficDataModel { Period = new DateTime(2002, 01, 01), TrafficRate = 2.1 },
new TrafficDataModel { Period = new DateTime(2003, 01, 01), TrafficRate = 3.5 },
new TrafficDataModel { Period = new DateTime(2004, 01, 01), TrafficRate = 2.7 },
new TrafficDataModel { Period = new DateTime(2005, 01, 01), TrafficRate = 1.7 },
new TrafficDataModel { Period = new DateTime(2006, 01, 01), TrafficRate = 2.2 },
new TrafficDataModel { Period = new DateTime(2007, 01, 01), TrafficRate = 2.6 },
new TrafficDataModel { Period = new DateTime(2008, 01, 01), TrafficRate = 2.9 },
new TrafficDataModel { Period = new DateTime(2009, 01, 01), TrafficRate = 3.7 },
new TrafficDataModel { Period = new DateTime(2010, 01, 01), TrafficRate = 1.4 },
new TrafficDataModel { Period = new DateTime(2011, 01, 01), TrafficRate = 3.2 }
};
public List<TrafficDataModel> TrafficData1 = new List<TrafficDataModel>
{
new TrafficDataModel { Period = new DateTime(2002, 01, 01), TrafficRate = 2 },
new TrafficDataModel { Period = new DateTime(2003, 01, 01), TrafficRate = 1.7 },
new TrafficDataModel { Period = new DateTime(2004, 01, 01), TrafficRate = 1.9 },
new TrafficDataModel { Period = new DateTime(2005, 01, 01), TrafficRate = 2.3 },
new TrafficDataModel { Period = new DateTime(2006, 01, 01), TrafficRate = 2.3 },
new TrafficDataModel { Period = new DateTime(2007, 01, 01), TrafficRate = 1.6 },
new TrafficDataModel { Period = new DateTime(2008, 01, 01), TrafficRate = 1.5 },
new TrafficDataModel { Period = new DateTime(2009, 01, 01), TrafficRate = 2.7 },
new TrafficDataModel { Period = new DateTime(2010, 01, 01), TrafficRate = 1.5 },
new TrafficDataModel { Period = new DateTime(2011, 01, 01), TrafficRate = 2.2 }
};
public class TrafficDataModel
{
public DateTime Period { get; set; }
public double TrafficRate { get; set; }
}
public class VisitorsData
{
public string Device { get; set; }
public int Amount { get; set; }
}
public class VisitsCountData
{
public string Month { get; set; }
public int Visits { get; set; }
}
public class UsageData
{
public string Device { get; set; }
public int Count { get; set; }
public string Text { get; set; }
}
}Key Features in This Example
1. Multi-Component Integration:
SfSidebarfor navigation sidebar with dockingSfAccumulationChartfor pie/doughnut charts (Active Visitors, Usage Statistics)SfChartfor column and spline area charts (Visitors by Type, Traffic History)SfDashboardLayoutas the main container
2. Panel Arrangement:
- Row 0: Three 1x1 KPI metric cards (Session, Users, Views)
- Row 1: Active Visitors doughnut chart (2x2) + Visitors by Type column chart (4x2)
- Row 3: Revenue pie chart (2x2) + Traffic History spline chart (4x2)
3. Template Usage:
<HeaderTemplate>
<div>Panel Title</div>
</HeaderTemplate>
<ContentTemplate>
<!-- Chart or content goes here -->
</ContentTemplate>4. CSS Customization:
- Custom card styling with gradient backgrounds
- Icon sizing and positioning
- Responsive sidebar styling
- Chart container sizing
5. Data Binding:
- Multiple data sources (VisitorData, UsageDataValue, MobileVisitData, etc.)
- DateTime series for traffic trends
- Dynamic property binding (XName, YName, DataSource)
Benefits of This Approach
✅ Professional UI: Multiple visualizations in one layout ✅ Responsive: Adapts to mobile with sidebar docking ✅ Flexible: Easy to add/remove panels or swap chart types ✅ Performance: Efficient grid layout with minimal redraws ✅ Accessible: Proper heading hierarchy and semantic structure ✅ Maintainable: Clean separation of data (C# code block) and template (cshtml)
Customization Tips
1. Change Chart Colors: Modify Palettes property 2. Adjust Panel Sizes: Change SizeX and SizeY values 3. Add More Charts: Insert additional DashboardLayoutPanel components 4. Update Data: Modify the data classes and collection initialization 5. Responsive Breakpoints: Add MediaQuery="max-width:768px" to stack panels on mobile
Troubleshooting Guide
Issue: Panels Not Draggable
Problem: Dragging panels doesn't work.
Solutions: 1. Enable dragging: AllowDragging="true" 2. Check if DraggableHandle is too restrictive 3. Ensure JavaScript is enabled 4. Verify component ID is set
Issue: Resizing Not Working
Problem: Resize handles don't appear or resizing fails.
Solutions: 1. Enable resizing: AllowResizing="true" 2. Check ResizableHandles property 3. Verify min/max size constraints allow resizing 4. Check CSS doesn't hide resize icon
Issue: Floating Not Working
Problem: AllowFloating="true" but panels don't float.
Solutions: 1. Verify EnablePersistence is configured correctly 2. Check that panels have unique IDs 3. Ensure no conflicting CSS positioning 4. Test in clean browser session
Issue: Performance Degradation
Problem: Dashboard becomes slow with many panels.
Solutions: 1. Reduce panel count initially 2. Implement lazy loading 3. Disable unnecessary features (dragging, resizing) 4. Optimize ContentTemplate complexity 5. Use OnChange events sparingly
Issue: Layout Not Responsive
Problem: MediaQuery doesn't trigger stacking.
Solutions: 1. Set MediaQuery property: MediaQuery="max-width:768px" 2. Test with actual device or DevTools 3. Check CSS media query syntax 4. Verify browser window size is actually changing 5. Clear cache and reload
Issue: Saved State Not Restoring
Problem: Layout doesn't restore after page reload.
Solutions: 1. Ensure ID is set: ID="dashboard" 2. Enable persistence: EnablePersistence="true" 3. Check localStorage is available (not incognito) 4. Verify no JavaScript errors in console 5. Try ResetPersistDataAsync and re-save
General Debugging Tips
Use Browser DevTools:
// Check localStorage
localStorage.getItem('dashboard')
// Clear saved data
localStorage.removeItem('dashboard')
// Check for errors
console.log(error)Step-by-Step Debugging: 1. Verify all IDs are unique 2. Check each property individually 3. Test with minimal example first 4. Gradually add complexity 5. Check browser console for errors 6. Verify latest Syncfusion package version
Common Configuration Errors:
- ❌ Missing ID attribute for persistence
- ❌ Duplicate panel IDs
- ❌ Invalid Column configuration
- ❌ CSS conflicts with drag/resize
- ❌ EnablePersistence without ID
- ❌ Conflicting negative sizes
Syncfusion Blazor Dashboard Layout API Reference
Overview
The SfDashboardLayout component is a grid-structured layout component that creates flexible dashboards with draggable, resizable, and removable panels. This API reference provides comprehensive documentation for all properties, methods, and events of the Dashboard Layout component and its related classes.
---
Table of Contents
- SfDashboardLayout Component
- Properties
- Methods
- Events
- DashboardLayoutPanel Component
- PanelModel Class
- Event Arguments
- Enumerations
- Usage Examples
- Common Patterns
---
SfDashboardLayout Component
Properties
| Property | Type | Default | Accepted Values | Description | Reference |
|---|---|---|---|---|---|
AllowDragging | bool | true | true, false | Specifies whether panels can be reordered through dragging | view |
AllowFloating | bool | true | true, false | Specifies whether panels fill available cells while dragging or resizing | view |
AllowResizing | bool | false | true, false | Specifies whether panels can be resized | view |
CellAspectRatio | double | 1 | Any positive number | Defines the cell aspect ratio of the panel | view |
CellSpacing | double[] | {5, 5} | Array of doubles | Defines the spacing between panels (horizontal, vertical) | view |
Columns | int | 1 | Any positive integer | Determines the number of columns in the layout | view |
DraggableHandle | string | null | CSS selector string | CSS selector for the draggable handle element | view |
EnablePersistence | bool | false | true, false | Persists the component state between page reloads | view |
EnableRtl | bool | false | true, false | Enables right-to-left direction for the component | view |
ID | string | null | Any string | ID attribute for the Dashboard Layout element | view |
IsAddPanelCalled | bool | false | true, false | Protected property to track if AddPanelAsync was called | view |
MediaQuery | string | max-width:600px | Valid CSS media query | Media query for responsive stacked layout | view |
ResizableHandles | ResizableHandle | SouthEast | East, West, North, South, NorthEast, NorthWest, SouthEast, SouthWest | Specifies the resize handle directions | view |
ShowGridLines | bool | false | true, false | Shows grid lines for design visualization | view |
---
Methods
| Method | Parameters | Return Type | Description | Reference |
|---|---|---|---|---|
AddPanelAsync() | PanelModel panel | Task | Adds a new panel to the Dashboard Layout | view |
GetPersistDataAsync() | None | Task<string> | Retrieves persisted state as a string | view |
MovePanelAsync() | string idValue, int rowValue, int colValue | Task | Moves a panel to specified row and column | view |
RefreshAsync() | None | Task | Updates and refreshes the Dashboard Layout | view |
RemoveAllAsync() | None | Task | Removes all panels from the Dashboard Layout | view |
RemovePanelAsync() | string idValue | Task | Removes a specific panel by ID | view |
ResetPersistDataAsync() | None | Task | Resets the state to original configuration | view |
ResizePanelAsync() | string idValue, int sizeXValue, int sizeYValue | Task | Resizes a panel to specified dimensions | view |
Serialize() | None | Task<List<PanelModel>> | Retrieves all panels as PanelModel collection | view |
SetPersistDataAsync() | string properties | Task | Loads previously saved state | view |
---
Events
| Event | Arguments | Description | Reference |
|---|---|---|---|
Changed | ChangeEventArgs | Raised when panel positions change | view |
Created | object | Raised when the Dashboard Layout is created | view |
Destroyed | object | Raised when the Dashboard Layout is destroyed | view |
OnDragStart | DragStartArgs | Raised when a panel starts to drag | view |
OnDragStop | DragStopArgs | Raised when a dragged panel is dropped | view |
OnResizeStart | ResizeArgs | Raised when a panel starts resizing | view |
OnResizeStop | ResizeArgs | Raised when panel resizing ends | view |
OnWindowResize | ResizeArgs | Raised when the window is resized | view |
---
DashboardLayoutPanel Component
Properties
| Property | Type | Default | Accepted Values | Description | Reference |
|---|---|---|---|---|---|
AllowDragging | bool | true | true, false | Allow/prevent dragging for this individual panel | view |
Column | int | 0 | Non-negative integer | Column position of the panel in the grid | view |
Content | RenderFragment | null | Razor markup | Direct content without template wrapper | view |
ContentTemplate | RenderFragment | null | Razor markup | Template for panel content area | view |
CssClass | string | Empty | CSS class names | Custom CSS classes for panel styling | view |
Enabled | bool | true | true, false | Enable or disable the panel | view |
Header | RenderFragment | null | Razor markup | Direct header content | view |
HeaderTemplate | RenderFragment | null | Razor markup | Template for panel header area | view |
Id | string | Auto-generated | Unique string identifier | Unique identifier for the panel | view |
MaxSizeX | int? | null | Positive integer or null | Maximum width in cells count | view |
MaxSizeY | int? | null | Positive integer or null | Maximum height in cells count | view |
MinSizeX | int | 1 | Positive integer | Minimum width in cells count | view |
MinSizeY | int | 1 | Positive integer | Minimum height in cells count | view |
Row | int | 0 | Non-negative integer | Row position of the panel in the grid | view |
SizeX | int | 1 | Positive integer | Width of the panel in cells count | view |
SizeY | int | 1 | Positive integer | Height of the panel in cells count | view |
ZIndex | double | 1000 | Any positive number | Z-index for panel layering | view |
---
DashboardLayoutPanel - Additional Property Examples
Content Property
Direct content assignment alternative to ContentTemplate (simpler use cases):
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout Columns="4" CellSpacing="@(new double[]{10, 10})">
<DashboardLayoutPanels>
<!-- Using Content property for simple string content -->
<DashboardLayoutPanel Id="panel-1">
<Content>Simple panel content</Content>
</DashboardLayoutPanel>
<!-- Using ContentTemplate for complex HTML -->
<DashboardLayoutPanel Id="panel-2" Column="1">
<ContentTemplate>
<div>
<p>Complex content with</p>
<ul>
<li>Multiple elements</li>
<li>And formatting</li>
</ul>
</div>
</ContentTemplate>
</DashboardLayoutPanel>
<!-- Using Header property -->
<DashboardLayoutPanel Id="panel-3" Column="2">
<Header>Panel Title</Header>
<Content>Simple header with content</Content>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>Usage Pattern:
- Use
Contentfor static text or simple markup - Use
ContentTemplatefor data binding and complex layouts - Both cannot be used together in same panel
AllowDragging Property
Control whether individual panels can be dragged (panel-level override of component setting):
@using Syncfusion.Blazor.Layouts
@using Syncfusion.Blazor.Buttons
<SfButton OnClick="ToggleDragging">Toggle Panel 2 Dragging</SfButton>
<SfDashboardLayout Columns="4" CellSpacing="@(new double[]{10, 10})" AllowDragging="true">
<DashboardLayoutPanels>
<!-- Draggable panel - can be moved around -->
<DashboardLayoutPanel Id="panel-1" AllowDragging="true">
<HeaderTemplate><div>Panel 1 (Draggable)</div></HeaderTemplate>
<ContentTemplate><div>You can drag this panel</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Panel with dynamic dragging control -->
<DashboardLayoutPanel Id="panel-2" Column="1" AllowDragging="@allowDragPanel2">
<HeaderTemplate><div>@(allowDragPanel2 ? "Panel 2 (Draggable)" : "Panel 2 (Locked)")</div></HeaderTemplate>
<ContentTemplate><div>@(allowDragPanel2 ? "You can drag this panel" : "Dragging is disabled")</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Non-draggable panel - acts as anchor -->
<DashboardLayoutPanel Id="panel-3" Column="2" AllowDragging="false">
<HeaderTemplate><div>Panel 3 (Locked)</div></HeaderTemplate>
<ContentTemplate><div>This panel cannot be dragged</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Panel 4 with conditional dragging -->
<DashboardLayoutPanel Id="panel-4" Column="3" AllowDragging="@userCanDrag">
<HeaderTemplate><div>Panel 4 (Permission-based)</div></HeaderTemplate>
<ContentTemplate><div>@(userCanDrag ? "You have permission to drag" : "Insufficient permissions")</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
private bool allowDragPanel2 = true;
private bool userCanDrag = true;
private void ToggleDragging()
{
allowDragPanel2 = !allowDragPanel2;
}
}Behavior:
AllowDragging="true": Panel can be dragged to new positions (respects component AllowDragging setting)AllowDragging="false": Panel cannot be dragged, acts as a fixed anchor point- Overrides component-level AllowDragging property at panel level
- Useful for protecting important panels from accidental movement
- Combines with component-level setting using AND logic (both must be true to allow drag)
Enabled Property
Control whether a panel is interactive and visible:
@using Syncfusion.Blazor.Layouts
@using Syncfusion.Blazor.Buttons
<SfButton OnClick="TogglePanels">Toggle Panel States</SfButton>
<SfDashboardLayout Columns="4" CellSpacing="@(new double[]{10, 10})">
<DashboardLayoutPanels>
<!-- Enabled panel - fully interactive -->
<DashboardLayoutPanel Id="panel-1" Enabled="true">
<HeaderTemplate><div>Active Panel</div></HeaderTemplate>
<ContentTemplate><div>This panel is enabled and interactive</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Disabled panel - grayed out, non-interactive -->
<DashboardLayoutPanel Id="panel-2" Column="1" Enabled="@isPanelEnabled">
<HeaderTemplate><div>@(isPanelEnabled ? "Enabled" : "Disabled") Panel</div></HeaderTemplate>
<ContentTemplate><div>@(isPanelEnabled ? "Interact with this panel" : "This panel is disabled")</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Dynamic enable/disable based on condition -->
<DashboardLayoutPanel Id="panel-3" Column="2" Enabled="@userHasPermission">
<HeaderTemplate><div>Conditional Panel</div></HeaderTemplate>
<ContentTemplate><div>Only visible to authorized users</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
private bool isPanelEnabled = false;
private bool userHasPermission = true;
private void TogglePanels()
{
isPanelEnabled = !isPanelEnabled;
}
}Behavior:
Enabled="true": Panel appears normally and supports all interactions (dragging, resizing, etc.)Enabled="false": Panel appears with reduced opacity, interactions are disabled- Useful for conditional UI based on permissions or application state
ZIndex Property
Control the stacking order of panels when they overlap:
@using Syncfusion.Blazor.Layouts
@using Syncfusion.Blazor.Buttons
<div>
<SfButton OnClick="BringToFront">Bring to Front</SfButton>
<SfButton OnClick="SendToBack">Send to Back</SfButton>
</div>
<SfDashboardLayout AllowFloating="true" Columns="4" CellSpacing="@(new double[]{10, 10})">
<DashboardLayoutPanels>
<!-- Default panel (ZIndex = 1000) -->
<DashboardLayoutPanel Id="panel-1" SizeX="2" SizeY="2">
<HeaderTemplate><div>Panel 1 (Z: 1000)</div></HeaderTemplate>
<ContentTemplate><div>Overlapping content</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Higher panel appears on top (ZIndex = 1100) -->
<DashboardLayoutPanel Id="panel-2" ZIndex="1100" SizeX="2" SizeY="2" Column="1">
<HeaderTemplate><div>Panel 2 (Z: 1100) - On Top</div></HeaderTemplate>
<ContentTemplate><div>This panel appears above panel-1</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Lower panel appears below (ZIndex = 900) -->
<DashboardLayoutPanel Id="panel-3" ZIndex="900" SizeX="2" SizeY="2" Column="2">
<HeaderTemplate><div>Panel 3 (Z: 900) - Behind</div></HeaderTemplate>
<ContentTemplate><div>This panel appears below panel-1</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
private SfDashboardLayout dashboard;
private double panel1ZIndex = 1000;
private void BringToFront()
{
panel1ZIndex = 1200; // Bring panel-1 to front
}
private void SendToBack()
{
panel1ZIndex = 800; // Send panel-1 to back
}
}ZIndex Behavior:
- Default value is 1000
- Higher values appear on top
- Lower values appear below
- Useful when AllowFloating="true" creates overlaps
- Affects stacking order in visual hierarchy
---
PanelModel Class
Properties
| Property | Type | Default | Description |
|---|---|---|---|
AllowDragging | bool | true | Allow/prevent dragging for the panel |
Column | int | 0 | Column position of the panel |
Content | RenderFragment | null | Panel content fragment |
CssClass | string | Empty | CSS class names for styling |
Enabled | bool | true | Panel enabled state |
Header | RenderFragment | null | Panel header fragment |
Id | string | Empty | Unique panel identifier |
MaxSizeX | int? | null | Maximum width in cells |
MaxSizeY | int? | null | Maximum height in cells |
MinSizeX | int | 1 | Minimum width in cells |
MinSizeY | int | 1 | Minimum height in cells |
Row | int | 0 | Row position of the panel |
SizeX | int | 1 | Width in cells count |
SizeY | int | 1 | Height in cells count |
ZIndex | double | 1000 | Z-index for layering |
---
Event Arguments
ChangeEventArgs
Raised when panel positions or collection changes.
| Property | Type | Description |
|---|---|---|
AddedPanels | List<PanelModel> | Panels added to the layout |
ChangedPanels | List<PanelModel> | Panels with position changes |
RemovedPanels | List<PanelModel> | Panels removed from the layout |
IsInteracted | bool | True if triggered by user interaction |
Usage Example:
<DashboardLayoutEvents Changed="@OnChanged" />
@code {
private void OnChanged(ChangeEventArgs args)
{
if (args.IsInteracted)
{
Console.WriteLine($"Changed panels: {args.ChangedPanels.Count}");
Console.WriteLine($"Added panels: {args.AddedPanels.Count}");
Console.WriteLine($"Removed panels: {args.RemovedPanels.Count}");
}
}
}---
DragStartArgs
Raised when a panel drag operation begins.
| Property | Type | Description |
|---|---|---|
Cancel | bool | Set to true to prevent the drag action |
Element | ElementReference | Reference to the DOM element being dragged |
Id | string | ID of the panel being dragged |
Usage Example:
<DashboardLayoutEvents OnDragStart="@OnDragStart" />
@code {
private void OnDragStart(DragStartArgs args)
{
if (args.Id == "protected-panel")
{
args.Cancel = true; // Prevent dragging
}
}
}---
DragStopArgs
Raised when a dragged panel is dropped.
| Property | Type | Description |
|---|---|---|
Element | ElementReference | Reference to the DOM element that was dragged |
Id | string | ID of the dropped panel |
Usage Example:
<DashboardLayoutEvents OnDragStop="@OnDragStop" />
@code {
private void OnDragStop(DragStopArgs args)
{
Console.WriteLine($"Panel {args.Id} was dropped");
}
}---
ResizeArgs
Raised during resize operations (start and stop).
| Property | Type | Description |
|---|---|---|
Element | ElementReference | Reference to the DOM element being resized |
Id | string | ID of the resizing panel |
IsInteracted | bool | True if triggered by user interaction |
Name | string | Event name (OnResizeStart or OnResizeStop) |
Usage Example:
<DashboardLayoutEvents OnResizeStart="@OnResizeStart" OnResizeStop="@OnResizeStop" />
@code {
private void OnResizeStart(ResizeArgs args)
{
Console.WriteLine($"Resizing panel {args.Id}");
}
private void OnResizeStop(ResizeArgs args)
{
if (args.IsInteracted)
{
Console.WriteLine($"Panel {args.Id} resize completed");
}
}
}---
CreatedEventArgs
Raised when the Dashboard Layout component is fully created and initialized.
Usage Example:
<DashboardLayoutEvents Created="@OnCreated" />
@code {
private void OnCreated(object args)
{
Console.WriteLine("Dashboard Layout component has been created and initialized");
// Initialize related components or load dashboard state
}
}---
DestroyedEventArgs
Raised when the Dashboard Layout component is destroyed or removed from the DOM.
Usage Example:
<DashboardLayoutEvents Destroyed="@OnDestroyed" />
@code {
private void OnDestroyed(object args)
{
Console.WriteLine("Dashboard Layout component is being destroyed");
// Cleanup resources, save state, or unbind event handlers
}
}---
Enumerations
ResizableHandle
Specifies the resize handle directions for panels.
| Value | Description |
|---|---|
East | East (right) direction |
West | West (left) direction |
North | North (top) direction |
South | South (bottom) direction |
NorthEast | North-East (top-right) direction |
NorthWest | North-West (top-left) direction |
SouthEast | South-East (bottom-right) direction |
SouthWest | South-West (bottom-left) direction |
Usage Example:
<!-- Single direction resize -->
<SfDashboardLayout AllowResizing="true" ResizableHandles="ResizableHandle.SouthEast">
...
</SfDashboardLayout>
<!-- Multiple directions (using bitwise OR) -->
<SfDashboardLayout AllowResizing="true" ResizableHandles="ResizableHandle.East | ResizableHandle.South">
...
</SfDashboardLayout>---
Usage Examples
EnableRtl Property
Enables right-to-left (RTL) text direction for the Dashboard Layout component, useful for languages like Arabic, Hebrew, and Persian.
@using Syncfusion.Blazor.Layouts
<!-- Enable RTL language support -->
<SfDashboardLayout ID="dashboard"
Columns="4"
EnableRtl="true"
CellSpacing="@(new double[]{10, 10})">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<HeaderTemplate><div>لوحة 1</div></HeaderTemplate>
<ContentTemplate><div>محتوى اللوحة</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Column="1">
<HeaderTemplate><div>لوحة 2</div></HeaderTemplate>
<ContentTemplate><div>محتوى اللوحة</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
/* RTL-specific styling */
.e-dashboardlayout.e-rtl {
direction: rtl;
}
</style>ID Property
Provides a unique identifier for the Dashboard Layout element, essential for programmatic access and event binding.
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout @ref="dashboardObject"
ID="myDashboard"
Columns="4">
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel-1">
<HeaderTemplate><div>Statistics</div></HeaderTemplate>
<ContentTemplate><div>Dashboard Content</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
SfDashboardLayout dashboardObject;
private async Task RefreshDashboard()
{
// Access dashboard using the ID
if (dashboardObject != null)
{
// Perform operations on the dashboard
await dashboardObject.RefreshAsync();
}
}
}IsAddPanelCalled Property
A protected property that tracks whether AddPanelAsync has been called. Useful for determining if dynamic panels have been added programmatically.
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout @ref="dashboardObject"
ID="dashboard"
Columns="4">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<HeaderTemplate><div>Initial Panel</div></HeaderTemplate>
<ContentTemplate><div>Static Content</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<button @onclick="AddDynamicPanel">Add Panel</button>
<p>Panels added dynamically: @panelAdditionStatus</p>
@code {
SfDashboardLayout dashboardObject;
private string panelAdditionStatus = "None";
private async Task AddDynamicPanel()
{
var newPanel = new PanelModel
{
Id = "dynamic-panel",
Row = 1,
Column = 0,
SizeX = 2,
SizeY = 1
};
// Add panel dynamically
await dashboardObject.AddPanelAsync(newPanel);
// Check if AddPanelAsync was called by examining the internal state
// This helps track dynamic vs. static panel creation
panelAdditionStatus = "Yes - Dynamic panels added";
}
}---
Methods Examples
AddPanelAsync() Method
Adds a new panel to the Dashboard Layout dynamically at runtime.
@using Syncfusion.Blazor.Layouts
<SfButton OnClick="AddNewPanel">Add Panel</SfButton>
<SfDashboardLayout @ref="dashboard" Columns="4">
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel-1">
<HeaderTemplate><div>Panel 1</div></HeaderTemplate>
<ContentTemplate><div>Content</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
SfDashboardLayout dashboard;
private int count = 1;
private async Task AddNewPanel()
{
count++;
var newPanel = new PanelModel { Id = $"panel-{count}", Row = count - 1, Column = 0, SizeX = 2, SizeY = 1 };
await dashboard.AddPanelAsync(newPanel);
}
}MovePanelAsync() Method
Moves a specific panel to a new row and column position.
@using Syncfusion.Blazor.Layouts
<SfButton OnClick="MovePanel">Move Panel 1</SfButton>
<SfDashboardLayout @ref="dashboard" Columns="4">
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel-1" Row="0" Column="0" SizeX="2">
<HeaderTemplate><div>Panel 1</div></HeaderTemplate>
<ContentTemplate><div>Content</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
SfDashboardLayout dashboard;
private async Task MovePanel()
{
await dashboard.MovePanelAsync("panel-1", 1, 1); // Move to row 1, column 1
}
}RefreshAsync() Method
Updates and refreshes the Dashboard Layout component.
@using Syncfusion.Blazor.Layouts
<SfButton OnClick="RefreshLayout">Refresh</SfButton>
<SfDashboardLayout @ref="dashboard" Columns="@columnCount">
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel-1">
<HeaderTemplate><div>Panel 1</div></HeaderTemplate>
<ContentTemplate><div>Content</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
SfDashboardLayout dashboard;
private int columnCount = 4;
private async Task RefreshLayout()
{
columnCount = 6;
await Task.Delay(100);
await dashboard.RefreshAsync();
}
}RemoveAllAsync() Method
Removes all panels from the Dashboard Layout.
@using Syncfusion.Blazor.Layouts
<SfButton OnClick="ClearAll">Remove All Panels</SfButton>
<SfDashboardLayout @ref="dashboard" Columns="4">
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel-1">
<HeaderTemplate><div>Panel 1</div></HeaderTemplate>
<ContentTemplate><div>Content</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
SfDashboardLayout dashboard;
private async Task ClearAll()
{
await dashboard.RemoveAllAsync();
}
}RemovePanelAsync() Method
Removes a specific panel by its ID.
@using Syncfusion.Blazor.Layouts
<SfButton OnClick="RemovePanel">Remove Panel 2</SfButton>
<SfDashboardLayout @ref="dashboard" Columns="4">
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel-1">
<HeaderTemplate><div>Panel 1</div></HeaderTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Id="panel-2" Column="1">
<HeaderTemplate><div>Panel 2</div></HeaderTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
SfDashboardLayout dashboard;
private async Task RemovePanel()
{
await dashboard.RemovePanelAsync("panel-2");
}
}ResizePanelAsync() Method
Resizes a specific panel to new dimensions.
@using Syncfusion.Blazor.Layouts
<SfButton OnClick="ResizePanel">Resize Panel 1 to 3x2</SfButton>
<SfDashboardLayout @ref="dashboard" Columns="4" AllowResizing="true">
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel-1" SizeX="2" SizeY="1" MaxSizeX="4" MaxSizeY="2">
<HeaderTemplate><div>Panel 1</div></HeaderTemplate>
<ContentTemplate><div>Content</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
SfDashboardLayout dashboard;
private async Task ResizePanel()
{
await dashboard.ResizePanelAsync("panel-1", 3, 2);
}
}Serialize() Method
Retrieves all panels as a collection of PanelModel objects.
@using Syncfusion.Blazor.Layouts
<SfButton OnClick="GetPanels">Get Panel Info</SfButton>
<SfDashboardLayout @ref="dashboard" Columns="4">
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel-1" SizeX="2">
<HeaderTemplate><div>Panel 1</div></HeaderTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
SfDashboardLayout dashboard;
private async Task GetPanels()
{
var panels = (List<PanelModel>)await dashboard.Serialize();
foreach (var panel in panels)
Console.WriteLine($"Panel {panel.Id}: {panel.SizeX}x{panel.SizeY}");
}
}---
Note: For comprehensive examples onGetPersistDataAsync(),SetPersistDataAsync(), andResetPersistDataAsync()persistence methods, refer to the State Persistence guide, which contains detailed implementation patterns and best practices.
---
Complete Component Usage Example
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout @ref="dashboardObject"
ID="dashboard"
Columns="4"
CellSpacing="@(new double[]{10, 10})"
CellAspectRatio="1.5"
AllowDragging="true"
AllowResizing="true"
AllowFloating="true"
ResizableHandles="ResizableHandle.SouthEast"
ShowGridLines="false"
EnablePersistence="true"
MediaQuery="max-width:768px">
<DashboardLayoutEvents Changed="@OnChanged"
Created="@OnCreated"
OnDragStart="@OnDragStart"
OnDragStop="@OnDragStop"
OnResizeStart="@OnResizeStart"
OnResizeStop="@OnResizeStop" />
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel-1"
Row="0"
Column="0"
SizeX="2"
SizeY="1"
MinSizeX="1"
MaxSizeX="4"
AllowDragging="true">
<HeaderTemplate>
<span>Panel 1</span>
</HeaderTemplate>
<ContentTemplate>
<div>Panel content goes here</div>
</ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
SfDashboardLayout dashboardObject;
private void OnChanged(ChangeEventArgs args)
{
Console.WriteLine("Dashboard changed");
}
private void OnCreated(object args)
{
Console.WriteLine("Dashboard created");
}
private void OnDragStart(DragStartArgs args)
{
Console.WriteLine($"Dragging panel: {args.Id}");
}
private void OnDragStop(DragStopArgs args)
{
Console.WriteLine($"Dropped panel: {args.Id}");
}
private void OnResizeStart(ResizeArgs args)
{
Console.WriteLine($"Resizing panel: {args.Id}");
}
private void OnResizeStop(ResizeArgs args)
{
Console.WriteLine($"Resize complete: {args.Id}");
}
}---
Common Patterns
Dynamic Panel Operations
// Add a panel programmatically
var newPanel = new PanelModel
{
Id = "new-panel",
Row = 0,
Column = 0,
SizeX = 2,
SizeY = 1
};
await dashboardObject.AddPanelAsync(newPanel);
// Move a panel to new position
await dashboardObject.MovePanelAsync("panel-1", 1, 2);
// Resize a panel
await dashboardObject.ResizePanelAsync("panel-1", 3, 2);
// Remove a specific panel
await dashboardObject.RemovePanelAsync("panel-1");
// Remove all panels
await dashboardObject.RemoveAllAsync();State Management
// Get current state
var state = await dashboardObject.GetPersistDataAsync();
await localStorage.SetItemAsync("dashboard-state", state);
// Restore state
var savedState = await localStorage.GetItemAsync("dashboard-state");
await dashboardObject.SetPersistDataAsync(savedState);
// Reset to original state
await dashboardObject.ResetPersistDataAsync();
// Get all panels as collection
var panels = await dashboardObject.Serialize();Conditional Event Handling
<DashboardLayoutEvents OnDragStart="@PreventSpecificPanelDrag" />
@code {
private void PreventSpecificPanelDrag(DragStartArgs args)
{
// Allow dragging only for specific panels
var protectedPanels = new[] { "locked-panel", "header-panel" };
if (protectedPanels.Contains(args.Id))
{
args.Cancel = true;
}
}
}---
Drag and Drop Functionality
Table of Contents
- Overview
- Enabling Drag and Drop
- Default Drag Behavior
- Collision Handling
- Customizing Drag Handles
- Drag Handle Examples
Overview
Dashboard Layout provides built-in drag-and-drop functionality allowing users to rearrange panels dynamically. When dragging a panel:
1. A placeholder area appears showing the target position 2. Colliding panels are automatically pushed to available space 3. Panels adjust in real-time based on collision detection 4. Layout optimizes automatically to find suitable placement
Enabling Drag and Drop
AllowDragging Property
By default, drag-and-drop is enabled. Explicitly set the AllowDragging property when needed:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
CellAspectRatio="2"
Columns="5"
AllowDragging="true">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<ContentTemplate><div>0</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<ContentTemplate><div>1</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=2 Column=3>
<ContentTemplate><div>2</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Row=1>
<ContentTemplate><div>3</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>Disabling Drag and Drop
<SfDashboardLayout AllowDragging="false">
<!-- Panels cannot be dragged -->
</SfDashboardLayout>Default Drag Behavior
Full Panel as Drag Handle
By default, the entire panel acts as the draggable area. Users can click anywhere on a panel and drag it to a new location.
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
CellAspectRatio="2"
Columns="5">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<ContentTemplate>
<div>Click anywhere on this panel to drag</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<ContentTemplate>
<div>This panel is also fully draggable</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=2 Column=3>
<ContentTemplate>
<div>Entire panel surface allows dragging</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Row=1>
<ContentTemplate>
<div>4</div>
</ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>Collision Handling
Automatic Panel Pushing
When panels collide during drag operations, the colliding panels are automatically pushed in the best available direction (left, right, top, or bottom).
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
CellAspectRatio="2"
Columns="5">
<DashboardLayoutPanels>
<!-- When Panel 0 is dragged over Panel 1, Panel 1 is pushed -->
<DashboardLayoutPanel>
<ContentTemplate><div>0</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<ContentTemplate><div>1</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=2 Column=3>
<ContentTemplate><div>2</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Row=1>
<ContentTemplate><div>3</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>Collision Behavior: 1. Placeholder shows where panel will land 2. Colliding panels shift automatically 3. Panels push to available space (adaptive) 4. Layout reorganizes in real-time 5. On release, final positions are confirmed
Placeholder Visualization
During drag operations, a visual placeholder area is displayed to indicate:
- Current drag position
- Where the panel will land if released
- Helps users determine optimal placement before dropping
Customizing Drag Handles
DraggableHandle Property
Restrict dragging to specific elements within panels using CSS selectors:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
CellAspectRatio="2"
Columns="5"
DraggableHandle=".e-panel-header">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<HeaderTemplate><div>Panel 1</div></HeaderTemplate>
<ContentTemplate>
<div>Content here is NOT draggable</div>
<button>Buttons are clickable, not draggable</button>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<HeaderTemplate><div>Panel 2</div></HeaderTemplate>
<ContentTemplate>
<div>Click header to drag</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=2 Column=3>
<HeaderTemplate><div>Panel 3</div></HeaderTemplate>
<ContentTemplate>
<div>Content is not draggable</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Row=1>
<HeaderTemplate><div>Panel 4</div></HeaderTemplate>
<ContentTemplate>
<div>Only drag from header</div>
</ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-header {
background-color: rgba(0, 0, 0, .1);
text-align: center;
cursor: move;
padding: 10px;
}
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>CSS Selector Specificity
The DraggableHandle property accepts CSS selectors:
- Class selector:
.e-panel-header(handles with this class) - Element selector:
div(drag from any div) - ID selector:
#header(specific element by ID) - Attribute selector:
[data-handle="true"](elements with attribute)
Use Cases for Custom Handles
Header-Only Dragging:
DraggableHandle=".e-panel-header"Users drag only from the header, allowing content interaction.
Icon-Based Dragging:
DraggableHandle=".drag-icon"Only a specific icon is draggable.
Multiple Selectors:
DraggableHandle=".e-panel-header, .drag-zone"Both elements can drag the panel.
Drag Handle Examples
Example 1: Header-Only Drag with Buttons
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
Columns="4"
DraggableHandle=".panel-header">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<HeaderTemplate>
<div class="panel-header">
<span>📊 Dashboard</span>
</div>
</HeaderTemplate>
<ContentTemplate>
<div>
<p>Drag from header only</p>
<button>Click me (not draggable)</button>
</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Column=1>
<HeaderTemplate>
<div class="panel-header">
<span>📈 Analytics</span>
</div>
</HeaderTemplate>
<ContentTemplate>
<div>
<p>Interactive content</p>
<input type="text" placeholder="Type here">
</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Column=2>
<HeaderTemplate>
<div class="panel-header">
<span>📋 Reports</span>
</div>
</HeaderTemplate>
<ContentTemplate>
<div>
<p>Content area</p>
</div>
</ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.panel-header {
background-color: #334099;
color: white;
padding: 10px;
cursor: move;
font-weight: bold;
}
.e-panel-content {
padding: 15px;
}
button {
padding: 5px 10px;
cursor: pointer;
}
input {
padding: 5px;
width: 100%;
}
</style>Example 2: Drag Icon Handle
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
Columns="3"
DraggableHandle=".drag-icon">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<HeaderTemplate>
<div class="panel-header">
<span class="drag-icon">⋮⋮</span>
<span>Panel Title</span>
</div>
</HeaderTemplate>
<ContentTemplate>
<div>Drag from the icon (⋮⋮) only</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Column=1>
<HeaderTemplate>
<div class="panel-header">
<span class="drag-icon">⋮⋮</span>
<span>Another Panel</span>
</div>
</HeaderTemplate>
<ContentTemplate>
<div>Entire content area is interactive</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Column=2>
<HeaderTemplate>
<div class="panel-header">
<span class="drag-icon">⋮⋮</span>
<span>Third Panel</span>
</div>
</HeaderTemplate>
<ContentTemplate>
<div>Click anywhere except the icon to interact</div>
</ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.panel-header {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
background-color: #f0f0f0;
}
.drag-icon {
cursor: move;
font-weight: bold;
color: #666;
}
.e-panel-content {
padding: 15px;
}
</style>Getting Started with Dashboard Layout
Table of Contents
- WebAssembly App Setup
- Server App Setup
- Web App Setup
- Basic Component Usage
- Panels with Headers and Content
WebAssembly App Setup
Prerequisites
- System requirements for Blazor components
Create Blazor WebAssembly App
You can create a Blazor WebAssembly App using:
- Microsoft Templates in Visual Studio
- Syncfusion Blazor Extension
- Visual Studio Code with templates
- .NET CLI with command:
dotnet new blazorwasm -o BlazorApp
Install NuGet Packages
Install the following NuGet packages using NuGet Package Manager or dotnet CLI:
Syncfusion.Blazor.Layouts
Syncfusion.Blazor.ThemesVia Package Manager Console:
Install-Package Syncfusion.Blazor.Layouts
Install-Package Syncfusion.Blazor.ThemesVia dotnet CLI:
dotnet add package Syncfusion.Blazor.Layouts
dotnet add package Syncfusion.Blazor.Themes
dotnet restoreAdd Import Namespaces
Open ~/_Imports.razor file and add:
@using Syncfusion.Blazor
@using Syncfusion.Blazor.LayoutsRegister Syncfusion Service
In Program.cs, add:
using Syncfusion.Blazor;
...
builder.Services.AddSyncfusionBlazor();
...Add StyleSheet and Script Resources
In ~/Components/App.razor or your main layout file, add stylesheet and script:
<link href="_content/Syncfusion.Blazor.Themes/fluent2.css" rel="stylesheet" />
...
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>Server App Setup
Prerequisites
- System requirements for Blazor components
Create Blazor Server App
Create a Blazor Server App (Blazor Web App with Server rendering) using:
- Microsoft Templates via Blazor Web App option
- Syncfusion Blazor Extension
- .NET CLI:
dotnet new blazor -o BlazorApp -int Server
Install NuGet Packages
Same as WebAssembly:
Install-Package Syncfusion.Blazor.Layouts
Install-Package Syncfusion.Blazor.ThemesAdd Import Namespaces
In ~/_Imports.razor, add:
@using Syncfusion.Blazor
@using Syncfusion.Blazor.LayoutsRegister Syncfusion Service
In Program.cs, add:
using Syncfusion.Blazor;
...
builder.Services.AddSyncfusionBlazor();
...Add StyleSheet and Script Resources
In ~/Components/App.razor, add:
<link href="_content/Syncfusion.Blazor.Themes/fluent2.css" rel="stylesheet" />
...
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>Add Dashboard Layout Component
In your razor page (e.g., ~/Components/Pages/Home.razor), if using per-page interactivity, define render mode:
@rendermode InteractiveServerThen add the component:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout>
<DashboardLayoutPanels>
<DashboardLayoutPanel>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>Press Ctrl+F5 (Windows) or ⌘+F5 (macOS) to launch.
Web App Setup
Prerequisites
- System requirements for Blazor components
Create Blazor Web App
Create a Blazor Web App using:
- Microsoft Templates with appropriate interactive render mode
- Syncfusion Blazor Extension
- .NET CLI:
dotnet new blazor -o BlazorWebApp -int Auto
For WebAssembly or Auto mode: Navigate to client project before installing packages.
Install NuGet Packages
Install-Package Syncfusion.Blazor.Layouts
Install-Package Syncfusion.Blazor.ThemesIf using WebAssembly or Auto mode, install in the client project.
Add Import Namespaces
In ~/_Imports.razor (client project for WebAssembly/Auto), add:
@using Syncfusion.Blazor
@using Syncfusion.Blazor.LayoutsRegister Syncfusion Service
In Program.cs of Blazor Web App (server project):
using Syncfusion.Blazor;
...
builder.Services.AddSyncfusionBlazor();
...If using WebAssembly or Auto mode, register in both server and client Program.cs files.
Add StyleSheet and Script Resources
In ~/Components/App.razor, add:
<link href="_content/Syncfusion.Blazor.Themes/fluent2.css" rel="stylesheet" />
...
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>Add Dashboard Layout Component
In your razor page, define render mode if per-page interactivity:
@rendermode InteractiveAutoOr appropriate mode: InteractiveServer, InteractiveWebAssembly, InteractiveAuto.
Then add component:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout>
<DashboardLayoutPanels>
<DashboardLayoutPanel></DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>Basic Component Usage
Minimal Dashboard
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout>
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<ContentTemplate><div>Panel 1</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>Dashboard with Grid Configuration
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout CellSpacing="@(new double[]{10, 10})" Columns="5">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<ContentTemplate><div>Panel 1</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Column=1>
<ContentTemplate><div>Panel 2</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Column=2>
<ContentTemplate><div>Panel 3</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>Panels with Headers and Content
Using HeaderTemplate and ContentTemplate
The HeaderTemplate displays a title or summary at the top of each panel. The ContentTemplate holds the main panel content.
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout CellSpacing="@(new double[]{10, 10})" Columns="5">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<HeaderTemplate><div>Panel 1</div></HeaderTemplate>
<ContentTemplate><div>Panel Content</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<HeaderTemplate><div>Panel 2</div></HeaderTemplate>
<ContentTemplate><div>Panel Content</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=2 Column=3>
<HeaderTemplate><div>Panel 3</div></HeaderTemplate>
<ContentTemplate><div>Panel Content</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Row=1>
<HeaderTemplate><div>Panel 4</div></HeaderTemplate>
<ContentTemplate><div>Panel Content</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-header {
background-color: rgba(0, 0, 0, .1);
text-align: center;
}
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>Hosting Components in Panels
Beyond simple content, panels can host complex Syncfusion Blazor components:
@using Syncfusion.Blazor.Layouts
@using Syncfusion.Blazor.Charts // Example: for charts
<SfDashboardLayout CellSpacing="@(new double[]{10, 10})" Columns="5">
<DashboardLayoutPanels>
<DashboardLayoutPanel SizeX=2 SizeY=2>
<HeaderTemplate><div>Chart</div></HeaderTemplate>
<ContentTemplate>
<SfChart>
<!-- Chart configuration -->
</SfChart>
</ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>Replace SfChart with any other Syncfusion component like SfGrid, SfAccumulationChart, SfGauge, etc.
Styling Headers and Content
Use CSS to customize appearance:
.e-panel-header {
background-color: #334099;
color: white;
padding: 10px;
font-weight: bold;
}
.e-panel-content {
background-color: #f5f5f5;
padding: 20px;
}Grid Configuration and Styling
Table of Contents
- Grid Structure
- Configuring Columns
- Cell Aspect Ratio
- Cell Spacing
- Visualizing Grid Lines
- CSS Customization
Grid Structure
The Dashboard Layout is built on a grid system divided into equally-sized cells. All positioning and sizing is based on these grid cells.
Key Properties:
- Columns: Number of cells per row
- CellAspectRatio: Height-to-width ratio of cells
- CellSpacing: Gap between cells
- ShowGridLines: Make grid visible for design
Configuring Columns
Columns Property
The Columns property specifies how many equal-width cells fit in each row:
@using Syncfusion.Blazor.Layouts
<!-- 5 columns per row -->
<SfDashboardLayout Columns="5">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<ContentTemplate><div>Panel 1 (1 cell wide)</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Column=1>
<ContentTemplate><div>Panel 2 (1 cell wide)</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Column=2>
<ContentTemplate><div>Panel 3 (1 cell wide)</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Column=3>
<ContentTemplate><div>Panel 4 (1 cell wide)</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Column=4>
<ContentTemplate><div>Panel 5 (1 cell wide)</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
padding: 10px;
}
</style>Common Column Configurations
| Value | Layout | Use Case |
|---|---|---|
| 1 | Single column (full width) | Mobile or stacked layouts |
| 2 | Two equal columns | 50/50 split |
| 3 | Three equal columns | Trisection layout |
| 4 | Four columns | 25% grid, 1/2/3 panel layouts |
| 5 | Five columns | Mixed 1/2/1.5 sizing |
| 6 | Six columns | 50%, 33%, 16.67% combinations |
| 12 | Twelve columns | Bootstrap-like system |
Multi-Row Layouts
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout CellSpacing="@(new double[]{10, 10})" Columns="6">
<DashboardLayoutPanels>
<!-- Row 1: 3 panels of 2 cells each -->
<DashboardLayoutPanel SizeX=2>
<ContentTemplate><div>Panel 1 (2x1)</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 Column=2>
<ContentTemplate><div>Panel 2 (2x1)</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 Column=4>
<ContentTemplate><div>Panel 3 (2x1)</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Row 2: 2 panels -->
<DashboardLayoutPanel SizeX=3 Row=1>
<ContentTemplate><div>Panel 4 (3x1)</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=3 Row=1 Column=3>
<ContentTemplate><div>Panel 5 (3x1)</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
padding: 10px;
}
</style>Cell Aspect Ratio
CellAspectRatio Property
Controls the height-to-width ratio of grid cells. The aspect ratio is calculated as width / height.
@using Syncfusion.Blazor.Layouts
<!-- CellAspectRatio = 2 means width is 2x the height -->
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
CellAspectRatio="2"
Columns="5">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<ContentTemplate><div>0</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<ContentTemplate><div>1</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=2 Column=3>
<ContentTemplate><div>2</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Row=1>
<ContentTemplate><div>3</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>AspectRatio Calculations
| Ratio | Formula | Result |
|---|---|---|
| 1 | 100px width / 100px height | Square cells |
| 2 | 100px width / 50px height | Wide, short cells |
| 0.5 | 100px width / 200px height | Narrow, tall cells |
| 3 | 100px width / 33.33px height | Very wide, short |
| 0.75 | 100px width / 133.33px height | Slightly tall |
Example: For 100px cell width:
- AspectRatio 2 → 50px height
- AspectRatio 1 → 100px height
- AspectRatio 0.5 → 200px height
Use Cases
Wide Cells (AspectRatio > 1): Charts, graphs, timeline visualizations
<SfDashboardLayout CellAspectRatio="2.5" Columns="4">
<!-- Cells are approximately 2.5x wider than tall -->
</SfDashboardLayout>Square Cells (AspectRatio = 1): Even distribution, balanced panels
<SfDashboardLayout CellAspectRatio="1" Columns="5">
<!-- Square cells -->
</SfDashboardLayout>Tall Cells (AspectRatio < 1): Text-heavy content, forms
<SfDashboardLayout CellAspectRatio="0.5" Columns="3">
<!-- Cells are taller than wide -->
</SfDashboardLayout>Cell Spacing
CellSpacing Property
Defines the gap between panels in both horizontal and vertical directions.
@using Syncfusion.Blazor.Layouts
<!-- [row spacing, column spacing] -->
<SfDashboardLayout
CellSpacing="@(new double[]{20, 20})"
Columns="5">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<ContentTemplate><div>0</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<ContentTemplate><div>1</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=2 Column=3>
<ContentTemplate><div>2</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Row=1>
<ContentTemplate><div>3</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>Spacing Format
CellSpacing is a double array: [verticalGap, horizontalGap]
// 10px spacing between all panels
CellSpacing="@(new double[]{10, 10})"
// 15px vertical, 5px horizontal spacing
CellSpacing="@(new double[]{15, 5})"
// Dense layout
CellSpacing="@(new double[]{5, 5})"
// Loose layout
CellSpacing="@(new double[]{25, 25})"Impact on Layout
| Spacing | Effect | Use Case |
|---|---|---|
| [5, 5] | Compact, minimal gaps | Dense dashboards |
| [10, 10] | Standard, clean gaps | Most dashboards |
| [15, 15] | Spacious, readable | Data-heavy displays |
| [20, 20] | Very spacious, clear | Minimal content per panel |
Visualizing Grid Lines
ShowGridLines Property
Makes the underlying grid structure visible during design and layout development:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
Columns="5"
ShowGridLines="true">
<DashboardLayoutPanels>
<DashboardLayoutPanel Column=1>
<ContentTemplate><div>0</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=1 SizeY=2 Column=2>
<ContentTemplate><div>1</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=1 Column=3>
<ContentTemplate><div>2</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Row=1 Column=3>
<ContentTemplate><div>3</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>Benefits of ShowGridLines:
- Visualize grid cell divisions
- Debug panel positioning
- Verify Row/Column assignments
- Design layout more accurately
- Identify size misalignments
Development Workflow: 1. Enable ShowGridLines during design 2. Position and size panels visually 3. Verify Row/Column and SizeX/SizeY values 4. Disable ShowGridLines for production 5. Deploy final layout
CSS Customization
Customizing Panel Headers
.e-dashboardlayout.e-control .e-panel .e-panel-container .e-panel-header {
color: #754131;
background-color: #c9e2f7;
text-align: center;
}Customizing Panel Content
.e-dashboardlayout.e-control .e-panel .e-panel-container .e-panel-content {
background-color: #c9e2f7;
padding: 50px;
}Customizing Resize Icon
.e-dashboardlayout.e-control .e-panel .e-panel-container .e-resize.e-double {
color: #0378d5;
font-size: 30px;
height: 20px;
width: 20px;
}Customizing Background
.e-dashboardlayout.e-control.e-responsive {
background: #b3d3ed;
}Complete Styling Example
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
Columns="5">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<HeaderTemplate><div>Styled Panel</div></HeaderTemplate>
<ContentTemplate><div>Content with custom styling</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
/* Dashboard background -->
.e-dashboardlayout.e-control.e-responsive {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
/* Panel headers -->
.e-dashboardlayout.e-control .e-panel .e-panel-container .e-panel-header {
background: linear-gradient(to right, #667eea 0%, #764ba2 100%);
color: white;
padding: 12px;
font-weight: bold;
border-radius: 4px 4px 0 0;
}
/* Panel content -->
.e-dashboardlayout.e-control .e-panel .e-panel-container .e-panel-content {
background-color: white;
padding: 15px;
border-radius: 0 0 4px 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
/* Resize icon -->
.e-dashboardlayout.e-control .e-panel .e-panel-container .e-resize.e-double {
color: #667eea;
opacity: 0.6;
transition: opacity 0.3s;
}
.e-dashboardlayout.e-control .e-panel:hover .e-resize.e-double {
opacity: 1;
}
</style>Panel Positioning and Sizing
Table of Contents
Panel Properties
Each DashboardLayoutPanel has the following key properties:
| Property | Default | Description |
|---|---|---|
| Id | null | Unique identifier for the panel |
| Row | 0 | Vertical position in grid (0-based) |
| Column | 0 | Horizontal position in grid (0-based) |
| SizeX | 1 | Panel width in cells |
| SizeY | 1 | Panel height in cells |
| MinSizeX | 1 | Minimum width in cells |
| MinSizeY | 1 | Minimum height in cells |
| MaxSizeX | null | Maximum width in cells (null = unlimited) |
| MaxSizeY | null | Maximum height in cells (null = unlimited) |
| HeaderTemplate | null | Template for panel header |
| ContentTemplate | null | Template for panel content |
| CssClass | null | Custom CSS class for styling |
Positioning Panels
Row and Column Properties
Panels are positioned using Row and Column properties. Both are 0-based indices on the dashboard grid.
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout CellSpacing="@(new double[]{20, 20})" Columns="4">
<DashboardLayoutPanels>
<!-- Panel at Row 0, Column 0 (default) -->
<DashboardLayoutPanel>
<ContentTemplate><div>1</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Panel at Row 0, Column 1 -->
<DashboardLayoutPanel Column=1>
<ContentTemplate><div>2</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Panel at Row 0, Column 2 -->
<DashboardLayoutPanel Column=2>
<ContentTemplate><div>3</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Panel at Row 1, Column 0 -->
<DashboardLayoutPanel Row=1>
<ContentTemplate><div>4</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Panel at Row 1, Column 1 -->
<DashboardLayoutPanel Row=1 Column=1>
<ContentTemplate><div>5</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Panel at Row 1, Column 2 -->
<DashboardLayoutPanel Row=1 Column=2>
<ContentTemplate><div>6</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>Key Points:
Rowspecifies the row position (0 = first row, 1 = second row, etc.)Columnspecifies the column position (0 = first column, 1 = second column, etc.)- Grid arrangement depends on the Columns property (how many columns fit per row)
- Panels are automatically arranged left-to-right, top-to-bottom when you don't specify positions
Sizing Panels
SizeX and SizeY Properties
Panel dimensions are defined in cells:
- SizeX: Width in cells (default = 1)
- SizeY: Height in cells (default = 1)
The actual pixel size depends on your grid configuration (Columns, CellAspectRatio, container width).
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout CellSpacing="@(new double[]{10, 10})" Columns="5">
<DashboardLayoutPanels>
<!-- Single cell panel (1x1) -->
<DashboardLayoutPanel>
<ContentTemplate><div>0</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- 2 cells wide, 2 cells tall -->
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<ContentTemplate><div>1</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- 1 cell wide, 2 cells tall -->
<DashboardLayoutPanel SizeY=2 Column=3>
<ContentTemplate><div>2</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Single cell at next row -->
<DashboardLayoutPanel Row=1>
<ContentTemplate><div>3</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>Sizing Guidelines:
- Start with SizeX=1 and SizeY=1 (default single cell)
- Use larger values for panels that need more space
- Make sure SizeX + Column ≤ Columns property (avoid overflow)
- Cell aspect ratio affects actual panel height
Size Constraints
Minimum and Maximum Sizes
Control what sizes users can resize panels to:
<DashboardLayoutPanel
SizeX=2
SizeY=2
MinSizeX=1
MinSizeY=1
MaxSizeX=4
MaxSizeY=4>
<ContentTemplate><div>Resizable Panel</div></ContentTemplate>
</DashboardLayoutPanel>Properties:
- MinSizeX: Minimum width users can resize to (default = 1)
- MinSizeY: Minimum height users can resize to (default = 1)
- MaxSizeX: Maximum width users can resize to (null = no limit)
- MaxSizeY: Maximum height users can resize to (null = no limit)
Preventing Extreme Resizing
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
Columns="5"
AllowResizing="true">
<DashboardLayoutPanels>
<!-- User can resize between 2x2 and 4x4 cells -->
<DashboardLayoutPanel
SizeX=2
SizeY=2
MinSizeX=2
MinSizeY=2
MaxSizeX=4
MaxSizeY=4>
<HeaderTemplate><div>Constrained Panel</div></HeaderTemplate>
<ContentTemplate><div>Content</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Standard panel, can be resized to any size -->
<DashboardLayoutPanel Column=2>
<HeaderTemplate><div>Flexible Panel</div></HeaderTemplate>
<ContentTemplate><div>Content</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Panel with minimum size only -->
<DashboardLayoutPanel
SizeX=2
Column=3
MinSizeX=1
MinSizeY=1>
<HeaderTemplate><div>Min Constrained</div></HeaderTemplate>
<ContentTemplate><div>Content</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>Constraint Behavior:
- Min constraints prevent panels from becoming too small
- Max constraints prevent panels from becoming too large
- If MaxSizeX is null, no upper limit applies
- Apply constraints to ensure usable minimum content area
Panel Identification
Using the Id Property
Each panel should have a unique identifier:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout>
<DashboardLayoutPanels>
<DashboardLayoutPanel Id="panel-metrics">
<ContentTemplate><div>Metrics Panel</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Id="panel-chart" Column=1>
<ContentTemplate><div>Chart Panel</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Id="panel-table" Column=2>
<ContentTemplate><div>Table Panel</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>Important for:
- State persistence (ID is required to save/restore layout)
- Identifying panels in dynamic scenarios
- Preventing panel overlap when rendering dynamically
- Tracking specific panels in code
Dynamic Panel Generation
When generating panels dynamically, ensure unique IDs:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout CellSpacing="@(new double[]{20, 20})" Columns="4">
<DashboardLayoutPanels>
@foreach (var panel in PanelItems)
{
<DashboardLayoutPanel
Id="@panel.Id"
Row="@panel.Row"
Column="@panel.Column">
<ContentTemplate>
<div class="panel-content">@panel.Content</div>
</ContentTemplate>
</DashboardLayoutPanel>
}
</DashboardLayoutPanels>
</SfDashboardLayout>
@code {
public class PanelModel
{
public string Id { get; set; }
public int Row { get; set; } = 0;
public int Column { get; set; } = 0;
public string Content { get; set; }
}
private List<PanelModel> PanelItems = new List<PanelModel>
{
new PanelModel { Id = "panel1", Row = 0, Column = 0, Content = "Panel 1" },
new PanelModel { Id = "panel2", Row = 0, Column = 1, Content = "Panel 2" },
new PanelModel { Id = "panel3", Row = 0, Column = 2, Content = "Panel 3" },
new PanelModel { Id = "panel4", Row = 1, Column = 0, Content = "Panel 4" },
new PanelModel { Id = "panel5", Row = 1, Column = 1, Content = "Panel 5" },
new PanelModel { Id = "panel6", Row = 1, Column = 2, Content = "Panel 6" }
};
}
<style>
.panel-content {
text-align: center;
margin-top: 10px;
font-size: 18px;
font-weight: 500;
}
</style>Best Practices:
- Always assign unique IDs when rendering panels dynamically
- Use descriptive ID names (e.g., "panel-metrics", "panel-chart")
- IDs are critical for preventing overlaps in dynamic scenarios
- Include IDs in your data model during dynamic generation
Resizing and Floating Panels
Table of Contents
Panel Resizing
Enabling Panel Resizing
Use the AllowResizing property to enable users to dynamically adjust panel dimensions:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
Columns="5"
CellAspectRatio="2"
AllowResizing="true">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<ContentTemplate><div>0</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<ContentTemplate><div>1</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=2 Column=3>
<ContentTemplate><div>2</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Row=1>
<ContentTemplate><div>3</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>Default Resize Behavior
When AllowResizing="true":
- Resize handle appears in the south-east corner (bottom-right) of each panel
- Users drag the handle to resize the panel
- Resize icon Class:
.e-resize.e-double - Only south-east direction is active by default
Resize Directions
ResizableHandles Property
Customize which directions panels can be resized:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
Columns="5"
CellAspectRatio="2"
AllowResizing="true"
ResizableHandles="e,south-east,west,south">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<ContentTemplate><div>0</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<ContentTemplate><div>1</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=2 Column=3>
<ContentTemplate><div>2</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Row=1>
<ContentTemplate><div>3</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>Available Resize Directions
The ResizableHandles property accepts comma-separated values:
| Direction | Abbreviation | Handle Position | Use Case |
|---|---|---|---|
| East | e | Right side | Resize width only |
| West | w | Left side | Resize from left |
| South | s | Bottom | Resize height only |
| North | n | Top | Resize from top |
| South-East | south-east | Bottom-right corner | Default, both dimensions |
| South-West | south-west | Bottom-left corner | Both dimensions from left |
| North-East | north-east | Top-right corner | Both dimensions from top |
| North-West | north-west | Top-left corner | Both dimensions from top-left |
Common Resize Configurations
Only Horizontal Resizing:
ResizableHandles="e,w"Only Vertical Resizing:
ResizableHandles="s,n"All Directions:
ResizableHandles="e,w,s,n,south-east,south-west,north-east,north-west"Corner Only (Default Behavior):
ResizableHandles="south-east"Floating Panels
AllowFloating Property
Floating allows panels to automatically move upward to fill empty cells in preceding rows, optimizing space utilization:
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
Columns="5"
CellAspectRatio="2"
AllowFloating="true">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<ContentTemplate><div>0</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<ContentTemplate><div>1</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=2 Column=3>
<ContentTemplate><div>2</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Row=1>
<ContentTemplate><div>3</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-content {
text-align: center;
margin-top: 10px;
}
</style>Floating Behavior
When AllowFloating="true": 1. Panels automatically float upward to fill empty cells 2. Empty spaces in preceding rows are occupied first 3. Maintains compact, optimized layout 4. Applies during panel drag operations 5. Applies when panels are resized
When to Use Floating
Use floating when:
- You want maximum space efficiency
- Panels of varying sizes need to coexist
- You want automatic layout optimization
- Space utilization is critical
Avoid floating when:
- You want explicit control over panel positions
- Users expect panels to stay in defined rows
- You need predictable layout structure
Combining Resizing and Floating
Full Interactive Layout
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
Columns="5"
CellAspectRatio="2"
AllowDragging="true"
AllowResizing="true"
AllowFloating="true">
<DashboardLayoutPanels>
<DashboardLayoutPanel>
<HeaderTemplate><div>Panel 1</div></HeaderTemplate>
<ContentTemplate><div>Draggable, Resizable, Floatable</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=2 SizeY=2 Column=1>
<HeaderTemplate><div>Panel 2 (2x2)</div></HeaderTemplate>
<ContentTemplate><div>All interactions enabled</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeY=2 Column=3>
<HeaderTemplate><div>Panel 3</div></HeaderTemplate>
<ContentTemplate><div>Full interactivity</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel Row=1>
<HeaderTemplate><div>Panel 4</div></HeaderTemplate>
<ContentTemplate><div>Drag, Resize, Float</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-header {
background-color: rgba(0, 0, 0, .1);
text-align: center;
padding: 10px;
}
.e-panel-content {
text-align: center;
margin-top: 10px;
padding: 10px;
}
</style>Practical Examples
Example 1: Admin Dashboard with Constrained Resizing
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{10, 10})"
Columns="6"
AllowResizing="true"
ResizableHandles="south-east">
<DashboardLayoutPanels>
<!-- Metrics cards - minimal resize -->
<DashboardLayoutPanel
SizeX=2
MinSizeX=2
MinSizeY=1>
<HeaderTemplate><div>Sessions</div></HeaderTemplate>
<ContentTemplate><div class="metric">124,444</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel
SizeX=2
Column=2
MinSizeX=2
MinSizeY=1>
<HeaderTemplate><div>Users</div></HeaderTemplate>
<ContentTemplate><div class="metric">64,496</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel
SizeX=2
Column=4
MinSizeX=2
MinSizeY=1>
<HeaderTemplate><div>Views</div></HeaderTemplate>
<ContentTemplate><div class="metric">442,278</div></ContentTemplate>
</DashboardLayoutPanel>
<!-- Charts - flexible resizing -->
<DashboardLayoutPanel
SizeX=3
SizeY=2
Row=1
MinSizeX=2
MaxSizeX=4>
<HeaderTemplate><div>Chart 1</div></HeaderTemplate>
<ContentTemplate><div>Chart visualization</div></ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel
SizeX=3
SizeY=2
Row=1
Column=3
MinSizeX=2
MaxSizeX=4>
<HeaderTemplate><div>Chart 2</div></HeaderTemplate>
<ContentTemplate><div>Chart visualization</div></ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.metric {
font-size: 24px;
font-weight: bold;
text-align: center;
padding: 20px;
color: #334099;
}
.e-panel-header {
background-color: #f5f5f5;
padding: 8px;
font-weight: bold;
}
.e-panel-content {
padding: 10px;
}
</style>Example 2: Responsive Workspace with Full Interactivity
@using Syncfusion.Blazor.Layouts
<SfDashboardLayout
CellSpacing="@(new double[]{8, 8})"
Columns="12"
AllowDragging="true"
AllowResizing="true"
AllowFloating="true"
ResizableHandles="e,s,south-east">
<DashboardLayoutPanels>
<DashboardLayoutPanel SizeX=6 SizeY=3>
<HeaderTemplate><div>Main Chart</div></HeaderTemplate>
<ContentTemplate>
<div>Large chart area - drag to rearrange, resize from edges</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=6 SizeY=3 Column=6>
<HeaderTemplate><div>Data Grid</div></HeaderTemplate>
<ContentTemplate>
<div>Data table - fully interactive</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=3 SizeY=2 Row=3>
<HeaderTemplate><div>Widget 1</div></HeaderTemplate>
<ContentTemplate>
<div>Metric widget</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=3 SizeY=2 Row=3 Column=3>
<HeaderTemplate><div>Widget 2</div></HeaderTemplate>
<ContentTemplate>
<div>Status widget</div>
</ContentTemplate>
</DashboardLayoutPanel>
<DashboardLayoutPanel SizeX=6 SizeY=2 Row=3 Column=6>
<HeaderTemplate><div>Timeline</div></HeaderTemplate>
<ContentTemplate>
<div>Timeline visualization</div>
</ContentTemplate>
</DashboardLayoutPanel>
</DashboardLayoutPanels>
</SfDashboardLayout>
<style>
.e-panel-header {
background-color: #334099;
color: white;
padding: 12px;
font-weight: bold;
}
.e-panel-content {
padding: 15px;
background-color: #fafafa;
}
</style>Customizing Resize Icon
The resize icon can be customized via CSS:
.e-dashboardlayout.e-control .e-panel .e-panel-container .e-resize.e-double {
color: #0378d5;
font-size: 30px;
height: 20px;
width: 20px;
}