This post is the December 8th entry in Matthew Groves’ The Third Annual C# Advent Series. Check out the other blog posts!
When I first heard of Blazor, it filled me with tons of excitement. If any of you are like me, then you’re a .NET developer who takes on the wild backend code and leaves the complex frontend code to the brilliant UI/UX developers who have done extensive work with JavaScript. With this framework, we can create client-side UI that interacts with the browser mostly without the need to write JavaScript. Another great thing about Blazor is that we can create reusable UI elements using Razor Components. Let’s create a simple wizard component.
Prerequisites
- .NET Core 3.1 SDK
- (Optional) An IDE like Visual Studio 16.4 / Visual Studio Mac 16.4, or an awesome editor like Visual Studio Code.
Creating a New Component
First, create a Components folder to house the components and then add a Razor Component. In Visual Studio, right click on the folder, Add New Item, and select the Razor Component item template. We’ll name this Wizard.razor, so we will be able to use the component with a tag like <Wizard></Wizard>. It is safe to clear all content from this, since we’re creating it all from scratch.
Now we have a blank Wizard.razor item. What’s next? We need to make a simple layout that will hold the elements that will describe each step of the wizard, the main content of the current step, and navigation buttons. Bootstrap has a lot of great layout components that will take the pain out of designing this.
<div>
<ul class="nav nav-pills nav-justified">
<li class="nav-item"><a class="nav-link active">Step 1</a></li>
<li class="nav-item"><a class="nav-link">Step 2</a></li>
<li class="nav-item"><a class="nav-link">Step 3</a></li>
</ul>
<div id="container-fluid">
<div id="row">
<p>Some Random Content</p>
</div>
</div>
</div>
<div>
<button class="btn btn-primary btn-lg" type="button">Previous</button>
<button class="btn btn-primary btn-lg" type="button">Next</button>
</div>
The HTML code will result in a simple layout that gives us three step items, some random content, and previous/next buttons
Ideally, the each step should handle its own content in a component that we can add inside of the wizard. For this we need to create a WizardStep component. Normally, this is where we start creating variables and wiring up click handlers in JavaScript to control how advance through the wizard. With Blazor, the .NET code we write will take care of this!
For this sample, I want to separate the bulk of code from being declared within the Razor files use separate code-behind files for the Wizard and WizardStep components instead. Ed Charbeneau has a brilliant post detailing how this separation works.
public partial class Wizard
{
protected internal List<WizardStep> Steps = new List<WizardStep>();
[Parameter]
public string Id { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public WizardStep ActiveStep { get; set; }
[Parameter]
public int ActiveStepIx { get; set; } public bool IsLastStep { get; set; }
}
The Wizard component now defines properties that correspond to the state of the steps within the Wizard. The ChildContent property is important, as the RenderFragment class allows for partial rendering of content contained within it. In this case, the ChildContent will be the WizardSteps.
With the WizardStep component, we want to define its name, the ChildContent property, and also we need a way to reference the Wizard Component it resides within. Why do we need to reference the Wizard component? In order to pass data to it and help keep its state in sync.
public partial class WizardStep
{
[CascadingParameter]
protected internal Wizard Parent { get; set; }[Parameter]
public RenderFragment ChildContent { get; set; }[Parameter]
public string Name { get; set; }
protected override void OnInitialized()
{
Parent.AddStep(this);
}
}
When the WizardStep component is finished initializing, it tells the Wizard, “Hey, I’m here. Add me as a step”. It will only render the ChildContent if it is the active step selected. The WizardStep is interacting with its parent directly because of the CascadingParameter attribute. This attribute states that the property it targets should have its value populated by the closest ancestor using a CascadingValue. For this to work properly, the Wizard component Razor code has to be wrapped inside of a CascadingValue with its value set to the instance of the Wizard component.
The Wizard Component contains methods that are executed by assigning the onclick property. If the method has no parameters, then it can be added as a method group. Otherwise, it has to be invoked as lambda. Now that we have everything together, let’s try this out!
Running the Wizard Component
The finished result shows the Wizard Component working as expected and without any JavaScript written.
Blazor is definitely something I plan on diving more into. The idea for this demo came from an existing MVC view that contained tons of jQuery and multiple components. I replaced just about all of the JavaScript code with C# code that works even better. As this was a simple component, I didn’t touch on any of the advanced topics (JavaScript Interop for instance), but these topics can always be explored deeper. I urge everyone to give Blazor a shot.
Useful Resources
Source code for this blog post is located at https://github.com/snickler/samples.