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.24k stars 1.76k forks source link

Compiled Binding to Array.Count provides no result #13872

Open omghb opened 1 year ago

omghb commented 1 year ago

Description

Compiled Binding to Array.Count provides no result. Building works without any error or warning.

Last version that worked well: Xamarin Forms 5.0.

We run into this issue during migration from Xamarin Forms 5.0 to MAUI 7.0. In Xamarin Forms this worked well.

Steps to Reproduce

  1. Create a new empty MAUI app
  2. Replace content of MainPage.xaml with:
<?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:local="clr-namespace:MauiApp2"
             x:Class="MauiApp2.MainPage" x:DataType="local:MainViewModel">

    <VerticalStackLayout>
        <Label Text="List.Count:"/>
        <Label Text="{Binding List.Count}"/>

        <Label Text="ListCount:"/>
        <Label Text="{Binding ListCount}"/>
    </VerticalStackLayout>
</ContentPage>
  1. Replace MainPage.xaml.cs with
    
    namespace MauiApp2;

public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); BindingContext = new MainViewModel(); } }

public class MainViewModel { private readonly string[] list = new[] { "Bill", "Steve", "John" };

public IReadOnlyList<string> List => list;

public int ListCount => list.Length;

}



**Note:** You might need to adapt the namespace.

4. Run application. 
  - See that first Binding results in an empty value -> BUG
  - Second Binding results in the value 3 -> correct.

### Link to public reproduction project repository

-

### Version with bug

7.0 (current)

### Last version that worked well

Unknown/Other

### Affected platforms

iOS, Android, Windows

### Affected platform versions

All

### Did you find any workaround?

_No response_

### Relevant log output

_No response_
ghost commented 1 year 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.

mattleibow commented 1 year ago

@StephaneDelcroix thoughts?

StephaneDelcroix commented 1 year ago
    public int ListCount => list.Length;

🧐

what would List.Count return ?

omghb commented 1 year ago

It returns 3. That's the tricky part 😉.

An Array has not a visible Count property. The visible property is the Length property.

However, an Array implements the interfaces ICollection, ICollection<T> and IReadOnlyCollection<T>. All of them declare a property Count. So the Array supports the Count property when used via interface.

We expose Collections often via IReadOnlyList<T> within a ViewModel and Bind to them. In Xamarin it was possible to Bind to the Count property. In MAUI it seems that this is not working anymore.

We could rewrite the example also like this:

public int ListCount => List.Count;
Zhanglirong-Winnie commented 1 year ago

Verified this issue with Visual Studio Enterprise 17.7.0 Preview 2.0. Can repro on android and windows platform with above code. Screenshot 2023-06-21 110223 Screenshot 2023-06-21 110357

StephaneDelcroix commented 1 year ago

My current tests shows that it actually works with XamlC on (and compiled bindings) like in Release but fails in DEBUG. and it's not beer-o-clock yet

StephaneDelcroix commented 1 year ago

this probably never worked on XF, the difference being that maui disable Xaml compilation on debug builds

omghb commented 1 year ago

It works with XF 5 for a released and published App (in Debug and Release mode).

We run into multiple bugs because of this issue after migration to MAUI. And we had to implement workarounds for those bindings so that the App works with MAUI again.

omghb commented 5 months ago

Bug is still in version 8.0.40.

The new collection initializer of C# 12 will also not work:

public IReadOnlyList<string> List { get; private set; } = [];

Using {Binding List.Count} does not work for [] although the interface supports the Count property: IReadOnlyList<T>.Count.