Separate UI and Code in Blazor

Blazor apps consist of one or more components. Components reside in .razor files and consist of UI markup and C# code. When you create a new Blazor server or WebAssembly project it stores component UI and code in a single file. However, at times this single file approach might not be adequate. Luckily, you can separate your UI markup and C# code easily. This article shows how.

Single file

Firstly, let's see how the UI markup and C# code is stored under the single file approach.

Begin by creating a new Blazor server project using Visual Studio. The following figure shows the newly created project in Solution Explorer. 

Then open the Counter.razor component from the Pages folder to reveal this markup and code:

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" 
        @onclick="IncrementCount">
        Click me
</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

As you can see the component UI markup is placed after @page directive. And component's C# code is placed inside the @code block.

That means UI markup and C# code are housed in a single file. This arrangement works well when your components are simple and don't contain huge chunks of markup and code. Single file approach is also good if you want keep minimal number of project files. However, if you are developing complex components you might want to separate UI markup and C# code in separate files.

There are two ways to accomplish that task - Partial class approach and Base class approach.

Let's see both of them in action.

Partial class

In this approach you create a partial class matching the name of the component. For example, the Counter component exists in Component.razor file. So, you need to create a partial class called Counter. Then you need to write all the C# code into the partial class. The UI markup will remain in the Counter.razor file.

Here, we will create a new component and copy the code from Counter component into it. This way we can test all the approaches in a single project.

Add a new Razor Component named Counter1.razor using Add New Item dialog.

Then add a new C# class file called Counter1.razor.cs.

The name of the class file can be anything but if you stick to this convention Visual Studio will show it as a nested file of Counter1.razor.

Now copy the UI code from Counter.razor into Counter1.razor file.

@page "/counter1"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary"
        @onclick="IncrementCount">
    Click me
</button>

Note that after coping the code we change the @page directive to /counter1 to avoid duplicate routes.

Then copy everything from the @code block of Counter.razor to Counter1.razor.cs. This is shown below:

public partial class Counter1
{
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

Notice that Counter1 class is marked to be a partial class.

We just created Counter1 component that separates its UI and C# code into different files.

Base class

Let's see the base class approach. This approaches also involves a .razor file and a corresponding .cs file but rather than creating a partial class we resort to inheritance.

Add another Razor Component called Counter2.razor. Also add a new C# class file called Counter2.razor.cs.

Now open the Counter2.razor.cs file and write the following class definition into it.

public class Counter2Base : ComponentBase
{
    protected int currentCount = 0;

    protected void IncrementCount()
    {
        currentCount++;
    }
}

Notice that the class name is Counter2Base and it inherits from ComponentBase class. This class name can be anything. But to avoid any ambiguity with the Counter2, we call it Counter2Base.

Also notice that the class members are changed from private to protected. This is required because we are going to use inheritance (rather than partial class) in this example.

Now modify the Counter2.razor file as shown below:

@page "/counter2"

@inherits Counter2Base

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary"
        @onclick="IncrementCount">
    Click me
</button>

As before we assign some different route to this component. Moreover, Counter2 component inherits from Counter2Base class. This is indicated using @inherits directive.

Now, let's see whether all the three components work as expected.

Open NavMenu.razor file and add two menu entries for the two additional components we created.

<li class="nav-item px-3">
    <NavLink class="nav-link" href="counter">
        <span class="oi oi-plus" aria-hidden="true">
        </span> Counter
    </NavLink>
</li>
<li class="nav-item px-3">
    <NavLink class="nav-link" href="counter1">
        <span class="oi oi-plus" aria-hidden="true">
        </span> Counter1
    </NavLink>
</li>
<li class="nav-item px-3">
    <NavLink class="nav-link" href="counter2">
        <span class="oi oi-plus" aria-hidden="true">
        </span> Counter2
    </NavLink>
</li>

Run the project and navigate to all the three "counter" components from the left side menu.

Click on the "Click me" button of each counter component and check whether it displays the correct value.

That's it for now! Keep coding!!


Bipin Joshi is an independent software consultant and trainer by profession specializing in Microsoft web development technologies. Having embraced the Yoga way of life he is also a yoga mentor, meditation teacher, and spiritual guide to his students. He is a prolific author and writes regularly about software development and yoga on his websites. He is programming, meditating, writing, and teaching for over 27 years. To know more about his private online courses on ASP.NET and meditation go here and here.

Posted On : 07 December 2020


Tags : ASP.NET ASP.NET Core MVC C# Visual Studio Components