This article will look into generating dropdown for enums in Blazor.
The repository for the source code listed in the article is here:
https://github.com/toreaurstadboss/DallEImageGenerationImgeDemoV4
First off, a helper class for enums that will use the InputSelect control. The helper class will support setting the display text for enum options / alternatives via resources files using the display attribute.
Enumhelper.cs | C# source code
using DallEImageGenerationImageDemoV4.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using System.ComponentModel.DataAnnotations;
using System.Linq.Expressions;
using System.Resources;
namespaceDallEImageGenerationImageDemoV4.Utility
{
publicstaticclassEnumHelper
{
publicstatic RenderFragment GenerateEnumDropDown<TEnum>(object receiver,
TEnum selectedValue,
Action<TEnum> valueChanged)
where TEnum : Enum
{
Expression<Func<TEnum>> onValueExpression = () => selectedValue;
var onValueChanged = EventCallback.Factory.Create<TEnum>(receiver, valueChanged);
return builder =>
{
// Set the selectedValue to the first enum value if it is not setif (EqualityComparer<TEnum>.Default.Equals(selectedValue, default))
{
object? firstEnum = Enum.GetValues(typeof(TEnum)).GetValue(0);
if (firstEnum != null)
{
selectedValue = (TEnum)firstEnum;
}
}
builder.OpenComponent<InputSelect<TEnum>>(0);
builder.AddAttribute(1, "Value", selectedValue);
builder.AddAttribute(2, "ValueChanged", onValueChanged);
builder.AddAttribute(3, "ValueExpression", onValueExpression);
builder.AddAttribute(4, "class", "form-select"); // Adding Bootstrap class for styling
builder.AddAttribute(5, "ChildContent", (RenderFragment)(childBuilder =>
{
foreach (varvaluein Enum.GetValues(typeof(TEnum)))
{
childBuilder.OpenElement(6, "option");
childBuilder.AddAttribute(7, "value", value?.ToString());
childBuilder.AddContent(8, GetEnumOptionDisplayText(value)?.ToString()?.Replace("_", " ")); // Ensure the display text is clean
childBuilder.CloseElement();
}
}));
builder.CloseComponent();
};
}
///<summary>/// Retrieves the display text of an enum alternative ///</summary>privatestaticstring? GetEnumOptionDisplayText<T>(T value)
{
string? result = value!.ToString()!;
var displayAttribute = value
.GetType()
.GetField(value!.ToString()!)
?.GetCustomAttributes(typeof(DisplayAttribute), false)?
.OfType<DisplayAttribute>()
.FirstOrDefault();
if (displayAttribute != null)
{
if (displayAttribute.ResourceType != null && !string.IsNullOrWhiteSpace(displayAttribute.Name))
{
result = new ResourceManager(displayAttribute.ResourceType).GetString(displayAttribute!.Name!);
}
elseif (!string.IsNullOrWhiteSpace(displayAttribute.Name))
{
result = displayAttribute.Name;
}
}
return result;
}
}
}
The following razor component shows how to use this helper.
It would be possible to instead make a component than such a helper method that just passes a typeref parameter of the enum type.
But using such a programmatic helper returning a RenderFragment. As the code shows, returning a builder which uses the
RenderTreeBuilder let's you register the rendertree to return here. It is possible to use OpenComponent and CloseComponent.
Using AddAttribute to add attributes to the InputSelect.
And a childbuilder for the option values.
Sometimes it is easier to just make such a class with helper method instead of a component. The downside is that it is a more manual process, it is similar to how MVC uses HtmlHelpers. What is the best option from using a component or such a RenderFragment helper is not clear, it is a technique many developers using Blazor should be aware of.