Skip to main content

Get Started with DevExpress Chips for .NET MAUI

  • 5 minutes to read

The DevExpress Mobile UI for .NET MAUI suite contains chips—small but highly functional visuals that allow users to make selections, filter content, input tokens, or trigger actions. Refer to the following help topic for a list of available chips: Chip Types.

This tutorial explains how to use a FilterChipGroup instance to filter a list of hotels.

DevExpress Chips for .NET MAUI

Prerequisites

Refer to the following pages before you proceed with this Getting Started lesson:

Create a New Application and Place a Chip Group on the Main Page

  1. Create a new .NET MAUI cross-platform solution, and name it ChipsExample. Our controls support iOS and Android only. Remove other platforms from the project.

    Tip

    You can also use DevExpress Project Templates to create a new application. See the following topic for more information: CLI Project Templates. If you use our templates, skip the following two steps:

  2. Install the DevExpress.Maui.Editors NuGet package. See the following topic for more information: Register DevExpress NuGet Gallery to Access Mobile UI for .NET MAUI.

  3. In the MauiProgram.cs file, call the DevExpress.Maui.UseDevExpress method to register handlers for our controls.

    using DevExpress.Maui;
    //...
    public static MauiApp CreateMauiApp() {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .UseDevExpress()
            //...
            .UseMauiCompatibility();
    
        return builder.Build();
    }
    
  4. In the MainPage.xaml file, declare the dxe XAML namespace and add a FilterChipGroup to the content page.

    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:dxe="clr-namespace:DevExpress.Maui.Editors;assembly=DevExpress.Maui.Editors"
                 xmlns:local="clr-namespace:ChipsExample"
                 x:Class="ChipsExample.MainPage">
        <dxe:FilterChipGroup/>
    </ContentPage>
    

Model

Create business objects and sample data as shown below.

using System.Collections.Generic;
using System.Linq;
//...
internal class Hotel {
    public static IList<string> CommodityList = new List<string>() { "Elevator", "Washer/Dryer", "Wheelchair Access", "Fireplace", "Pet-Friendly" };
    public static IList<string> NameList = new List<string>() { "Hilton", "Sheraton", "Westin", "Four Seasons", "Ritz-Carlton", "Hyatt", "Renaissance", "Embassy Suites" };
    public string Name { get; set; }
    public IList<string> Commodities { get; set; }
}

internal static class Data {
    public static IList<Hotel> Hotels { get; set; } = new List<Hotel>();
    static Data() {
        for (int i = 0; i < Hotel.NameList.Count; i++) {
            var hotel = new Hotel();
            var r = new Random();
            hotel.Name = Hotel.NameList[i];
            var commodities = new List<string>();
            commodities.AddRange(Hotel.CommodityList.OrderBy(x => r.Next()).Take(r.Next(1, Hotel.CommodityList.Count)));
            hotel.Commodities = commodities;
            Hotels.Add(hotel);
        }
    }
}

View Model

Create view models. The MainViewModel object exposes the following properties:

  • Chips—stores a collection of view models for chips. They store chip captions. A chip displays a commodity available in a hotel.
  • Hotels—stores a collection of view models for hotels. They store hotel names and available commodities. The view models also specify the Boolean IsVisible property. We will toggle this setting depending on whether the corresponding chip is selected.
using System.ComponentModel;
using System.Linq;
//...
internal class MainViewModel {
    public ObservableCollection<HotelViewModel> Hotels { get; set; }
    public IList<string> Chips { get; set; }

    public MainViewModel() {
        Hotels = new ObservableCollection<HotelViewModel>(Data.Hotels.Select(x => new HotelViewModel(x)));
        Chips = Hotel.CommodityList.ToList();
    }
}
internal class HotelViewModel : INotifyPropertyChanged {
    public HotelViewModel(Hotel hotel) {
        Name = hotel.Name;
        Commodities = hotel.Commodities.ToList();
    }
    public string Name { get; set; }
    public IList<string> Commodities { get; set; }
    bool isVisible = true;
    public bool IsVisible {
        get { return isVisible; }
        set {
            isVisible = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsVisible)));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

View

In the MainPage.xaml file, update the page’s content as shown below. As you can see, we specify the page’s BindingContext property. It is set to a MainViewModel instance. Below, we declare a FilterChipGroup and CollectionView objects. They are bound to the Chips and Hotels properties in the view model, respectively.

The DisplayMember property is set to the ChipViewModel.Text property. This property stores the chip caption.

Each item in the CollectionView displays the hotel name and available commodities. We use Label objects in a StackLayout to arrange this information. The Label objects are bound to the corresponding properties in the HotelViewModel objects.

<ContentPage.BindingContext>
    <local:MainViewModel/>
</ContentPage.BindingContext>
<StackLayout>
    <dxe:FilterChipGroup SelectionChanged="FilterChipGroup_SelectionChanged"
                         ItemsSource="{Binding Chips}"
                         DisplayMember="Text"/>
    <CollectionView ItemsSource="{Binding Hotels}">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <StackLayout IsVisible="{Binding IsVisible}">
                    <StackLayout.Triggers>
                        <Trigger TargetType="StackLayout"
                                 Property="IsVisible"
                                 Value="False">
                            <Setter Property="HeightRequest" Value="0"/>
                            <Setter Property="Margin" Value="0"/>
                            <Setter Property="Padding" Value="0"/>
                        </Trigger>
                    </StackLayout.Triggers>
                    <Label Grid.Row="0"
                           Text="{Binding Name}"
                           FontSize="Large"
                           Margin="15, 5"/>
                    <CollectionView Grid.Row="1"
                                    ItemsLayout="HorizontalList" 
                                    ItemsSource="{Binding Commodities}" 
                                    Margin="15, 0">
                        <CollectionView.ItemTemplate>
                            <DataTemplate>
                                <Label Text="{Binding}"
                                       Margin="0, 0, 10, 0"
                                       TextColor="Gray"/>
                            </DataTemplate>
                        </CollectionView.ItemTemplate>
                    </CollectionView>
                </StackLayout>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</StackLayout>

Filter Hotels when User Selects Commodity

Handle the SelectionChanged event to respond when a user selects a chip in the group. We change a hotel’s visibility depending on whether it provides the selected commodity.

using DevExpress.Maui.Editors;
//...
private void FilterChipGroup_SelectionChanged(object sender, EventArgs e) {
    var viewModel = this.BindingContext as MainViewModel;
    var filterChipGroup = sender as FilterChipGroup;
    if (filterChipGroup.SelectedItems == null || filterChipGroup.SelectedItems.Count == 0) {
        foreach (HotelViewModel hotel in viewModel.Hotels)
            hotel.IsVisible = true;
    }
    else {
        foreach (HotelViewModel hotel in viewModel.Hotels) {
            if (((Collection<object>)filterChipGroup.SelectedItems).Except<object>(hotel.Commodities).Any())
                hotel.IsVisible = false;
            else
                hotel.IsVisible = true;

        }
    }
}