Virtualization in Blazor MultiSelect Dropdown Component

4 Nov 202520 minutes to read

The MultiSelect component includes a virtual scrolling feature that improves UI performance when working with large datasets. By enabling the EnableVirtualization option, the MultiSelect renders only a subset of items initially. As the user scrolls, additional items are dynamically loaded, resulting in a smooth and efficient experience.

This feature works with both local and remote data. For example, when the MultiSelect is bound to 150 items, only the items that fit within the popup are loaded initially, based on the popup height. As scrolling continues, more items are fetched and rendered on demand, enabling efficient navigation through the entire dataset.

Binding local data

The MultiSelect component can generate list items from an array of complex data. For this, the appropriate properties should be mapped to the fields property. With virtual scrolling enabled, the list is updated based on the scroll offset and loads additional items from the in-memory data source.

In the following example, the ID and Text properties from the complex data are mapped to the Value and Text fields, respectively.

  • CSHTML
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="Select an item" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" PopupHeight="160px" EnableVirtualization="true">
        <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
        public Query LocalDataQuery = new Query().Take(6); 
        public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        { 
            this.Records = Enumerable.Range(1, 150).Select(i => new Record() 
            { 
                ID = i.ToString(), 
                Text = "Item " + i, 
            }).ToList(); 
        } 
    }

    Binding remote data

    The MultiSelect supports retrieval of data from remote data services with the help of DataManager component. When using remote data, it initially fetches all the data from the server, triggering the ActionBegin and ActionComplete events, and then stores the data locally. During virtual scrolling, additional data is retrieved from the locally stored data, triggering the ActionBegin and ActionComplete events at that time as well.

    The following sample displays the EmployeeID from the VirtualDropdownData Data Service.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="OrderDetails" AllowFiltering="true" PopupHeight="160px" EnableVirtualization="true" Placeholder="Select ID" Query="@RemoteDataQuery">
        <SfDataManager Url="https://services.syncfusion.com/js/production/api/VirtualDropdownData" CrossDomain="true" Adaptor="Syncfusion.Blazor.Adaptors.UrlAdaptor" />
        <MultiSelectFieldSettings Text="EmployeeID" Value="EmployeeID" />
    </SfMultiSelect>
    
    @code{
        public Query RemoteDataQuery = new Query().Take(6); 
        public class OrderDetails
        {
            public int? OrderID { get; set; }
            public string CustomerID { get; set; }
            public string EmployeeID { get; set; }
            public double? Freight { get; set; }
            public string ShipCity { get; set; }
            public bool Verified { get; set; }
            public DateTime? OrderDate { get; set; }
            public string ShipName { get; set; }
            public string ShipCountry { get; set; }
            public DateTime? ShippedDate { get; set; }
            public string ShipAddress { get; set; }
        }
    }

    Customizing items count in virtualization

    When the EnableVirtualization property is enabled, the Take property provided by the user within the Query parameter at the initial state or during the ActionBegin event will be considered. Internally, it calculates the items that fit onto the current page (i.e., probably twice the amount of the popup’s height). If the user-provided take value is less than the minimum number of items that fit into the popup, the user-provided take value will not be considered.

    The following example demonstrates customizing the item count in virtualization.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="e.g. Item 1" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" PopupHeight="160px" EnableVirtualization="true">
        <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
       public Query LocalDataQuery = new Query().Take(25);
       public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
            public string Group { get; set; }
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        {
            var random = new Random();
            this.Records = Enumerable.Range(1, 150).Select(i => new Record()
                {
                    ID = i.ToString(),
                    Text = "Item " + i,
                    Group = GetRandomGroup(random)
                }).ToList();
        }
        private string GetRandomGroup(Random random)
        {
            switch (random.Next(1, 5))
            {
                case 1:
                    return "Group A";
                case 2:
                    return "Group B";
                case 3:
                    return "Group C";
                case 4:
                    return "Group D";
                default:
                    return string.Empty;
            }
        }
    }

    Grouping with virtualization

    The MultiSelect component supports grouping with virtualization. Items can be organized into groups using the GroupBy field in the data source. After grouping, virtualization behaves as it does with local data binding, providing a seamless experience. When the data source is remote, an initial request retrieves the full dataset for grouping, after which virtualization operates on the grouped data locally.

    The following example demonstrates grouping with virtualization.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="e.g. Item 1" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" PopupHeight="160px" EnableVirtualization="true">
        <MultiSelectFieldSettings GroupBy="Group" Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
       public Query LocalDataQuery = new Query().Take(10);
       public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
            public string Group { get; set; }
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        {
            var random = new Random();
            this.Records = Enumerable.Range(1, 150).Select(i => new Record()
                {
                    ID = i.ToString(),
                    Text = "Item " + i,
                    Group = GetRandomGroup(random)
                }).ToList();
        }
        private string GetRandomGroup(Random random)
        {
            switch (random.Next(1, 5))
            {
                case 1:
                    return "Group A";
                case 2:
                    return "Group B";
                case 3:
                    return "Group C";
                case 4:
                    return "Group D";
                default:
                    return string.Empty;
            }
        }
    }

    Filtering with virtualization

    The MultiSelect component supports filtering with virtualization. When the AllowFiltering option is enabled, the component filters data in response to user input. For remote data, the MultiSelect sends a request to the server based on the typed characters. Before the request is sent, an action begin event is triggered; after data is returned, an action complete event is triggered. Initial data is loaded when the popup opens. Regardless of whether the filtered list has a selection, the popup closes after filtering.

    The following example demonstrates filtering with virtualization.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="e.g. Item 1" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" PopupHeight="160px" EnableVirtualization="true">
        <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
       public Query LocalDataQuery = new Query().Take(10);
       public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
            public string Group { get; set; }
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        {
            var random = new Random();
            this.Records = Enumerable.Range(1, 150).Select(i => new Record()
                {
                    ID = i.ToString(),
                    Text = "Item " + i,
                    Group = GetRandomGroup(random)
                }).ToList();
        }
        private string GetRandomGroup(Random random)
        {
            switch (random.Next(1, 5))
            {
                case 1:
                    return "Group A";
                case 2:
                    return "Group B";
                case 3:
                    return "Group C";
                case 4:
                    return "Group D";
                default:
                    return string.Empty;
            }
        }
    }

    Checkbox with virtualization

    The MultiSelect component supports checkbox selection with virtualization. When the Mode property is set to CheckBox, each list item renders a checkbox. Based on checkbox selection or clearing, the component’s Value property is updated with the corresponding values.

    The following example demonstrates checkbox selection with virtualization.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="e.g. Item 1" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" PopupHeight="160px" Mode="VisualMode.CheckBox" EnableVirtualization="true">
        <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
       public Query LocalDataQuery = new Query().Take(10);
       public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
            public string Group { get; set; }
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        {
            var random = new Random();
            this.Records = Enumerable.Range(1, 150).Select(i => new Record()
                {
                    ID = i.ToString(),
                    Text = "Item " + i,
                    Group = GetRandomGroup(random)
                }).ToList();
        }
        private string GetRandomGroup(Random random)
        {
            switch (random.Next(1, 5))
            {
                case 1:
                    return "Group A";
                case 2:
                    return "Group B";
                case 3:
                    return "Group C";
                case 4:
                    return "Group D";
                default:
                    return string.Empty;
            }
        }
    }

    Custom value with virtualization

    The MultiSelect component supports custom values with virtualization. When the AllowCustomValue property is enabled, users can add a new option that is not present in the existing data. Upon selecting a custom value, the CustomValueSpecifier event is triggered, and the custom value is appended to the end of the complete list.

    The following example demonstrates custom values with virtualization.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="e.g. Item 1" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" AllowCustomValue="true" PopupHeight="160px" EnableVirtualization="true">
        <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
       public Query LocalDataQuery = new Query().Take(10);
       public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
            public string Group { get; set; }
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        {
            var random = new Random();
            this.Records = Enumerable.Range(1, 150).Select(i => new Record()
                {
                    ID = i.ToString(),
                    Text = "Item " + i,
                    Group = GetRandomGroup(random)
                }).ToList();
        }
        private string GetRandomGroup(Random random)
        {
            switch (random.Next(1, 5))
            {
                case 1:
                    return "Group A";
                case 2:
                    return "Group B";
                case 3:
                    return "Group C";
                case 4:
                    return "Group D";
                default:
                    return string.Empty;
            }
        }
    }

    Preselect values with virtualization

    The MultiSelect component supports preselected values with virtualization. When binding values from local or remote data, the corresponding items are resolved from the bound data source and applied to the component’s Value. When binding a custom value, it is applied to the component and appended to the end of the complete list.

    The following example demonstrates preselect values with virtualization.

  • RAZOR
  • @using Syncfusion.Blazor.DropDowns
    @using Syncfusion.Blazor.Data 
    
    <SfMultiSelect TValue="string[]" TItem="Record" Placeholder="e.g. Item 1" @bind-Value="@Value" DataSource="@Records" Query="@LocalDataQuery" AllowFiltering="true" PopupHeight="160px" EnableVirtualization="true">
        <MultiSelectFieldSettings Text="Text" Value="ID"></MultiSelectFieldSettings>
    </SfMultiSelect>
    
    @code{
       public Query LocalDataQuery = new Query().Take(10);
       public string[] Value { get; set; } = new string[] { "10", "50", "100" };
       public class Record 
        { 
            public string ID { get; set; } 
            public string Text { get; set; } 
            public string Group { get; set; }
        } 
        public List<Record> Records { get; set; } 
        protected override void OnInitialized()
        {
            var random = new Random();
            this.Records = Enumerable.Range(1, 150).Select(i => new Record()
                {
                    ID = i.ToString(),
                    Text = "Item " + i,
                    Group = GetRandomGroup(random)
                }).ToList();
        }
        private string GetRandomGroup(Random random)
        {
            switch (random.Next(1, 5))
            {
                case 1:
                    return "Group A";
                case 2:
                    return "Group B";
                case 3:
                    return "Group C";
                case 4:
                    return "Group D";
                default:
                    return string.Empty;
            }
        }
    }