public int buildPortraitView()
        {
            int result = 1;

            // all my elements are already members...
            if (portraitView == null)
            {
                portraitView = new Grid {
                    ColumnSpacing = 1, RowSpacing = 1
                };
                //for (int i = 0; i < 16; i++) {
                //portraitView.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
                //}
                portraitView.RowDefinitions.Add(new RowDefinition {
                    Height = new GridLength(16, GridUnitType.Star)
                });
            }

            // ok. How do I build the rows in leaderboards
            if ((listOfLeaderboards != null) && (listOfLeaderboards.Count > 0))
            {
                foreach (KeyValuePair <CategoryJSON, IList <LeaderboardJSON> > kvpCatBoard in listOfLeaderboards)
                {
                    LeaderboardElement le = buildLeaderboardElement(kvpCatBoard.Key, kvpCatBoard.Value);
                    if (le != null)
                    {
                        leaderboards.Add(le);
                    }
                }
                // bleh. this returns a new, not observablecollection object.
                //leaderboards.OrderByDescending(a => a.categoryId);
                GlobalSingletonHelpers.SortAndReverse(leaderboards);
                //printOrder();
            }

            int deviceDependentRowHeight = 450;

            if (Device.Idiom == TargetIdiom.Tablet)
            {
                deviceDependentRowHeight = (90 + (3 * 270));
            }
            // want to fill a listview instead of a scroller holding a stack.
            myListView = new ListView {
                RowHeight = deviceDependentRowHeight, ItemsSource = leaderboards, ItemTemplate = myDataTemplate,
            };

            portraitView.Children.Add(myListView, 0, 0);
            Grid.SetRowSpan(myListView, 16);

            //Debug.WriteLine("DHB:LeaderboardPage:buildPortraitView final mem status:" + PlatformSpecificCalls.GetMemoryStatus());
            Debug.WriteLine("DHB:LeaderboardPage:buildPortraitView end");
            return(result);
        }
        protected LeaderboardElement buildLeaderboardElement(CategoryJSON category, IList <LeaderboardJSON> leaderboard)
        {
            LeaderboardElement le      = null;
            List <SKBitmap>    bitmaps = new List <SKBitmap>();

            if (leaderboard.Count > 0)    // only build leaderboards with images.
            {
                foreach (LeaderboardJSON leader in leaderboard)
                {
                    SKBitmap bitmap = GlobalSingletonHelpers.SKBitmapFromBytes(leader.imgStr);
                    if (bitmap != null)
                    {
                        bitmaps.Add(bitmap);
                    }
                }
                le = new LeaderboardElement(category.description, category.categoryId, bitmaps, leaderboard);
#if DEBUG
                le.title = le.title + " - " + le.categoryId;
#endif
            }
            return(le);
        }
        protected async virtual void OnRequestLeaderboard(object sender, EventArgs e)
        {
            // the current category command does not send back a category in leaderboard state.
            // for now, the system is only going to support Yesterday's and Today's leaderboard.

            Debug.WriteLine("DHB:LeaderboardPage:OnRequestLeaderboard start");
            long   loadCategory = ((RequestLeaderboardEventArgs)e).Category.categoryId;
            string categoryName = ((RequestLeaderboardEventArgs)e).Category.description;

            string result = await requestLeaderboardAsync(loadCategory);

            if (result.Equals(LOAD_FAILURE))
            {
                //leaderboardLabelP.Text = "Connection failed. Please check connection";
                while (result.Equals(LOAD_FAILURE))
                {
                    await Task.Delay(3000);

                    Debug.WriteLine("DHB:LeaderboardPage:OnRequestLeaderboard sending re-request.");
                    result = await requestLeaderboardAsync(loadCategory);
                }
            }
            // fix labels, connection is back...
            //leaderboardLabelP.Text = "BEST OF: ";

            // process successful leaderboard result string
            IList <LeaderboardJSON> newLeaderBoard = JsonHelper.DeserializeToList <LeaderboardJSON>(result);

            // may have been added already. this approach throws an exception if key exists
            //listOfLeaderboards.Add(((RequestLeaderboardEventArgs)e).Category, newLeaderBoard);
            // this one resets the value:
            CategoryJSON category = (((RequestLeaderboardEventArgs)e).Category);

            listOfLeaderboards[category]          = newLeaderBoard;
            leaderboardUpdateTimestamps[category] = DateTime.Now;

            // create a new leaderrow and insert or replace.
            LeaderboardElement le = buildLeaderboardElement(category, newLeaderBoard);

            if (le != null)
            {
                // actually need to determine where to put this, and whether to remove another leaderboard...
                // and can this happen in an async func?
                int leaderboardStatus = leaderboardAlreadyDrawn(category.categoryId);
                Device.BeginInvokeOnMainThread(() =>
                {
                    if (leaderboardStatus == -1)
                    {
                        leaderboards.Add(le);
                        //leaderboards.OrderByDescending(a => a.categoryId);
                        GlobalSingletonHelpers.SortAndReverse(leaderboards);
                        //printOrder();
                    }
                    else
                    {
                        leaderboards.RemoveAt(leaderboardStatus);
                        leaderboards.Insert(leaderboardStatus, le);
                    }
                });
            }

            //drawLeaderImages(((RequestLeaderboardEventArgs)e).Category);  // this happens async... so build afterwards is meaningless...
            // I do need to update the ui now...
            // this should fix with the switch to listview...
            //buildUI();

            Debug.WriteLine("DHB:LeaderboardPage:OnRequestLeaderboard UI Change");
#if DEBUG
            // will be null if everything went ok.
            if (JsonHelper.InvalidJsonElements != null)
            {
                // ignore this error. do we have a debug compiler directive??
                throw new Exception("Invalid leaderboard parse from server in Leaderboard get.");
            }
#endif // DEBUG

            Debug.WriteLine("DHB:LeaderboardPage:OnRequestLeaderboard end");
        }