Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Page loaded event?

Is there a good way to make your own page loaded event. I'm having an issue on android where if I build a table dynamically before the page is fully loaded (displayed) on the device that as you scroll, the content that is off screen disappears.

If I add the content while the pages is already fully loaded everything works correctly.

Best Answer

Answers

  • JasonMaddenJasonMadden USMember ✭✭

    I tried using the OnAppearing already, but It happens a little to early :(.

  • gvsharmagorintagvsharmagorinta USMember ✭✭

    OnAppearing is works better.

  • yousufctecyousufctec USMember ✭✭✭

    OnAppearing will be executed before the screen comes, when you want an Loaded event that needs to be executed right after the screen comes, there is a workaround.

    1. Create an property in viewmodel like below.

          private bool _toggleTemp;
          public bool ToggleTemp
          {
              get => _toggleTemp;
              set => SetProperty(ref _toggleTemp, value);
          }
      
    2. Add the following line to the last line of the constructor.

      LoadingVm.ToggleTemp = true;

    3. Add an Switch to your screen and make IsVisible to false as below.

      <Switch IsToggled="{Binding ToggleTemp}" Toggled="Switch_OnToggled" IsVisible="False" />

    4. Now you can write the code that you want to write in Page Loaded in Switch_OnToggled.

          private async void Switch_OnToggled(object sender, ToggledEventArgs e)
          { 
              /* Your code goes here... */ 
          }
      

    Thanks!

    Regards,
    Yousuf.

  • SteveShaw.5557SteveShaw.5557 USMember ✭✭✭

    @yousufctec - so Switch_OnToggled won't be executed until after the page is visible on screen?
    What causes it to be delayed until then?
    What testing have you done to verify it isn't called earlier?

  • JesseMockJesseMock USUniversity ✭✭

    I agree this is still a problem. If I load my ListView in OnAppearing, it does not fill up the screen vertically even with VeritcalOptions="FillAndExpand". It cuts off all the content in the ListView. But if I put a button on the page and load the ListView after clicking the button, the ListView takes up the entire screen as expected. OnAppearing is happening before the page is fully loaded. Need another way.

  • JohnHardmanJohnHardman GBUniversity admin

    @JesseMock said:
    OnAppearing is happening before the page is fully loaded. Need another way.

    It's a horrible hack, as it uses polling, uses a property marked as for Xamarin internal use only, and introduces a race condition, but in some circumstances the IsInNativeLayout property can help. If you search the XF source code, you'll see it in use there.

                    int cycle = 0;
                    while ((!view.IsInNativeLayout) && (++cycle <= maxCycles))
                    {
                        await Task.Delay(TimeSpan.FromMilliseconds(millisecondDelay));
                    }
    
  • @JasonMadden said:
    I ended up having to solve this problem rather nastily

    In the onappearing I wrapped everything in an async call and waited a few hundred ms for the page to get rendered.

    await WaitAndExecute(1000, () =>
    {
    // refresh code
    }

    protected async Task WaitAndExecute(int milisec, Action actionToExecute)
    {
    await Task.Delay(milisec);
    actionToExecute();
    }

    Worked for me . Thanks :smile:

  • udayuday Member

    @JasonMadden said:
    I ended up having to solve this problem rather nastily

    In the onappearing I wrapped everything in an async call and waited a few hundred ms for the page to get rendered.

    await WaitAndExecute(1000, () =>
    {
    // refresh code
    }

    protected async Task WaitAndExecute(int milisec, Action actionToExecute)
    {
    await Task.Delay(milisec);
    actionToExecute();
    }

    works for me

  • @yousufctec said:
    OnAppearing will be executed before the screen comes, when you want an Loaded event that needs to be executed right after the screen comes, there is a workaround.

    1. Create an property in viewmodel like below.

          private bool _toggleTemp;
          public bool ToggleTemp
          {
              get => _toggleTemp;
              set => SetProperty(ref _toggleTemp, value);
          }
      
    2. Add the following line to the last line of the constructor.

      LoadingVm.ToggleTemp = true;

    3. Add an Switch to your screen and make IsVisible to false as below.

      <Switch IsToggled="{Binding ToggleTemp}" Toggled="Switch_OnToggled" IsVisible="False" />

    4. Now you can write the code that you want to write in Page Loaded in Switch_OnToggled.

          private async void Switch_OnToggled(object sender, ToggledEventArgs e)
          { 
            /* Your code goes here... */ 
          }
      

    Thanks!

    Regards,
    Yousuf.

    Hi there I don't quite understand how yout method works do you have an example so noob learners we can see the code? thanks

  • yousufctecyousufctec USMember ✭✭✭

    @SteveShaw.5557 said:
    @yousufctec - so Switch_OnToggled won't be executed until after the page is visible on screen?
    What causes it to be delayed until then?
    What testing have you done to verify it isn't called earlier?

    @SteveShaw.5557 Because this is how I made it work in my application. You're basically calling the code once after all your other code has been executed. Page visibility can never be known you will not be able to whether it rendered or not. It's simple that I'm just trying to call that piece of code once after I do all other population.

    Regards,
    Yousuf.

  • yousufctecyousufctec USMember ✭✭✭

    @jointothedarkside said:

    @yousufctec said:
    OnAppearing will be executed before the screen comes, when you want an Loaded event that needs to be executed right after the screen comes, there is a workaround.

    1. Create an property in viewmodel like below.

          private bool _toggleTemp;
          public bool ToggleTemp
          {
              get => _toggleTemp;
              set => SetProperty(ref _toggleTemp, value);
          }
      
    2. Add the following line to the last line of the constructor.

      LoadingVm.ToggleTemp = true;

    3. Add an Switch to your screen and make IsVisible to false as below.

      <Switch IsToggled="{Binding ToggleTemp}" Toggled="Switch_OnToggled" IsVisible="False" />

    4. Now you can write the code that you want to write in Page Loaded in Switch_OnToggled.

          private async void Switch_OnToggled(object sender, ToggledEventArgs e)
          { 
              /* Your code goes here... */ 
          }
      

    Thanks!

    Regards,
    Yousuf.

    Hi there I don't quite understand how yout method works do you have an example so noob learners we can see the code? thanks

    @jointothedarkside It will create a switch in the view and bind the ToggleTemp property to it. And in the constructor once after I'm done with all other population with UI or whatever, I'm changing this property value. Which will trigger the Switch_OnToggled event where you can place your code that needs to be executed after everything. May be even you can sleep the thread there for few seconds to be very sure that everything is loaded.

    Sorry, I don't have any sample code as that project is over quite long back.

    Regards,
    Yousuf.

  • LeloLelo Member ✭✭✭
    edited November 2019

    To get an event occurring later than OnAppearing i'ts possible to hook up to SizeChanged of a control in the page. Hook it it up in the constructor:

    cameraView.SizeChanged += (object sender, EventArgs e) =>
    {
        Console.WriteLine("size changed");
        cameraView.Start();
    };
    

    I previously had to use Task.Run and Task.Delay(miliseconds) but it was not needed after using SizeChanged event.

Sign In or Register to comment.