Binding an Enumeration to a FluentSelect in Blazor FluentUI

Blazor is a joy to work with and Blazor FluentUI is a great UI framework to quickly build user interfaces, that look like "Native WinUI" applications. Now something you often need to do in a Blazor Form is to bind Enumerations to a FluentSelect.

But if you scroll through the Blazor FluentUI documentation, you will only find examples for a string and int values. And I see how you could easily waste an hour coming up with something, so writing it down may be useful to others.

The code has been taken from the Git Repository at:

Table of contents

Binding Enumerations

The auto-generated TaskItemPriorityEnum looks like this:

// <auto-generated/>
using System.Runtime.Serialization;
using System;
namespace RebacExperiments.Shared.ApiSdk.Models {
    public enum TaskItemPriorityEnum {
        [EnumMember(Value = "Low")]
        Low,
        [EnumMember(Value = "Normal")]
        Normal,
        [EnumMember(Value = "High")]
        High,
    }
}

I am sure we could come up with a lot clever generic implementations, but I like to keep it simple and flexible. So I would implement it like this.

@inject IStringLocalizer<SharedResource> Loc

<!-- ... -->

<EditForm Model="@CurrentTaskItem" OnValidSubmit="@(async () => await HandleValidSubmitAsync())" FormName="task_item_edit" novalidate>
    <!-- ... -->
    <FluentStack Orientation="Orientation.Vertical">
        <!-- ... -->
        <div>
            <FluentSelect TOption="TaskItemPriorityEnum?" @bind-SelectedOption=@CurrentTaskItem.TaskItemPriority @onchange=HandleTaskItemPriority>
                <FluentOption Value="-1">@Loc["TaskItemPriorityEnum_Select"]</FluentOption>
                @foreach (TaskItemPriorityEnum taskItemPriority in Enum.GetValues<TaskItemPriorityEnum>())
                {
                   <FluentOption Value=@taskItemPriority.ToString() Selected=@(taskItemPriority == CurrentTaskItem.TaskItemPriority)>@Loc[$"TaskItemPriorityEnum_{taskItemPriority.ToString()}"]</FluentOption>
                }
            </FluentSelect>
            <FluentValidationMessage For="@(() => CurrentTaskItem.TaskItemPriority)" />
        </div>
    </FluentStack>
    <!-- ... -->
</EditForm>

And all that needs to be done in the Code-Behind is to implement the HandleTaskItemPriority method, which is invoked when a new Option has been selected in the FluentSelect.

// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using RebacExperiments.Blazor.Infrastructure;
using RebacExperiments.Blazor.Localization;
using RebacExperiments.Shared.ApiSdk.Models;
using System.Net.Http.Headers;

namespace RebacExperiments.Blazor.Pages
{
    public partial class TaskItemEdit
    {
        // ...

        public void HandleTaskItemPriority(ChangeEventArgs changeEventArgs)
        {
            var stringValue = changeEventArgs.Value?.ToString();

            if(string.IsNullOrWhiteSpace(stringValue) || stringValue == "-1")
            {
                CurrentTaskItem.TaskItemPriority = null;
            } 
            else
            {
                CurrentTaskItem.TaskItemPriority = Enum.Parse<TaskItemPriorityEnum>(stringValue);
            }

            StateHasChanged();            
        }

        // ...
    }
}

Conclusion

And that's it!

There is room for improvements, and I'd be happy to hear about your approaches.