dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.04k stars 1.73k forks source link

[BUG] Duplicated items in searched results #25020

Open suugbut opened 16 hours ago

suugbut commented 16 hours ago

Description

This problem occurs only on Windows. No problem on Android. Not tested on other platforms.

Once the app runs, the main page shows the following 3 items. image

I type a for example, the list shows duplicated items as follows. image

And if I clear the search entry, the list shows duplicated items too. image

Expected Behavior

There should not be duplicated items.

Steps to Reproduce

Create default MAU project with the following package references:

<PackageReference Include="CommunityToolkit.Maui" Version="9.1.0" />
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.91" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.91" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
// model
public class Library
{
    public required string Title { get; init; }
    public required ImageSource ImageSource { get; init; }
}
// repo
public class LibraryRepo
{
    private static readonly IEnumerable<Library> _libraries =
    [
        new()
        {
            Title = "AAA",
            ImageSource = "https://api.nuget.org/v3-flatcontainer/communitytoolkit.mvvm/8.2.0/icon"
        },
        new()
        {
            Title = "BBB",
            ImageSource = "https://api.nuget.org/v3-flatcontainer/sentry.maui/3.33.1/icon"
        },
        new()
        {
            Title = "CCC",
            ImageSource = "https://api.nuget.org/v3-flatcontainer/esri.arcgisruntime.maui/100.14.1-preview3/icon"
        }
    ];
    public static IEnumerable<Library> GetAll()
    {
        return _libraries;
    }
    public static IEnumerable<Library> GetByTitle(string word)
    {
        return _libraries
            .Where(l => l.Title.Contains(word, StringComparison.OrdinalIgnoreCase));
    }
}
// view model
public class MainPageViewModel
{
    public ObservableCollection<Library> Libraries { get; } = [];

    public ICommand UserStoppedTypingCommand { get; }

    void ReloadLibraries(IEnumerable<Library> libraries)
    {
        Libraries.Clear();
        foreach (var library in libraries)
        {
            Libraries.Add(library);
        }
    }

    public MainPageViewModel()
    {
        ReloadLibraries(LibraryRepo.GetAll());
        UserStoppedTypingCommand = new Command<string>(
        execute: s =>
        {
            if (string.IsNullOrWhiteSpace(s))
                ReloadLibraries(LibraryRepo.GetAll());
            else 
                ReloadLibraries(LibraryRepo.GetByTitle(s));
        });
    }
}
// page
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:loc="clr-namespace:MaybeBug"
             xmlns:tool="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             BindingContext="{loc:MainPageViewModel}"
             x:Class="MaybeBug.MainPage"
             x:DataType="loc:MainPageViewModel">
    <CollectionView ItemsSource="{Binding Libraries}">
        <CollectionView.Header>
            <HorizontalStackLayout>
                <Entry x:Name="SearchBar"
                       WidthRequest="200">
                    <Entry.Behaviors>
                        <tool:UserStoppedTypingBehavior Command="{Binding UserStoppedTypingCommand}"
                                                        CommandParameter="{Binding Text, Source={Reference SearchBar}}" />
                    </Entry.Behaviors>
                </Entry>
            </HorizontalStackLayout>
        </CollectionView.Header>
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="loc:Library">
                <HorizontalStackLayout>
                    <Image Source="{Binding ImageSource}"
                           WidthRequest="100"
                           HeightRequest="100" />
                    <Label Text="{Binding Title}"
                           VerticalTextAlignment="Center" />
                </HorizontalStackLayout>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</ContentPage>

Link to public reproduction project repository

https://github.com/suugbut/BugReport

Version with bug

Unknown/Other

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Windows

Affected platform versions

OS: Windows 10 Pro 22H2

Did you find any workaround?

No response

Relevant log output

No response

jfversluis commented 13 hours ago

Just to rule out any external factors, if you do not use the UserStoppedTypingBehavior from the Toolkit, does that change anything in the behavior? It would be useful to maybe downgrade 1 or 2 versions of .NET MAUI to see if it works in earlier versions so we can see if its a regression or not.

suugbut commented 9 hours ago

I just removed UserStoppedTypingBehavior (see the last commit). The duplication no longer occurs but refreshing causes an empty image for the second item. image

This new issue occurs from version 8.0.7 to the latest for both Microsoft.Maui.Controls and Microsoft.Maui.Controls.Compatibility.

No issue for version 8.0.6 or earlier.