Friday, August 25, 2017

Visual Studio grinds to a halt when upgrading a netcore website

This cost me the better part of a day to investigate since I tried everything else but recreating the project.

How I messed up


I had an ASP.NET Core WebApi project that I simply upgraded to .NET Core 2.0 by changing a line in the configuration from

<TargetFramework>netcoreapp1.1</TargetFramework>

to

<TargetFramework>netcoreapp2.0</TargetFramework>

What happened


Visual Studio (2017) pretty much hanged and/or performed extremely slowly. When loading the solution VS took about 2 minutes to load the web project.

How did I resolve it


Simply recreate the web project (with 2.0 selected) and import all files to it again. Pay a little notice to the startup.cs file. You might find some small changes there so don't just overwrite it.

Thursday, August 17, 2017

Popped Pages in Xamarin Forms

This post is long overdue. About a year ago (July 2016) I managed to get some code into Xamarin Forms Core. This code change was necessary in order to make TinyPubSub work correctly.

TLDR;


If you call Navigation.PopToRoot() in Xamarin Forms and want to know all the pages being popped you need to cast the NavigationEventArgs to a PoppedToRootEventArgs.

    var page = new NavigationPage();
     page.PoppedToRoot += (object sender, NavigationEventArgs e) => 
     {
         // Typecast the args
         var args = e as PoppedToRootEventArgs;

         // Get the pages
         var poppedPages = args.PoppedPages;
     };

Long story


There was quite a long discussion before I got this change approved by Jason Smith and the Forms team. The most pressing issue was that we could not break the signature of the PoppedToRoot event so we ended up creating a new event args class (called PoppedToRootEventArgs) and simply passed that one in. 

This of course hides the PoppedToRootEventArgs from plain sight so you need to know what you are looking for.

The internal workings of PopToRoot (the important parts) looks like this:

    var args = new NavigationRequestedEventArgs(RootPage, animated);

     EventHandler<NavigationRequestedEventArgs> requestPopToRoot = PopToRootRequested;
     if (requestPopToRoot != null)
     {
         requestPopToRoot(this, args);

         if (args.Task != null)
             await args.Task;
     }

    PoppedToRoot?.Invoke(thisnew PoppedToRootEventArgs(RootPage, childrenToRemove.OfType<Page>().ToList()));
        

The last line is the event (PoppedToRoot) and as you see we pass in PoppedToRootEventArgs as the args.

The PoppedToRootEventArgs is simply a class inheriting from NavigationEventArgs that adds PoppedPages as a IEnumerable to the class.

    public class PoppedToRootEventArgs : NavigationEventArgs
    {
        public PoppedToRootEventArgs(Page page, IEnumerable<Page> poppedPages) : base(page)
        {
            if (poppedPages == null)
                throw new ArgumentNullException(nameof(poppedPages));

            PoppedPages = poppedPages;
        }

        public IEnumerable<Page> PoppedPages { getprivate set; }
    }