Building ListView-like TableNode-s with Blazor Diagram

In this blog post we look how you can create TableNode that render their cells following the logic of a list view: the tables have as many table columns and rows as needed in order to fit their content. The width of each column is fixed. When necessary, tables can be scrolled vertically. This is the final result:

TableNodes in Blazor

I. Project Setup

For the purpose of this tutorial we use the Diagramming library for Blazor. You can use the same code with a Mindfusion diagramming component for any other platform: MAUI, WPF, WinForms or other.

We create a new project in Visual Studio with the “Blazor WebAssembly Standalone App” template. After that, we add the Mindfusion Diagramming library from NuGet:

Diagramming for Blazor on NuGet

The diagram component renders itself into a DIV element. The size and location of the DIV element are specified through HTML and CSS just like every other DIV element. So, in the app.css file, which is located in wwwroot\css we add a new CSS style:

.wrapper {
    display: grid;
    border-style: solid;
    border-color: #cecece;
    grid-gap: 10px;
    width: 100vw;
    height: 100vh;
}

The code above tells the browser that the element has grid display and should be drawn with a light gray border. The important thing to note is that the element, to which this style is applied, e.g. our diagram, takes all the width and height of the view: 100vw and 100 vh.

Now we are ready to start coding the diagram.

II. The Diagram

We will create our diagram in the Home.razor file for simplicity. First, we import the Mindfusion.* namepaces that we would use:

@using MindFusion.Drawing;
@using MindFusion.Diagramming;
@using MindFusion.Diagramming.Blazor;

We also need a few Graphucs namespaces:

@using Microsoft.Maui.Graphics
@using Microsoft.Maui.Graphics.Converters
@using Microsoft.Maui.Graphics.Skia

Now it is time to initialize the DIV element that will hold our diagram:

<div class="wrapper" style="background-color: #e6e6e6;">
	<DiagramView @ref="diagramView" />
	</div>

Note that the Diagram is not initialized directly – we initialize a DiagramView instead. This is because the Diagram is a property of the DiagramView and the view acts as a visual container for the diagram. This separation allows the diagram instance to be rendered into various views: a 3D view for example.

The OnAfterRenderAsync method is a good place to get the Diagram instance. We will need to variables: for the diagram and the view. Then we get the diagram from diagramView object.


@code {

	DiagramView diagramView;
	Diagram diagram;

	protected override async Task OnAfterRenderAsync(bool firstRender)
	{
		base.OnAfterRender(firstRender);

		if (firstRender)
		{
			diagram = diagramView.Diagram;
			..............................

 		}
	}
}



III. Styling

The Diagram class class provides lots of properties for customizing the looks of the diagram. In our sample we use just a few styling properties:

diagram.LinkHeadShapeSize = 2;
diagramView.Behavior = Behavior.DrawTables;

diagram.BackBrush = new SolidBrush(Color.FromRgb(213, 229, 242));

We increase the size of the head shape for links and specify that the Behavior of the diagram shall be LinkTables. The Behavior property determines how the diagram view responds to user action and there are various options to choose from: create / link containers, nodes, tables, modify, do nothing etc. The create*** behavior options allow the user to draw new nodes but does not allow connecting them. When the behavior is link*** new nodes can both be created and connected.

From the styling options we use only BackBrush – we set the background of the diagram to a light blue colour.

IV. Calculating Table Rows and Columns

For the calculations of the necessary rows and columns of the table, we need to know the width of the cells. All cells have equal width and we provide it to our custom ReflowTable method as a parameter:

void ReflowTable(TableNode table, float cellWidth)
{
	var data = TableData(table);
	int columns = (int)Math.Floor(table.Bounds.Width / cellWidth);
	if (columns == 0)
		columns = 1;
	table.ColumnWidth = cellWidth;
	table.RedimTable(columns, 0);
	int c = 0;
	int r = 0;
	foreach (string value in data)
	{
		if (table.RowCount <= r)
			table.AddRow();
		table[c, r].Text = value;
		c++;
		if (c == columns)
		{
			c = 0;
			r++;
		}
	}
}

In this method we calculate the columns, into which we can split the table, based on the requested cell width and the width of the table. So, larger tables will have more columns. We call the RedimTable method that restructures the table with the given amount of columns and rows. Then we need to repopulate the cells with the respective data. The RedimTable method empties the cell contents, so it's important to keep track of what you had so you can re-enter the data in the respective cells.

V. Events

After we have created the calculations and initializations, we should handle the appropriate events where we can safely apply them. The nodeCreated and events events are the right choice. Every time a table is created or modified, we need to recalculate the tables and populate the cells with the data.

Events are wired the standard way:

diagram.NodeCreated += OnNodeCreated;
diagram.NodeModified += OnNodeModified;

The event handling is simple: we need to make sure that a TableNode was created and then we call the ReflowTable method to calculate the number of rows and columns:

void OnNodeCreated(object sender, NodeEventArgs e)
{
	if (e.Node is TableNode table)
	{
		table.CaptionHeight = 7;
		table.Font = new MindFusion.Drawing.Font("Verdana", 10);
		table.CaptionBackBrush = new SolidBrush(Color.FromRgb(33, 117, 191));
		table.CaptionBrush = new SolidBrush(Color.FromRgb(225, 225, 225));
		table.Brush = new SolidBrush(Color.FromRgb(67, 174, 217));
		table.TextBrush = new SolidBrush(Color.FromRgb(225, 225, 225));
		table.CellTextBrush = new SolidBrush(Color.FromRgb(225, 225, 225));
		table.Scrollable = true;
		ReflowTable(table, 30);
	}
}

We apply some styling to the TableNode to make it more presentable. You can look at the various options in the online documentation. In our case we change the background of the caption as well as the text colour and we also apply some colour to the background of the table cells.

With that our sample project is ready. You can download the source code from this link:

Creating ListView-like TableNode-s in .NET Blazor

If you need technical assistance, you are welcome to use the discussion board, the HelpDesk or write at support@mindfusion.eu.

About Mindfusion Diagramming for Blazor: A native component, written entirely in C# that lets you create all types of diagrams, flowcharts, process schemes, class hierarchies, organizational charts and many more. The component supports a large set of automatic layout algorithms, predefined table nodes, text options and user interaction modes. Styling and appearance customization is done through themes as well as numerous properties and a large set of brushes and strokes. The library includes additional controls like a ruler, zoom and overview. Prices are calculated per developer, each license includes 12-month subscription for technical support and upgrades.