Search code examples
c#xamlmaui

.NET MAUI System.ObjectDisposedException: 'Cannot access a disposed object. Object name: 'Microsoft.Maui.Platform.LayoutViewGroup'.'


I have a big problem with my app, it crash with the error in the title.

I'm using WeakMessageReferences.

That's the class i created:

using CommunityToolkit.Mvvm.Messaging;

namespace NuesWarehouseMobile.Utilities
{
    internal static class RefreshManager
    {
        public static void RequestRefresh(string viewName)
        {
            WeakReferenceMessenger.Default.Send(new RefreshViewMessage(viewName));
        }

        public static void Register<TRecipient>(TRecipient recipient, Action<RefreshViewMessage> action) where TRecipient : class
        {
            WeakReferenceMessenger.Default.Register<RefreshViewMessage>(recipient, (r, m) => action(m));
        }
    
        public static void Unregister<TRecipient>(TRecipient recipient) where TRecipient : class
        {
            WeakReferenceMessenger.Default.Unregister<RefreshViewMessage>(recipient);
        }
    }
    
    public class RefreshViewMessage
    {
        public string ViewName { get; }
    
        public RefreshViewMessage(string viewName)
        {
            ViewName = viewName;
        }
    }

}

using the WeakReferences is generating the exception.

I tried to cache the views so they don't get disposed but it's not working.

I tried to make some strong references for the same thing but it's not working.

I tried to use different methods to update my views but only the messages are working so i have to stick for that.

View logic:

    using CommunityToolkit.Mvvm.Messaging;
using NuesWarehouse.Core.Dtos;
using NuesWarehouseMobile.Core.Interfaces.Services;
using NuesWarehouseMobile.Utilities;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows.Input;

namespace NuesWarehouseMobile.MenuView;

public partial class DocumentiDaEvadereView : ContentView
{
    private readonly IDocumentService _documentService;
    private int currentPage = 1;
    private int perPage = 20;
    private string stato = "Aperto-Picking-Parzialmente Evaso"; //SPAZIO VUOTO
    private string tipoDoc = "OrdineVendita";




    private bool _isLoading;
    public bool IsLoading
    {
        get => _isLoading;
        set
        {
            _isLoading = value;
            OnPropertyChanged(nameof(IsLoading));
        }
    }

    public ObservableCollection<DocumentiDto> Documents { get; set; }

    public ICommand LoadDocumentsCommand { get; }
    public ICommand NextPageCommand { get; }
    public ICommand PreviousPageCommand { get; }

    private int _currentPageDisplay;
    public int CurrentPageDisplay
    {
        get => _currentPageDisplay;
        set
        {
            _currentPageDisplay = value;
            OnPropertyChanged();
        }
    }


    public DocumentiDaEvadereView()
    {
        InitializeComponent();

        RefreshManager.Register(this, OnRefreshViewMessageReceived);

        IsLoading = true;
        _documentService = Application.Current.Handler.MauiContext.Services.GetService<IDocumentService>();
        Documents = new ObservableCollection<DocumentiDto>();
        LoadDocumentsAsync();

        LoadDocumentsCommand = new Command(async () => await LoadDocumentsAsync());
        NextPageCommand = new Command(async () => await LoadNextPageAsync());
        PreviousPageCommand = new Command(async () => await LoadPreviousPageAsync());

        //CurrentPageDisplay = currentPage;

        double screenHeight = DeviceDisplay.MainDisplayInfo.Height / DeviceDisplay.MainDisplayInfo.Density;
        double gridHeight = screenHeight * 0.6;
        DocumentsDataGrid.HeightRequest = gridHeight;

        BindingContext = this;
        // Carica la prima pagina
        LoadDocumentsCommand.Execute(null);

        
        IsLoading = false;
    }

    private async Task LoadDocumentsAsync(int page = 1)
    {
        
        var documents = await _documentService.GetDocumentsByPage(page, perPage, tipoDoc, stato);
        Documents.Clear();
        foreach (var document in documents)
        {
            if (document.Stato == "Evaso")
            {
                document.StatoColor = "Green";
            }
            else if (document.Stato == "Parzialmente Evaso")
            {
                document.StatoColor = "Orange";
            }
            else
            {
                document.StatoColor = "Yellow";
            }
            Documents.Add(document);
        }
        CurrentPageDisplay = currentPage;

        DocumentsDataGrid.ItemsSource = null;
        DocumentsDataGrid.ItemsSource = Documents;
    }

    private async Task LoadNextPageAsync()
    {
        currentPage++;
        await LoadDocumentsAsync(currentPage);
    }

    private async Task LoadPreviousPageAsync()
    {
        if (currentPage > 1)
        {
            currentPage--;
            await LoadDocumentsAsync(currentPage);
        }
    }


    // Metodo per aprire una nuova view
    private void ApriNuovaPaginaCommand(object sender, EventArgs e)
    {
        IsLoading = true;
        var button = sender as Button;
        if (button?.CommandParameter is string documentId)
        {
            Debug.WriteLine(documentId);
            Navigation.PushAsync(new EvasioneDocumentoPage(documentId));
        }
        else
        {
            Debug.WriteLine("====ATTENZIONE, PARAMETRO documentId NON PASSATO CORRETTAMENTE====");
        }
        IsLoading = false;

    }

    private void OnRefreshViewMessageReceived(RefreshViewMessage message)
    {
        if (message.ViewName == "EvasioneDocumento") // Controllo parametro
        {
            Debug.WriteLine("Messaggio ricevuto in DocumentsView! Aggiorno i documenti...");
            _ = LoadDocumentsAsync(1); // Ricarica i documenti
        }
    }

    ~DocumentiDaEvadereView()
    {
        // Deregistrazione per evitare memory leaks
        RefreshManager.Unregister(this);
    }
}

Solution

  • I just fixed it by adding "this.IsLoaded" to the receiver of the message :D