How to Bind a MudSelect from an External Source in Blazor Using MudBlazor

posted 2 min read

Blazor is a modern framework from Microsoft that allows you to build interactive web applications using C# and .NET, both on the server and the client, without needing JavaScript. It brings the full power of .NET to the browser via WebAssembly or server-side rendering.

MudBlazor is a popular UI component library built specifically for Blazor. It offers clean, responsive components following Google's Material Design system, making it incredibly easy to create modern, beautiful, and interactive web UIs entirely in C#.

Use Case

Let’s say you need to:

Display a multi-select dropdown

Load the options from an external service

Sync selected values with the parent component

Reuse this logic throughout your application

We'll walk through a real-world pattern using MudSelect, bound to a list of brands (dtoBrands) provided by a service.

Prerequisites

A Blazor project with MudBlazor installed

A service that returns the brand data
A DTO like:

public class BrandDto
{
    public string Text { get; set; }
    public string Value { get; set; }
}

Sample Service Interface

public interface IBrandService
{
    Task<IEnumerable<BrandDto>> GetBrandsAsync();
}

The MudSelect Markup

<MudSelect T="BrandDto"
           Label="@Label"
           MultiSelection="true"
           Clearable="true"
           @bind-SelectedValues="InternalSelectedValues"
           ToStringFunc="item => item.Text">
    @if (dtoBrands.Any())
    {
        @foreach (var item in dtoBrands)
        {
            <MudSelectItem T="BrandDto" Value="item">
                @item.Text
            </MudSelectItem>
        }
    }
</MudSelect>

⚙️ Component Logic

@inject IBrandService BrandService

@code {
    [Parameter]
    public string Label { get; set; } = "Select Brands";

    [Parameter]
    public IEnumerable<BrandDto> SelectedValues { get; set; } = new HashSet<BrandDto>();

    [Parameter]
    public EventCallback<IEnumerable<BrandDto>> SelectedValuesChanged { get; set; }

    protected IEnumerable<BrandDto> dtoBrands = new List<BrandDto>();

    private IEnumerable<BrandDto> _internalSelectedValues = new HashSet<BrandDto>();

    private IEnumerable<BrandDto> InternalSelectedValues
    {
        get => _internalSelectedValues;
        set
        {
            if (_internalSelectedValues != value)
            {
                _internalSelectedValues = value;
                SelectedValuesChanged.InvokeAsync(_internalSelectedValues);
            }
        }
    }

    protected override async Task OnInitializedAsync()
    {
        dtoBrands = await BrandService.GetBrandsAsync();

        _internalSelectedValues = new HashSet<BrandDto>(
            dtoBrands.Where(x => SelectedValues.Any(s => s.Value == x.Value))
        );
    }

    public override async Task SetParametersAsync(ParameterView parameters)
    {
        await base.SetParametersAsync(parameters);

        _internalSelectedValues = new HashSet<BrandDto>(
            dtoBrands.Where(x => SelectedValues.Any(s => s.Value == x.Value))
        );
    }
}

How It Works

♻️ Example Usage

Imagine turning this into a reusable component, like BrandSelector.razor. You’d use it like this:

<BrandSelector Label="Choose Brands"
               SelectedValues="@selectedBrands"
               SelectedValuesChanged="@OnSelectedBrandsChanged" />

Why This Pattern Rocks

By combining Blazor's powerful component model with MudBlazor's modern UI toolkit, you get:

✅ Fully data-driven dropdowns

✅ Type-safe C# components

✅ No need for JavaScript

✅ A consistent look and feel

And all of it is maintainable and testable across large-scale apps.

✅ Final Thoughts

Blazor and MudBlazor are a dream combo for building modern web apps in C#. By binding a MudSelect to an external service, you're creating a highly flexible and reusable pattern that fits beautifully in a clean architecture.

Useful Links

Blazor documentation

MudBlazor official site

MudSelect documentation

If you read this far, tweet to the author to show them you care. Tweet a Thanks

Really helpful breakdown! I used a similar approach but wrapped the logic inside a LoadOptions() method and triggered it manually. Curious to see if using OnInitializedAsync has better lifecycle benefits. Thanks for sharing!

Thanks for your comment!
OnInitializedAsync is the best place to load data when the component is initialized, just before the first render.
it runs automatically and helps keep your code cleaner by avoiding manual method calls.

More Posts

EF Core Global Query Filters: A Complete Guide

Spyros - Mar 2

EF Core Bulk Updates and Deletes: Performance vs Change Tracking

Spyros - Mar 24

EF Core: Lazy Loading, Eager Loading, and Loading Data on Demand

Spyros - Mar 6

When NOT to Use AsSplitQuery() in EF.core

Spyros - Feb 26

A Comprehensive Guide to Building Web Applications with Blazor

topuzas - Mar 14
chevron_left