Weird disappearing error

Eduardo Gomez Romero 1,335 Reputation points
2025-01-17T23:11:03.83+00:00

I have a very weird error where everything disappears after a while

and I think the fault is here

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="METROWIND.Views.NewsPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:constants="clr-namespace:METROWIND.Constants"
    xmlns:ffimageloading="clr-namespace:FFImageLoading.Maui;assembly=FFImageLoading.Maui"
    xmlns:models="clr-namespace:METROWIND.Models"
    xmlns:rex="clr-namespace:METROWIND.Resources"
    xmlns:vm="clr-namespace:METROWIND.ViewModel"
    x:DataType="vm:NewsPageViewModel">

    <Grid
        Padding="5,0,5,0">

        <CollectionView
            x:Name="NewsList"
            ItemsSource="{x:Binding ArticleList}"
            SelectionMode="None">

            <CollectionView.ItemsLayout>
                <LinearItemsLayout
                    ItemSpacing="10"
                    Orientation="Vertical" />
            </CollectionView.ItemsLayout>

            <CollectionView.EmptyViewTemplate>
                <DataTemplate>
                    <VerticalStackLayout
                        HorizontalOptions="CenterAndExpand"
                        VerticalOptions="CenterAndExpand">
                        <ActivityIndicator IsRunning="True" />
                        <Label
                            HorizontalOptions="Center"
                            Text="{x:Static rex:AppResource.Loading}" />
                    </VerticalStackLayout>
                </DataTemplate>
            </CollectionView.EmptyViewTemplate>

            <CollectionView.ItemTemplate>
                <DataTemplate x:DataType="models:Article">
                    <Border
                        Padding="10"
                        StrokeShape="RoundRectangle 20"
                        StrokeThickness="1">
                        <Grid
                            Padding="10"
                            ColumnDefinitions="Auto,*"
                            RowDefinitions="250,Auto,Auto,Auto,Auto"
                            RowSpacing="10">
                            <ffimageloading:CachedImage
                                Grid.ColumnSpan="2"
                                Aspect="AspectFill"
                                BitmapOptimizations="True"
                                CacheDuration="30"
                                ErrorPlaceholder="no_image.png"
                                LoadingPlaceholder="loading.gif"
                                Source="{x:Binding UrlToImage,
                                                   TargetNullValue=no_image.png}" />
                            <!--  Title  -->
                            <Label
                                Grid.Row="1"
                                Grid.ColumnSpan="2"
                                FontAttributes="Bold"
                                FontSize="Large"
                                Text="{x:Binding Title}" />
                            <!--  Source and Icon  -->
                            <HorizontalStackLayout
                                Grid.Row="2"
                                Grid.ColumnSpan="2"
                                Spacing="10">
                                <Label
                                    FontFamily="ma"
                                    FontSize="Large"
                                    Text="{x:Static constants:MaterialFonts.Newspaper}"
                                    VerticalTextAlignment="Center" />
                                <Label
                                    Text="{x:Binding Source.Name}"
                                    VerticalTextAlignment="Center" />
                            </HorizontalStackLayout>
                            <!--  Author and Date  -->
                            <Grid
                                Grid.Row="3"
                                Grid.ColumnSpan="2"
                                ColumnDefinitions="Auto,*,Auto"
                                ColumnSpacing="10">
                                <Label
                                    FontFamily="ma"
                                    FontSize="Large"
                                    Text="{x:Static constants:MaterialFonts.Person}" />
                                <Label
                                    Grid.Column="1"
                                    Text="{x:Binding Author,
                                                     TargetNullValue='Author unknown'}"
                                    VerticalTextAlignment="Center" />
                                <Label
                                    Grid.Column="2"
                                    Text="{x:Binding PublishedAt}" />
                            </Grid>
                        </Grid>
                        <Border.GestureRecognizers>
                            <TapGestureRecognizer
                                Command="{Binding ShowNewsDetailCommand, Source={RelativeSource AncestorType={x:Type vm:NewsPageViewModel}}, x:DataType=vm:NewsPageViewModel}"
                                CommandParameter="{x:Binding .}" />
                        </Border.GestureRecognizers>
                    </Border>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </Grid>
</ContentPage>


vm

namespace METROWIND.ViewModel
{
    public partial class NewsPageViewModel: ObservableObject
    {
        public ObservableCollection<Article> ArticleList { get; set; } = [];

        readonly IHttpService _httpService;
        readonly IDeviceLanguageService _deviceLanguageService;
        readonly IAppService _appService;

        public NewsPageViewModel(IDeviceLanguageService deviceLanguageService,
            IHttpService httpService,
            IAppService appService)
        {
            _deviceLanguageService = deviceLanguageService;
            _httpService = httpService;
            _appService = appService;
            LoadNews();

        }

        public async void LoadNews()
        {
            var language = _deviceLanguageService.GetDeviceCultureInfo();
            var newsUrl = AppConstants.GetNewsUrl(language.TwoLetterISOLanguageName);

            var newsObj = await _httpService.GetAsync<News>(newsUrl);

            if (newsObj != null && newsObj.Articles != null)
            {
                foreach (var article in newsObj.Articles)
                {
                    ArticleList.Add(article);
                }
            }
        }

        [RelayCommand]
        async Task ShowNewsDetail(Article article)
        {
            if (article != null)
            {
                await _appService.NavigateToPage($"{nameof(ArticleDetailsPage)}",
                     new Dictionary<string, object> {{ "articleObj", article }
                });
            }
        }
    }
}

error

https://reccloud.com/u/rpo2p6u

in this video I show the app working on debug on an emulator, but when I use it in my phone for a while, everything disappears, and I don't get any errors

on the emulator also occurs

https://reccloud.com/u/lgh9z56

i do not know if has something do with the binding mismatch error that I get in the station page

  <Grid>
      <Border
          x:Name="MobileContent"
          Style="{x:StaticResource ChargeStationBorderStyle}">
          <expander:SfExpander
              AnimationDuration="200"
              IsExpanded="{x:Binding IsExpanded}">
              <expander:SfExpander.Header>
                  <Grid RowDefinitions="48">
                      <Label Style="{x:StaticResource ChooseStationLabelStyle}" />
                  </Grid>
              </expander:SfExpander.Header>
              <expander:SfExpander.Content>
                  <Grid
                      Padding="10,0,0,0"
                      RowDefinitions="Auto">
                      <CollectionView ItemsSource="{x:Binding TurbinePins}">
                          <CollectionView.ItemTemplate>
                              <DataTemplate x:DataType="model:TurbinePin">
                                  <Border Stroke="Transparent">
                                      <HorizontalStackLayout Spacing="10">
                                          <Label Style="{x:StaticResource ElectricBoltLabelStyle}" />
                                          <Label
                                              Style="{x:StaticResource AddressLabelStyle}"
                                              Text="{x:Binding Turbine.Name}" />
                                      </HorizontalStackLayout>
                                      <Border.Behaviors>
                                          <mct:TouchBehavior
                                              DefaultBackgroundColor="White"
                                              PressedBackgroundColor="CornflowerBlue" />
                                      </Border.Behaviors>
                                      <Border.GestureRecognizers>
                                          <TapGestureRecognizer
                                              Command="{x:Binding ItemSelectedCommand,
                                                                  Source={RelativeSource AncestorType={x:Type vm:ChargingStationsMapPageViewModel}},
                                                                  x:DataType=vm:ChargingStationsMapPageViewModel}"
                                              CommandParameter="{x:Binding Turbine}" />
                                      </Border.GestureRecognizers>

                                  </Border>
                              </DataTemplate>
                          </CollectionView.ItemTemplate>
                      </CollectionView>
                  </Grid>
              </expander:SfExpander.Content>
          </expander:SfExpander>
      </Border>

      <maps:Map
          x:Name="ChargingStationMap"
          ItemsSource="{x:Binding TurbinePins}"
          VerticalOptions="FillAndExpand">
          <maps:Map.ItemTemplate>
              <DataTemplate x:DataType="model:TurbinePin">
                  <controls:CustomMapPin
                      Address="{x:Binding Turbine.Address}"
                      Images="{x:Binding Turbine.ImagesURLs}"
                      Label="{x:Binding Turbine.Name}"
                      Location="{x:Binding Turbine.Location}"
                      MarkerClickedCommand="{x:Binding PinClickedCommand}"
                      MarkerClickedCommandParameter="{x:Binding}" />
              </DataTemplate>
          </maps:Map.ItemTemplate>
      </maps:Map>

      <Button
          x:Name="mapLayers"
          Command="{x:Binding OpenMapLayerOptionsCommand}"
          Style="{x:StaticResource MapButtonStyle}">
          <Button.ImageSource>
              <FontImageSource
                  FontFamily="ma"
                  Glyph="{x:Static constant:MaterialFonts.Layers}" />
          </Button.ImageSource>
      </Button>

      <popup:SfPopup
          x:Name="MapChangeTypuPopUp"
          RelativeView="{x:Reference mapLayers}"
          Style="{x:StaticResource ChargeStationPopupStyle}"
          WidthRequest="{x:Binding Width,
                                   Source={x:Reference mapLayers}}">
          <popup:SfPopup.PopupStyle>
              <popup:PopupStyle CornerRadius="8" />
          </popup:SfPopup.PopupStyle>
          <popup:SfPopup.ContentTemplate>
              <DataTemplate x:DataType="vm:ChargingStationsMapPageViewModel">
                  <VerticalStackLayout Spacing="10">
                      <VerticalStackLayout BindableLayout.ItemsSource="{x:Binding MapTypeButtons}">
                          <BindableLayout.ItemTemplate>
                              <DataTemplate x:DataType="model:MapTypeButton">
                                  <controls:CustomImageButton
                                      BorderColor="{Binding SelectedColor}"
                                      Caption="{Binding Caption}"
                                      ClickCommand="{Binding ChangeMapTypeCommand, Source={RelativeSource AncestorType={x:Type vm:ChargingStationsMapPageViewModel}}, x:DataType=vm:ChargingStationsMapPageViewModel}"
                                      ImageName="{Binding ImageName}"
                                      MapNumber="{x:Binding MapNumber}"
                                      Parameter="{Binding}" />
                              </DataTemplate>
                          </BindableLayout.ItemTemplate>
                      </VerticalStackLayout>
                  </VerticalStackLayout>
              </DataTemplate>
          </popup:SfPopup.ContentTemplate>
      </popup:SfPopup>
  </Grid>


vm

public partial class ChargingStationsMapPageViewModel: AppShellViewModel
{
    public SfPopup? MapDialogPopUp;

    public Map? MapView;

    [ObservableProperty]
    bool isExpanded;

    public ChargingStationsMapPageViewModel(
        ITurbineService turbineService, IAppService
        appService, IServiceProvider serviceProvider,
        NoInternetPopUp noInternetPopUp,
        ICommandHandler commandHandler, IConnectivity connectivity)
        : base(turbineService, appService, serviceProvider, commandHandler, connectivity, noInternetPopUp)
    {
        MapDialogButtons();

    }
    public ObservableCollection<MapTypeButton> MapTypeButtons { get; set; } = [];

    private void MapDialogButtons()
    {
        MapTypeButtons.Add(new MapTypeButton
        {
            Caption = AppResource.Default,
            ImageName = MaterialFonts.Map,
            Selected = true,
            MapNumber = 1
        });
        MapTypeButtons.Add(new MapTypeButton
        {
            Caption = AppResource.Satelite,
            MapNumber = 2,
            ImageName = MaterialFonts.Satellite,
        });
    }

    [RelayCommand]
    void ItemSelected(Turbine Turbine)
    {
        if (Turbine == null || MapView == null)
        {
            return;
        }
        var mapSpan = MapSpan.FromCenterAndRadius(Turbine.Location,
            Distance.FromKilometers(2));

        MapView!.MoveToRegion(mapSpan);
    }

    [RelayCommand]

    void OpenMapLayerOptions()
    {
        MapDialogPopUp!.IsOpen = true;
    }

    [RelayCommand]
    void ChangeMapType(MapTypeButton mapTypeCustomButton)
    {
        if (mapTypeCustomButton == null)
        {
            return;
        }

        foreach (var mapTypeButton in MapTypeButtons)
        {
            mapTypeButton.Selected = false;
        }

        mapTypeCustomButton.Selected = true;

        switch (mapTypeCustomButton.MapNumber)
        {
            case 1:
                MapView!.MapType = MapType.Street;
                break;
            case 2:
                MapView!.MapType = MapType.Satellite;
                break;
        }

        MapDialogPopUp!.IsOpen = false;
    }
}

this view model inherits from the shell

        public AppShellViewModel(ITurbineService turbineService, IAppService appService,
            IServiceProvider serviceProvider, ICommandHandler commandHandler,
            IConnectivity connectivity, NoInternetPopUp noInternetPopUp)
        {
            _serviceProvider = serviceProvider;
            _turbineService = turbineService;
            _appService = appService;
            _commandHandler = commandHandler;
            _connectivity = connectivity;
            _noInternetPopUp = noInternetPopUp;

            _turbineService.NoInternet += TurbineService_NoInternet;

            InitializeCommand();

            _turbineService.SetPinClickHandler(this);

            if (!_isConnectivityEventRegistered)
            {
                _connectivity.ConnectivityChanged += Connectivity_ConnectivityChanged;
                _isConnectivityEventRegistered = true;
            }
        }

        private void TurbineService_NoInternet()
        {
            _noInternetPopUp.Show();
        }

        private void InitializeCommand()
        {
            _commandHandler.SetPinClickedCommand(new Command<TurbinePin>(async (pin) =>
            await PinMarkerClicked(pin)));
        }

        [RelayCommand]
        async Task Appearing(AppShell appShell)
        {
            _shell = appShell;

            try
            {
                if (TurbinePins.Count == 0 && !isInitializing)
                {
                    isInitializing = true;
                    await _turbineService.InitializeAsync();
                    isInitializing = false;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Initialization failed: {ex.Message}");
                isInitializing = false;
            }
        }

        private void Connectivity_ConnectivityChanged(object? sender, ConnectivityChangedEventArgs e)
        {
            HandleConnectivityChangeAsync();
        }

        private async void HandleConnectivityChangeAsync()
        {
            if (_connectivity.NetworkAccess == NetworkAccess.Internet)
            {
                _noInternetPopUp.IsOpen = false;

                try
                {
                    if (TurbinePins.Count == 0 && !isInitializing)
                    {
                        isInitializing = true;
                        await _turbineService.InitializeAsync();
                        isInitializing = false;
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"Initialization failed: {ex.Message}");
                    isInitializing = false;
                }
            }
            else
            {
                TurbineService_NoInternet();
            }
        }

        [RelayCommand]
        void OpenMenu()
        {
            IsMenuPopUpOpen = true;
        }

        [RelayCommand]
        void ToggleSwitch()
        {
            if (IsCompactMode)
            {
                _shell!.FlyoutWidth = 65;
            }
            else
            {
                _shell!.FlyoutWidth = 300;
            }

            IsMenuPopUpOpen = false;
        }

        public async Task PinMarkerClicked(TurbinePin turbine)
        {
            if (turbine != null)
            {
#if ANDROID || IOS
                await _appService.NavigateToPage(nameof(TurbineDetailPage),
            new Dictionary<string, object> { { "SelectedTurbine", turbine } });
#elif WINDOWS || MACCATALYST
                var viewModel = _serviceProvider.GetRequiredService<TurbineDetailPageViewModel>();

                viewModel.SelectedTurbine = turbine;

                var page = _serviceProvider.GetRequiredService<TurbineDetailPage>();

                page.BindingContext = viewModel;

                var secondWindow = new Window(page);

                var existingWindow = Application.Current!.Windows.FirstOrDefault(
                    w => w.Page is TurbineDetailPage);

                if (existingWindow != null)
                {
                    Application.Current?.ActivateWindow(existingWindow);
                }
                else
                {
                    Application.Current!.OpenWindow(secondWindow);
                }
#endif
            }
        }

ps: btw why the loading text is on the top, in the xmal you can see that is on the center

Could you please check the code

https://github.com/eduardoagr/METROWIND/tree/MetroWind-1-2

.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
4,013 questions
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 80,851 Reputation points Microsoft External Staff
    2025-01-22T08:57:55.5466667+00:00

    Hello,

    I find this issue is related to the <ffimageloading:CachedImage>, If you have many items in the CollectionView, and click <ffimageloading:CachedImage> when it is loading, you will get white and empty view.

    Then, I use Image to instead of ffimageloading:CachedImage like following code in the NewsPage.xaml

         <!--<ffimageloading:CachedImage
                                    Grid.ColumnSpan="2"
                                    Aspect="{OnIdiom Desktop=AspectFill, Phone=AspectFit}"
                                    BitmapOptimizations="True"
                                    CacheDuration="60"
                                    DownsampleToViewSize="True"
                                    ErrorPlaceholder="no_image.png"
                                    LoadingPlaceholder="loading.gif"
                                    Source="{x:Binding UrlToImage,
                                                       TargetNullValue=no_image.png}" />-->
    <Image
                                     Grid.ColumnSpan="2"
                                     Aspect="{OnIdiom Desktop=AspectFill, Phone=AspectFit}"                              
                                     Source="{x:Binding UrlToImage,
                                     TargetNullValue=no_image.png}"
    />
    

    Then, if you use webview to display content, please open MauiProgram.cs, add following webviewhandler to enable the JS and all mixed content showing in CreateMauiApp method.

    Microsoft.Maui.Handlers.WebViewHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
            {
    #if ANDROID
                handler.PlatformView.Settings.JavaScriptEnabled=true;
                handler.PlatformView.Settings.MixedContentMode = Android.Webkit.MixedContentHandling.AlwaysAllow;
                handler.PlatformView.SetWebViewClient(new MyWebViewClient());
     
    #endif
            });
    
    
    #if ANDROID
    internal class MyWebViewClient : WebViewClient
    {
        public override void OnReceivedSslError(Android.Webkit.WebView? view, SslErrorHandler? handler, SslError? error)
        {
            base.OnReceivedSslError(view, handler, error);
            handler.Cancel();
            view.LoadData("<html><body><h2>Error loading page</h2></body></html>", "text/html", "UTF-8");
        }
    }
    #endif
    
     
    

    And add these namespace.

    #if ANDROID
     
    using Android.Net.Http;
    using Android.Webkit;
    #endif
    

    In the end, open the ArticleDetailsPage.xaml.cs, if this page disappearing, you can set the webview.source=null, after that, GC will execute,

    public partial class ArticleDetailsPage : ContentPage
    {
        public ArticleDetailsPage(ArticleDetailsPageViewModel articleDetailsPageViewModel)
        {
            InitializeComponent();
            BindingContext = articleDetailsPageViewModel;
        }
     
        protected override void OnDisappearing()
        {
            base.OnDisappearing();
     
            if (webView != null)
            {                 
                webView.Source = null;                    
            }
        }
    

    Best Regards,

    Leon Lu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


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.