enisn / UraniumUI

Uranium is a Free & Open-Source UI Kit for MAUI.
Apache License 2.0
1.19k stars 143 forks source link

Search/Filter PickerField options #730

Open MikkBenelis opened 3 months ago

MikkBenelis commented 3 months ago

I'd like to request the same (#711) for the regular PickerField. I need to make it searchable because I have way too many options to select from... Is it achievable with the current Uranuim UI implementation?

enisn commented 3 months ago

By default there is no such a feature yet, you can implement it by yourself for now:

It uses IDialogService.DisplayCheckBoxPromptAsync() method to ask selections. https://github.com/enisn/UraniumUI/blob/eae1bbe8ebc372f126a7bd9623bd6ae23d2481f0/src/UraniumUI.Material/Controls/MultipleSelectionField.cs#L62

You may have configured different implementation such as Mopups, ComunityToolkit or just using Default one.

You can customize one of those implementations that you use. I.e. the default one:

https://github.com/enisn/UraniumUI/blob/eae1bbe8ebc372f126a7bd9623bd6ae23d2481f0/src/UraniumUI/Dialogs/DefaultDialogService.cs#L162C41-L162C67

public class MyDialogService : DefaultDialogService
{
    public override Task<IEnumerable<T>> DisplayCheckBoxPromptAsync<T>(
        string message,
        IEnumerable<T> selectionSource,
        IEnumerable<T> selectedItems = null,
        string accept = "OK",
        string cancel = "Cancel",
        string displayMember = null)
    {
        // Your custom dialog implementation with search option
    }
}

And don't forget to replace it in service collection in MauiProgram.cs

builder.Services.Replace(new ServiceDescriptor(typeof(IDialogService), typeof(MyDialogService )));
MikkBenelis commented 3 months ago

Thanks for the really quick answer and sorry for the delayed response... Just tried to implement it like you suggested, but my overridden prompt is not called. Below are 3 parts of my application: program setup, overridden service and part of the UI. Should it really use the IDialogService.DisplayCheckBoxPromptAsync() for the PickerField?

Here is my MauiProgram.cs:

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .UseUraniumUI()
            .UseUraniumUIMaterial()
            .UseMauiCommunityToolkit()
            .ConfigureFonts(fonts =>
            {
                fonts.AddMaterialIconFonts();
            });

        // A set of custom services goes here, auth is a sample one
        builder.Services.AddSingleton<AuthenticationService>();

        builder.Services.Replace(
            new ServiceDescriptor(typeof(IDialogService),
                typeof(CustomDialogService)));

        return builder.Build();
    }
}

Here is my CustomDialogService.cs:

public class CustomDialogService : DefaultDialogService
{
    public override Task<IEnumerable<T>> DisplayCheckBoxPromptAsync<T>(
        string message,
        IEnumerable<T> selectionSource,
        IEnumerable<T>? selectedItems = null,
        string accept = "OK",
        string cancel = "Cancel",
        string? displayMember = null)
    {
        Console.WriteLine("IT WORKS!"); // <--- was not called and breakpoint was not hit
        return base.DisplayCheckBoxPromptAsync(message,
                selectionSource, selectedItems, accept, cancel,
                displayMember);
    }
}

Here is a part of my EmployeeForm.xaml:

<material:PickerField x:Name="LocationPicker"
                      Icon="{FontImageSource FontFamily=MaterialRegular,
                          Glyph={x:Static m:MaterialRounded.My_location},
                          Color={Binding TextColor, Source={x:Reference LocationPicker}}}"
                      Title="{x:Static localization:Strings.FormFieldLocation}"
                      SelectedItem="{Binding Location}"
                      ItemsSource="{Binding Locations}"
                      Unfocused="LocationPicker_OnUnfocused"
                      Focused="LocationPicker_OnFocused">
    <validations:RequiredValidation />
</material:PickerField>
enisn commented 3 months ago

Sorry my bad, I wrote the example without testing. Replacing the service doesn't work as it is

The following example can replace it without any problem:

builder.Services.Replace(ServiceDescriptor.Singleton<IDialogService, CustomDialogService>());
enisn commented 3 months ago

In the next version, I'll implement a lazy-loading & search capabilities, I added it to the roadmap, but for now, you can implement something on your own in this version

MikkBenelis commented 3 months ago

Thanks, it'll be really useful. I need it now so will implement something by myself for this version. I've tried to replace this service like you suggested, but an overridden version still was not called... I suppose it is used in a different way for the PickerField compared to MultipleSelectionField.

enisn commented 3 months ago

For single selections, I can suggest using AutoCompleteTextField, it allows searching inside ItemsSource but it doesn't force to pick one of the items from ItemsSource, you can add a simple validation logic on your own.

Here a simple google search implementation sample with it:

https://github.com/enisn/UraniumUI/blob/a450de874ee476d11e8b8195dcd523178f737458/demo/UraniumApp/Pages/AutoCompleteTextField/GoogleAutoCompletePage.xaml#L14

https://github.com/enisn/UraniumUI/blob/a450de874ee476d11e8b8195dcd523178f737458/demo/UraniumApp/Pages/AutoCompleteTextField/GoogleAutoCompleteViewModel.cs#L28-L34