Save/Load GridView layout using SettingsService
At the recommendation of @svick, I decided to serialize the objects themselves. Rather than creating a custom object/stub, I just added [JsonIgnore] attribute to the properties that I did not want to serialize.

Here is the new code for saving the layout:

private void MainGridView_OnDrop(object sender, DragEventArgs e)
{
    var grid = e.OriginalSource as GridView;
    var items = grid?.ItemsSource as ObservableCollection&lt;AppPage&gt;;

    if (items != null)
    {
        foreach (var p in items)
        {
            p.PageIndex = items.IndexOf(p);
        }
        // serialize items
        var layout = JsonConvert.SerializeObject(items);
        _settings.MainMenuLayout = layout;
    }
}


Then I was able to simplify reading the layout from settings like so:

var layout = _settings.MainMenuLayout;
if (!string.IsNullOrEmpty(layout))
{
    var pageStubs = JsonConvert.DeserializeObject&lt;ObservableCollection&lt;AppPage&gt;&gt;(layout);

    foreach (var p in pageStubs)
    {
        var cur = pages.First(page =&gt; page.PageName == p.PageName);
        cur.PageIndex = p.PageIndex;
    }
    // sort based on index
    AppPages = new ObservableCollection&lt;AppPage&gt;(pages.OrderBy(p =&gt; p.PageIndex));
}
else
{
    AppPages = pages;
}


The only properties of AppPage that get serialized are the PageName and PageIndex, which are the only properties used for this process.

Any further improvements are always welcome!