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
21.94k stars 1.7k forks source link

CollectionView ItemTemplate Binding does not always display full string from model #20758

Open JonPetitta opened 6 months ago

JonPetitta commented 6 months ago

Description

While running on Android using CollectionView with a simple model that has a string property, let's call it Name. The full string is not always shown. I have created 200 model items in a loop with the name set as follows. item.Name = "Item " + $"{i}";

Thus creating Item 0 Item 1 ... Item 199

Sometimes the ItemTemplate Label will not have the full string, and only show the following. Item

Steps to Reproduce

1 Create maui app 2 Create model with a string property 3 Initialize 200 instances of the model into a list setting the string property to "FOO " + $"{i}" 4 Create ViewModel containing the 200 items 5 Add CollectionView to a page and bind it to the ViewModel list 6 Add a simple ItemTemplate to the collection view to display the string property of the model bound to a Label 7 Run the application on Android, scroll down some and you will see some Labels only show "FOO"

Link to public reproduction project repository

https://github.com/JonPetitta/CollectionViewItemIssue

Version with bug

8.0.3 GA

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 14

Did you find any workaround?

No response

Relevant log output

No response

drasticactions commented 6 months ago

This has nothing to do with the Binding, it's a layout issue.

スクリーンショット 2024-02-22 18 08 34

If you use the Live Visual Tree and Live Property Explorer, you can see that the missing number does exist on the Label, so it's not a binding issue. The issue is the Horizontal Stack Layout and how template generation/recycling works. Since you don't provide a specific width for the Name label, it has to be calculated when the layout is drawn. When you scroll down, the template is being recycled and reused due to virtualization, and the template being selected is one where the width for the name is less then the total width of the new line, hence why it's cut off. If you force the view to redrawn (such as resizing the Window in the case of the Windows Android Subsystem) it would force it to recalculate the line, showing the full text.

That is probably where the bug is in MAUI, since if MAUI/Android not relaying out its UI when the text changes, then that's incorrect behavior. How and when virtualization within CollectionView works with mutating items should be looked at.

As an enduser: Relying on Auto/* Layout where widths and heights are calculated on the fly are also not great for general performance, since you're relying on MAUI or the platform itself to redraw itself based on whatever new context exists. When possible, IMO, giving explicit Widths or Heights for your stack layout or grid items will generally lead to better layouts and performance.

TL;DR : Binding is fine, layout is broken.

ghost commented 6 months ago

We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.

XamlTest commented 4 months ago

Verified this on VS 17.10.0 Preview 2.0(8.0.14). Repro on Android 14.0-API34, not repro on Windows 11, iOS 17.2 and MacCatalyst with below Project: CollectinViewItemIssue.zip