Diagram Validation
Rule-based checks with severities, fix suggestions and a custom-rule API
DiagramValidator runs a set of rules over the current components and connection lines and returns a list of DiagramIssue records. The editor sample runs it from the Validate command and reports the summary in the status bar; hosts can run it before saving, exporting or executing a workflow.
Table of Contents
Running Validation
The validator owns its rule list. Add the defaults, optionally add your own rules, then validate the diagram's current contents:
var validator = new DiagramValidator();
validator.AddDefaultRules();
List<DiagramIssue> issues = validator.Validate(
drawingManager.GetComponents().ToList(),
drawingManager.GetLines());
int errors = issues.Count(i => i.Severity == DiagramIssueSeverity.Error);
int warnings = issues.Count(i => i.Severity == DiagramIssueSeverity.Warning);
foreach (var issue in issues)
{
Console.WriteLine($"[{issue.Severity}] {issue.RuleName}: {issue.Message}");
if (!string.IsNullOrEmpty(issue.FixSuggestion))
Console.WriteLine($" fix: {issue.FixSuggestion}");
}
Built-in Rules
AddDefaultRules() registers six rules:
| Rule | Detects |
|---|---|
OrphanNodeRule | Components with zero incoming and zero outgoing connections. |
CycleDetectionRule | Cycles in the diagram that may cause infinite loops when executed. |
DeadEndNodeRule | Nodes that have inputs but no outputs (or vice versa) where the family expects flow-through. |
OverlappingComponentsRule | Components whose bounds overlap, hiding content on the canvas. |
EmptyDiagramRule | A diagram with no components at all (for example before an export or execution). |
UnconnectedPortRule | Ports that should be wired but have no connection. |
Issues and Severities
| Member | Type | Description |
|---|---|---|
Message | string | Human-readable description of the problem. |
Severity | DiagramIssueSeverity | Info, Warning (default) or Error. |
Component | SkiaComponent | The component involved, when the issue is component-specific. |
Line | IConnectionLine | The connection involved, when the issue is line-specific. |
RuleName | string | Name of the rule that produced the issue (for filtering or suppression). |
FixSuggestion | string | Optional hint on how to resolve the problem. |
Issues are data, not exceptions: validation never throws for a malformed diagram, it reports. That makes it safe to run on every save.
Custom Rules
Implement IDiagramRule and register the rule with AddRule. Rules receive the full component and line lists and yield issues:
public sealed class NamingConventionRule : IDiagramRule
{
public string Name => "NamingConvention";
public string Description => "Process nodes must use verb phrases (e.g. 'Validate Order').";
public IEnumerable<DiagramIssue> Validate(
IReadOnlyList<SkiaComponent> components,
IReadOnlyList<IConnectionLine> lines)
{
foreach (var node in components.OfType<ProcessNode>())
{
if (!string.IsNullOrWhiteSpace(node.Label) &&
char.IsLower(node.Label.TrimStart()[0]))
{
yield return new DiagramIssue
{
RuleName = Name,
Severity = DiagramIssueSeverity.Info,
Component = node,
Message = $"'{node.Label}' should start with a capital letter.",
FixSuggestion = "Rename the node using a verb phrase."
};
}
}
}
}
// Register and run
var validator = new DiagramValidator();
validator.AddDefaultRules();
validator.AddRule(new NamingConventionRule());
var issues = validator.Validate(components, lines);
Rules are independent and order-insensitive; Rules exposes the registered list if you want to display or toggle them in a UI.