Save/Load GridView layout using SettingsService I am able to save my GridView layout by storing a string representation of the items in the ItemsSource. I then load that string representation from the SettingsService and set the index of the items accordingly.

The layout is changed by drag/dropping items in the GridView. Here is the code-behind:

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)
    {
        var layout = "";

        // save settings
        foreach (var p in items)
        {
            p.PageIndex = items.IndexOf(p);
            // serialize pagename and pageindex
            layout += $"{p.PageName},{p.PageIndex}|";
        }
        _settings.MainMenuLayout = layout;
    }
}


Then when I load the application, I check for the MainMenuLayout setting and parse it out like so:

public void LoadMainMenu()
{
    var pages = new ObservableCollection&lt;AppPage&gt;
    {
        new AppPage("Payees", "ms-appx:///Assets/payee-180.png", typeof(Views.PayeesPage)),
        new AppPage("Bills", "ms-appx:///Assets/invoice-180.png", typeof(Views.InvoicesPage)),
        new AppPage("Payments", "ms-appx:///Assets/envelope-180.png", typeof(Views.PaymentsPage)),
        new AppPage("Checkbook", "ms-appx:///Assets/checkbook-180.png", typeof(Views.CheckbookPage)),
        new AppPage("Receipts", "ms-appx:///Assets/receipt-180.png", null),
        new AppPage("Categories", "ms-appx:///Assets/categories-180.png", typeof(Views.CategoriesPage)),
        new AppPage("Accounts", "ms-appx:///Assets/bank-180.png", typeof(Views.AccountsPage)),
        new AppPage("Budget", "ms-appx:///Assets/budget-180.png", null),
        new AppPage("Contacts", "ms-appx:///Assets/contacts-180.png", typeof(Views.ContactsPage)),
        new AppPage("Reports", "ms-appx:///Assets/charts-180.png", typeof(Views.ReportsPage)),
        new AppPage("Test", "ms-appx:///Assets/beaker-180.png", typeof(Views.TestPage)),
    };

    var layout = _settings.MainMenuLayout;
    if (!string.IsNullOrEmpty(layout))
    {
        // split on |
        var pagesSplit = layout.Split('|');

        foreach (var p in pagesSplit)
        {
            // then split on ,
            if (p.Contains(","))
            {
                var pageInfo = p.Split(',');
                var cur = pages.First(page =&gt; page.PageName == pageInfo[0]);
                cur.PageIndex = int.Parse(pageInfo[1]);
            }
        }
    }

    // sort based on index
    AppPages = new ObservableCollection&lt;AppPage&gt;(pages.OrderBy(p =&gt; p.PageIndex));
}


Is there a better way to serialize/deserialize the layout? I don't want to store the entire AppPage objects for every item, as there are additional properties that are unrelated to the layout.
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!