syncfusion-blazor-diagram — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited syncfusion-blazor-diagram (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A comprehensive skill for building interactive diagrams with the Syncfusion Blazor Diagram component — flowcharts, organizational charts, mind maps, BPMN process diagrams, UML sequence diagrams, network diagrams, and more.
Use this skill when you need to:
SfDiagramComponent, nodes, connectors, or shapesAPI Verification Required: Always verify API class names, properties, and signatures by reading reference files (references/*.md) BEFORE generating code examples. Do not assume or infer class names. ⚠️ Before writing ANY code, review the Common Mistakes section directly below to avoid known invalid APIs and properties.
@using Syncfusion.Blazor.Diagram
<SfDiagramComponent Width="100%" Height="600px" Nodes="@nodes" Connectors="@connectors" />
@code {
DiagramObjectCollection<Node> nodes = new DiagramObjectCollection<Node>
{
new Node
{
ID = "node1", OffsetX = 150, OffsetY = 150,
Width = 100, Height = 50,
Style = new ShapeStyle { Fill = "#6BA5D7", StrokeColor = "white" },
Annotations = new DiagramObjectCollection<ShapeAnnotation>
{
new ShapeAnnotation { Content = "Start" }
}
}
};
DiagramObjectCollection<Connector> connectors = new DiagramObjectCollection<Connector>
{
new Connector { ID = "conn1", SourceID = "node1", TargetID = "node2" }
};
}| Goal | Reference |
|---|---|
| First diagram setup | references/getting-started.md |
| Add/configure nodes | references/nodes.md |
| Add/configure connectors | references/connectors.md |
| Use built-in shapes | references/shapes.md |
| Add text labels | references/annotations.md |
| Define connection points | references/ports.md |
| Org charts / auto-layout | references/layout.md |
| Swimlane diagrams | references/swimlane.md |
| BPMN process diagrams | references/bpmn.md |
| Drag-and-drop palette | references/symbol-palette.md |
| Bind data to diagram | references/data-binding.md |
| Selection, drag, zoom | references/interaction.md |
| Handle diagram events | references/events.md |
| Save and load diagrams | references/serialization.md |
| Export / print | references/export-print.md |
| CSS / theme styling | references/styling.md |
| UML sequence diagrams | references/uml-sequence.md |
| Real-time collaboration | references/collaborative-editing.md |
| Context menu, tooltips, rulers, localization | references/advanced-features.md |
| Miniature overview / bird's-eye navigation | references/overview-component.md |
📄 Read: references/getting-started.md
Syncfusion.Blazor.Diagram)📄 Read: references/nodes.md
📄 Read: references/connectors.md
📄 Read: references/shapes.md
📄 Read: references/annotations.md
📄 Read: references/ports.md
📄 Read: references/layout.md
await DoLayoutAsync() — refresh layout at runtime after adding/removing nodes📄 Read: references/swimlane.md
<SfDiagramComponent Height="600px" Swimlanes="@swimlanes" />
@code {
DiagramObjectCollection<Swimlane> swimlanes = new();
protected override void OnInitialized()
{
swimlanes.Add(new Swimlane
{
ID = "swimlane1",
OffsetX = 400, OffsetY = 300,
Width = 600, Height = 200,
Lanes = new DiagramObjectCollection<Lane>()
{
new Lane(){
Height = 100,
Header = new SwimlaneHeader(){
Width = 30,
Annotation = new ShapeAnnotation(){ Content = "Consumer" }
},
Children = new DiagramObjectCollection<Node>()
{
new Node(){Height = 50, Width = 50, LaneOffsetX = 250, LaneOffsetY = 30},
}
},
}
});
}
}📄 Read: references/bpmn.md
// Exclusive gateway (XOR)
nodes.Add(new Node
{
ID = "gateway1", OffsetX = 300, OffsetY = 200, Width = 50, Height = 50,
Shape = new BpmnGateway
{
GatewayType = BpmnGatewayType.Exclusive
}
});📄 Read: references/symbol-palette.md
SfSymbolPaletteComponent📄 Read: references/data-binding.md
await ReadDataAsync(query?), await InsertDataAsync(data), await UpdateDataAsync(keyField, data), await DeleteDataAsync(keyField, value)await RefreshDataSourceAsync() — reload all data and rebuild layout📄 Read: references/interaction.md
Select(collection, multipleSelection?), SelectAll(), UnSelect(obj), ClearSelection()Drag(obj, tx, ty), Rotate(obj, angle, pivot?), Scale(obj, sx, sy, pivot)Zoom(factor, focusPoint), ResetZoom(), Pan(hOffset, vOffset, focusPoint?)BringIntoView(DiagramRect) — scroll viewport to show a regionBringIntoCenter(DiagramRect) — scroll viewport to center a regionFitToPage(FitOptions?) — fit content to viewport (sync; FitMode.Width/Height/Both, DiagramRegion.Content/PageSettings)Nudge(Direction, int?) — move selected elements by pixels; default 1px; Direction.Top/Bottom/Left/RightBringToFront(), BringForward(), SendBackward(), SendToBack() — must Select() firstCopy(), Cut(), Paste(collection?), Delete(collection?)Group(), Ungroup(), AddChildAsync(group, child), RemoveChild(group, child)StartTextEdit(obj, annotationId?)CommandManager (custom/override shortcuts via child component)CommandManager uses KeyboardCommand + KeyGesture (DiagramKeys + ModifierKeys) + CommandKeyArgsSetAlign, SetDistribute, SetSameSize — all sync)Undo(), Redo() (sync); StartGroupAction() / EndGroupAction() for batched undo stepsAddHistoryEntry(entry), ClearHistory()GetObject(id), GetPageBounds(x?, y?), Clear() (removes all elements)BeginUpdate() + await EndUpdateAsync() — group multiple changes into one render passawait AddDiagramElementsAsync(DiagramObjectCollection<NodeBase>)📄 Read: references/events.md
📄 Read: references/serialization.md
📄 Read: references/export-print.md
📄 Read: references/styling.md
CssClass property)📄 Read: references/uml-sequence.md
await UpdateFromModelAsync() — refresh diagram after programmatic model changes📄 Read: references/collaborative-editing.md
GetDiagramUpdates(HistoryChangedEventArgs) + await SetDiagramUpdatesAsync(updates) — efficient change propagation📄 Read: references/overview-component.md
SfDiagramOverviewComponent as a miniature thumbnail panelSourceID / IDWidth and HeightDiagramOverviewConstraints@using Syncfusion.Blazor.Diagram.Overview namespace.@using Syncfusion.Blazor.Diagram
@using Syncfusion.Blazor.Diagram.Overview
@using System.Collections.ObjectModel
<SfDiagramComponent ID="element"
Width="100%"
Height="500px">
</SfDiagramComponent>
<!-- Overview panel linked to the diagram above -->
<SfDiagramOverviewComponent Height="150px" SourceID="element" />📄 Read: references/advanced-features.md
await ShowTooltipAsync(obj) / await HideTooltipAsync(obj) — requires OpensOn = "Custom"#### Annotation Editing
⚠️ `AllowEditing` does NOT exist onShapeAnnotationorPathAnnotation. Inline editing is on by default — no property is needed to enable it. To disable editing, setConstraints = AnnotationConstraints.ReadOnly: ```csharp // ❌ Wrong — CS0117: AllowEditing does not exist new ShapeAnnotation { Content = "Label", AllowEditing = false }
>
// ✅ Correct — use AnnotationConstraints.ReadOnly to disable editing new ShapeAnnotation { Content = "Label", Constraints = AnnotationConstraints.ReadOnly } ```
#### EndUpdateAsync Method
⚠️ Always use `EndUpdateAsync()` (async) —EndUpdate()(sync, non-async) does NOT exist and will cause a compile error. UseBeginUpdate()/EndUpdateAsync()when changing multiple properties at once —awaitis required: ```csharp // ❌ Wrong — EndUpdate() does not exist diagram.BeginUpdate(); // ... changes ... diagram.EndUpdate();
>
// ✅ Correct — EndUpdateAsync is async diagram.BeginUpdate(); // ... changes ... await diagram.EndUpdateAsync(); ```
#### Click Event
⚠️ `ClickEventArgs` name collision: If your page also uses@using Syncfusion.Blazor.Navigations(or Buttons),ClickEventArgsbecomes ambiguous. Always qualify it: ``csharp // ✅ Use the fully qualified type in the handler signature private void OnClick(Syncfusion.Blazor.Diagram.ClickEventArgs args) { }``
⚠️ `args.Count` is NOT an `int` field — it is a method that returns anint. Do NOT compare it directly with==inline without storing the result first: ```csharp // ❌ Wrong — CS0019: Operator '==' cannot be applied to operands of type 'method group' and 'int' if (args.Count == 2)
>
// ✅ Correct — store result then compare int clickCount = args.Count; if (clickCount == 2) { / double-click / } ```
#### SizeChanged Event
⚠️ `SizeChangedEventArgs.Element` is typed as `DiagramSelectionSettings`, notNode. Pattern-matchingargs.Element is Node nalways fails withCS8121. Cast toDiagramSelectionSettingsand read.Nodes[0]to get the resized node: ```csharp // ❌ Wrong — CS8121: DiagramSelectionSettings cannot match Node if (args.Element is Node n) { }
>
// ✅ Correct — Element is DiagramSelectionSettings if (args.Element is DiagramSelectionSettings sel && sel.Nodes.Count > 0) { var node = sel.Nodes[0]; double w = args.NewValue.Width; double h = args.NewValue.Height; } ```
⚠️ `args.NewValue.Width` and `args.NewValue.Height` are plain `double`, notdouble?. Using??on them causesCS0019. Assign them directly: ```csharp // ❌ Wrong — CS0019 double w = args.NewValue.Width ?? 0;
>
// ✅ Correct double w = args.NewValue.Width; ```
#### Selection Changed Event
⚠️ `SelectionChangedEventArgs` name collision: If your page also uses@using Syncfusion.Blazor.Buttons(or other Syncfusion packages),SelectionChangedEventArgsbecomes ambiguous. Always qualify it: ``csharp // ✅ Fully qualified private void OnSelectionChanged(Syncfusion.Blazor.Diagram.SelectionChangedEventArgs args) { }``
⚠️ `args.NewValue` is a `DiagramSelectionSettings` object — NOT a `Node`, NOT a collection: - Pattern-matchingargs.NewValue is Nodealways fails withCS8121- Iteratingargs.NewValueas a collection fails — it is a single settings object - The only correct approach is to read_diagram.SelectionSettings.Nodes/.Connectors: ```csharp // ❌ Wrong — CS8121: DiagramSelectionSettings cannot match Node if (args.NewValue is Node n) { }
>
// ❌ Wrong — DiagramSelectionSettings is not IEnumerable foreach (var item in args.NewValue) { }
>
// ✅ Correct — use SelectionSettings on the diagram reference foreach (var node in _diagram.SelectionSettings.Nodes) Console.WriteLine(node.ID); foreach (var conn in _diagram.SelectionSettings.Connectors) Console.WriteLine(conn.ID); ```
#### Text Changed Event
⚠️ `TextChangedEventArgs` does NOT exist — using it causesCS0246. The correct event args type is `TextChangeEventArgs` (nod): ```csharp // ❌ Wrong — CS0246: TextChangedEventArgs not found private void OnTextChanged(TextChangedEventArgs args) { }
>
// ✅ Correct private void OnTextChanged(TextChangeEventArgs args) { } ```
#### Drag Start Event
⚠️ `DragStartEventArgs` is ambiguous whenSyncfusion.Blazor.Popups(or other packages that exposeDragStartEventArgs) is also referenced. Always qualify it asSyncfusion.Blazor.Diagram.DragStartEventArgs: ```csharp // ❌ Wrong — CS0104: ambiguous reference between Diagram and Popups private void OnDragStart(DragStartEventArgs args) { }
>
// ✅ Correct — fully qualified private void OnDragStart(Syncfusion.Blazor.Diagram.DragStartEventArgs args) { } ```
⚠️ `DragEnterEventArgs` does NOT exist inSyncfusion.Blazor.Diagram. There is no `DragEnter` event onSfDiagramComponentthat receives aDragEnterEventArgs. The available drag events onSfDiagramComponentare:DragStart,Dragging,DragLeave,DragDrop— all for SymbolPalette drag-and-drop only. For tracking when a node is being moved (internal drag), usePositionChanged: ```csharp // ❌ Wrong — DragEnterEventArgs does not exist private void OnDragEnter(DragEnterEventArgs args) { }
>
// ❌ Wrong — OnPositionChange does not exist on SfDiagramComponent <SfDiagramComponent OnPositionChange="OnPositionChange" />
>
// ✅ Correct — use PositionChanged <SfDiagramComponent PositionChanged="OnPositionChanged" />
>
private void OnPositionChanged(PositionChangedEventArgs args) { if (args.Element is Node n) Console.WriteLine($"Node {n.ID} moved to ({n.OffsetX}, {n.OffsetY})"); } ```
#### Snap Distance
⚠️ `SnapObjectDistance` does NOT exist onSnapSettings— using it causesInvalidOperationException: does not have a property matching the name 'SnapObjectDistance'. The correct property name is `SnapDistance`: ```razor @ ❌ Wrong — SnapObjectDistance does not exist @ <SnapSettings SnapObjectDistance="5" />
>
@ ✅ Correct @ <SnapSettings Constraints="SnapConstraints.SnapToObject" SnapDistance="5" /> ```
#### Styling
⚠️ `CssClass` does NOT exist onSfDiagramComponent— using it causesInvalidOperationException: Object of type 'SfDiagramComponent' does not have a property matching the name 'CssClass'. Wrap the component in a<div>with a scoping class instead: ```razor @ ❌ Wrong — CssClass does not exist on SfDiagramComponent @ <SfDiagramComponent CssClass="my-diagram" />
>
@ ✅ Correct — use a wrapper div @ <div class="my-diagram"> <SfDiagramComponent ... /> </div> ```
#### Phase Offset Property
⚠️ `Phase.Offset` does NOT exist — using it causes a compile error. Use `Phase.Width` to set the size of a phase in a swimlane: ```csharp // ❌ Wrong — Offset does not exist on Phase new Phase { ID = "ph1", Offset = 220 }
>
// ✅ Correct — use Width new Phase { ID = "ph1", Width = 220 } ```
#### Lane Constraints Property
⚠️ `Lane.Constraints` does NOT exist and `LaneConstraints` enum does NOT exist. Individual lanes cannot have constraints set via a Constraints property. To restrict swimlane-level interactions, use `SwimlaneConstraints` on the `Swimlane` object itself: ```csharp // ❌ Wrong — Lane.Constraints and LaneConstraints do not exist lane.Constraints = LaneConstraints.Default & ~LaneConstraints.ResizeEntries;>
// ✅ Correct — set constraints on the Swimlane object swimlane.Constraints = SwimlaneConstraints.Default & ~SwimlaneConstraints.Interaction; ```
#### FitMode.Page Value
⚠️ `FitMode.Page` does NOT exist — using it causesCS0117. The correct values forFitModeare `FitMode.Width` and `FitMode.Height`: ```csharp // ❌ Wrong — FitMode.Page does not exist new FitOptions { Mode = FitMode.Page }
>
// ✅ Correct — use FitMode.Width or FitMode.Height new FitOptions { Mode = FitMode.Width, Region = DiagramRegion.Content } ```
#### LoadDiagram Method
⚠️ `SfDiagramComponent.LoadDiagram()` does NOT exist — using it causes a compile error. Use the async version `LoadDiagramAsync()` instead: ```csharp // ❌ Wrong — LoadDiagram() does not exist diagram.LoadDiagram(savedJson);
>
// ✅ Correct — use LoadDiagramAsync await diagram.LoadDiagramAsync(savedJson); ```
#### FitToPageAsync Method
⚠️ `SfDiagramComponent.FitToPageAsync()` does NOT exist — using it causes a compile error. Use the non-async overload `FitToPage()` instead: ```csharp // ❌ Wrong — FitToPageAsync does not exist await diagram.FitToPageAsync(new FitOptions { Mode = FitMode.Width });
>
// ✅ Correct — use FitToPage (synchronous) diagram.FitToPage(new FitOptions { Mode = FitMode.Width, Region = DiagramRegion.Content }); ```
#### BasicShapes Enum
⚠️ `BasicShapes` does NOT exist — use NodeBasicShapes instead: ```csharp // ❌ Wrong new BasicShape { Shape = BasicShapes.Rectangle }>
// ✅ Correct new BasicShape { Shape = NodeBasicShapes.Rectangle } ```
#### DiagramThickness Constructor
⚠️ `DiagramThickness` does NOT have a 4-argument constructor — using it causes CS1729: does not contain a constructor that takes 4 arguments. Use the object initializer syntax with named properties instead: ```csharp // ❌ Wrong — CS1729: no 4-argument constructor new DiagramThickness(20, 50, 20, 20)>
// ✅ Correct — use object initializer with named properties new DiagramThickness { Left = 20, Top = 50, Right = 20, Bottom = 20 }
>
// ✅ Correct — set only the sides you need new DiagramThickness { Top = 50 } ```
#### ScrollSettings EnableAutoScroll Property
⚠️ `CanAutoScroll` does NOT exist onScrollSettings— using it causesInvalidOperationException: does not have a property matching the name 'CanAutoScroll'. The correct property name is `EnableAutoScroll`: ```razor @ ❌ Wrong — CanAutoScroll does not exist @ <ScrollSettings CanAutoScroll="true" />
>
@ ✅ Correct @ <ScrollSettings EnableAutoScroll="true" /> ```
#### Zoom, Undo, and Redo Methods
⚠️ `ZoomAsync()`, `UndoAsync()`, and `RedoAsync()` do NOT exist — using them causes a compile error. Use the non-async overloads `Zoom()`, `Undo()`, and `Redo()` instead: ```csharp // ❌ Wrong — ZoomAsync, UndoAsync, RedoAsync do not exist await _diagram.ZoomAsync(1.2, new DiagramPoint { X = 300, Y = 300 }); await _diagram.UndoAsync(); await _diagram.RedoAsync();
>
// ✅ Correct — use non-async overloads _diagram.Zoom(1.2, new DiagramPoint { X = 300, Y = 300 }); _diagram.Undo(); _diagram.Redo(); ```
#### Overview Component Namespace
⚠️ `SfDiagramOverviewComponent` requires an additional `@using` — it lives inSyncfusion.Blazor.Diagram.Overview, NOT inSyncfusion.Blazor.Diagram. Forgetting it causesCS0246: ```razor @ ❌ Wrong — SfDiagramOverviewComponent not found without the Overview namespace @ @using Syncfusion.Blazor.Diagram
>
@ ✅ Correct — both namespaces required @ @using Syncfusion.Blazor.Diagram @using Syncfusion.Blazor.Diagram.Overview ```
⚠️ `SourceID` must exactly match the `ID` set on `SfDiagramComponent` — the ID is NOT auto-generated; you must set it explicitly. A mismatch (including case) renders the overview empty: ```razor @ ❌ Wrong — ID not set on the diagram; SourceID has nothing to link to @ <SfDiagramComponent Width="100%" Height="500px" Nodes="@_nodes" /> <SfDiagramOverviewComponent SourceID="myDiagram" Height="150px" />>
@ ✅ Correct — ID set on diagram, SourceID matches exactly @ <SfDiagramComponent ID="myDiagram" Width="100%" Height="500px" Nodes="@_nodes" /> <SfDiagramOverviewComponent SourceID="myDiagram" Height="150px" /> ```
⚠️ Do NOT nest `SfDiagramOverviewComponent` inside `SfDiagramComponent` — the overview is a sibling component rendered outside the diagram markup.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.