Searchable Indented Dropdown

Viewed 23

I would like to create a dropdown menu, that can be searched and will display it's options in an indented manner. I have already built a dropdown that will asynchronously refresh based on the search query I enter. However it does not allow me, to show all children on a parent match.

For example:

enter image description here

Basically when I start searching for something, I would like not only the parent to show up, but also the children of a matching option. The search should also work on the children. So in the case of USA, only Austin shows up.

I attempted to look for other solutions, but I only found options to indent certain list items when added in order. Searching would still behave normally though.

1 Answers

Take a look at this Fiddle and adapt it to use a TextBox event called TextChanged.

Fiddle code:

public class Country
{
    public string Name { get; set; }
    public List<City> Cities { get; set; }
}

public class City
{
    public string Name { get; set; }
}

public static void Main()
{
    var items = new List<Country>()
    {
        new Country() { Name = "Austria", Cities = new List<City>() { new City() { Name = "Vienna" }, new City() { Name = "Linz" } } },
        new Country() { Name = "Australia", Cities = new List<City>() { new City() { Name = "Sydney" }, new City() { Name = "Melbourne" } } },
        new Country() { Name = "USA", Cities = new List<City>() { new City() { Name = "Austin" }, new City() { Name = "New York" } } }
    };
    var searchTerm = "aus";
    
    var filteredItems = items.Where(i => i.Name.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) ||
                                         i.Cities.Any(c => c.Name.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)))
                            .Select(i => new Country()
                                    {
                                        Name = i.Name,
                                        Cities = i.Cities.Where(c => c.Name.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) ||
                                                                     i.Name.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)).ToList()
                                    })
                            .ToList();
    
    
    Console.WriteLine("****Unfiltered:");
    Output(items);
    Console.WriteLine("\r\n****Filtered:");
    Output(filteredItems);
}

public static void Output(List<Country> countries)
{
    foreach (var country in countries)
    {
        Console.WriteLine(country.Name);
        foreach (var city in country.Cities)
        {
            Console.WriteLine("    " + city.Name);
        }
    }
}

Output:

****Unfiltered:
Austria
    Vienna
    Linz
Australia
    Sydney
    Melbourne
USA
    Austin
    New York

****Filtered:
Austria
    Vienna
    Linz
Australia
    Sydney
    Melbourne
USA
    Austin
Related