MAUI app crash when execute BindableLayout.SetItemsSource with visual studio 2022 17.14.7

Anton Moroder 20 Reputation points
2025-06-30T10:33:22.18+00:00

After the command BindableLayout.SetItemsSource(FlexLayout, IEnumerable) in DEBUG environment and WinUI it gives the error:

System.ArgumentOutOfRangeException in System.Private.CoreLib.dll

Exception thrown: 'System.Reflection.TargetInvocationException' in System.Private.CoreLib.dll

and doesn't crash.

Instead in RELEASE (WinUI, Android and iOS) after the command BindableLayout.SetItemsSource(FlexLayout, IEnumerable)

the app crash.

NB. the System.ArgumentOutOfRangeException error occurs n times as long as the IEnumerable list (list count=10 errors=10)

in previous versions of visual studio everything worked fine

Developer technologies | .NET | .NET MAUI
{count} votes

Accepted answer
  1. Tony Dinh (WICLOUD CORPORATION) 160 Reputation points Microsoft External Staff
    2025-07-03T08:23:01.45+00:00

    Hello Anton Moroder!

    I noticed that you're trying to access the first element of an empty PayGuests list, which can lead to a System.Reflection.TargetInvocationException, especially as it crashes in Release mode.

    When the UI is being rendered, it attempts to bind to PayGuests[0].GuestName, but the PayGuests data list hasn't populated yet. You can see the exception count of System.ArgumentOutOfRangeException error corresponds to the number of items in the data list, which strongly suggests that the data within the IEnumerable list hasn't loaded by the time of binding.

    The reason it might work in Debug but not Release is due to the optimizations in Release builds. These optimizations can result in the following:

    • Stricter error handling: Release builds are less forgiving of unexpected conditions like accessing an empty list, as mentioned above.
    • Faster execution: The faster pace increases the likelihood of the UI trying to access the data before it's ready.
    • Different execution order: In older .NET runtime versions, there might have been slight variations in the timing of data binding and UI rendering.

    I suggest adding a null and count check within the FirstGuestName property to handle this scenario. This ensures that you only try to access the first element when the list actually contains elements, preventing the exception. It will display "Loading..." initially and then show the data once it's loaded.

    I have created an example implementation for you:

    //Your example class
    public class Xenus_GIS_InHouseReservation : INotifyPropertyChanged
    {
        private ObservableCollection<PayGuestItem> _payGuests = new();
     
        public Xenus_GIS_InHouseReservation()
        {
            PayGuests = new ObservableCollection<PayGuestItem>();
        }
     
        public event PropertyChangedEventHandler PropertyChanged;
     
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
     
        public ObservableCollection<PayGuestItem> PayGuests
        {
            get => _payGuests;
            set
            {
                if (_payGuests != value)
                {
                    _payGuests = value;
                    OnPropertyChanged(nameof(PayGuests));
                    OnPropertyChanged(nameof(FirstGuestName));
                }
            }
        }
     
        public string FirstGuestName
        {
            get
            {
                return PayGuests?.FirstOrDefault()?.GuestName ?? "Loading...";
            }
        }
     
        public void NotifyUpdate()
        {
            OnPropertyChanged(nameof(FirstGuestName));
        }
    }
    

    Load data example implementation:

    public partial class with_error_page : ContentPage
    {
        ObservableCollection<Xenus_GIS_InHouseReservation> Reservations = new ();
        public with_error_page()
        {
            InitializeComponent();
            Reservations.Add(new Xenus_GIS_InHouseReservation
            {
                PayGuests = new ObservableCollection<PayGuestItem> { }
            });
     
            Reservations.Add(new Xenus_GIS_InHouseReservation
            {
                PayGuests = new ObservableCollection<PayGuestItem> {
                        new PayGuestItem { GuestName = "Bob Johnson" },
                        new PayGuestItem { GuestName = "Charlie Brown" }
                    }
            });
            BindableLayout.SetItemsSource(listGuest, Reservations);
        }
     
        //Example stimulate value loaded after UI rendered and UI updated for first element in list
        public void OnAddItemClicked(object sender, EventArgs e)
        {
            Reservations[0].PayGuests.Add(new PayGuestItem { GuestName = "New Guest" });
            // Manually notify that FirstGuestName has changed
            Reservations[0].NotifyUpdate();
        }
    }
    

    In your XAML page, you can bind the name like this. I've also added a button to simulate this issue; you can see that the System.ArgumentOutOfRangeException is handled.

    <StackLayout>
        <FlexLayout x:Name="listGuest" Wrap="Wrap" Direction="Row">
            <BindableLayout.ItemTemplate>
                <DataTemplate x:DataType="local:Xenus_GIS_InHouseReservation">
                    <Border FlexLayout.Basis="50%">
                        <Label Text="{Binding FirstGuestName}"/>
                    </Border>
                </DataTemplate>
            </BindableLayout.ItemTemplate>
        </FlexLayout>
        <Button Text="Add Item" Clicked="OnAddItemClicked"/>
    </StackLayout>
    

    I hope this helps! If you encounter any issues, don't hesitate to let me know.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.