When designing a Windows 8 app, you need a way to preserve the state of various items as you navigate from page to page. Windows allows this using the pageState dictionary - a dictionary that can contain any serializable object. If you're a web programmer, you can think of this as similar to using a session variable. Today I'll add this to the cascading ListBoxes shown earlier. You can download the code for that project at ListBoxDrillDown.zip.
First, we'll add a navigation button to the page. Put the
pnlMain StackPanel and the new button inside another
StackPanel, like this:
<StackPanel x:Name="pnlContainer" Grid.Row="2" Orientation="Vertical">
<Button x:Name="btnSearch" Content="Show" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="40,0,0,0" Click="btnSearch_Click"/>
<StackPanel x:Name="pnlMain" HorizontalAlignment="Left" Margin="20,10" VerticalAlignment="Top" Orientation="Horizontal"/>
Then add the
private void btnSearch_Click(object sender, RoutedEventArgs e)
if (_categoryID > 0)
LandingPage isn't actually part of the project yet, so go ahead and add it. Just add a Basic Page called
LandingPage.xaml to the project. It won't be used for anything other than the back button control.
Now, if you run the app, after you select at least one item in the first
ListBox you'll be able to click the button to navigate to the second page. When you click the back button, however, you return with only the first ListBox showing and nothing selected; anything that you had drilled down into will have to be reselected. Let's fix that.
SaveState method and add the following code:
List<int> list = new List<int>();
for (int x = 1; x <= _listBoxCount; x++)
ListBox lb = (ListBox)pnlMain.Children[x - 1];
if (lb.SelectedValue != null)
pageState["listBoxSettings"] = list;
Here I'm simply adding all the
SelectedIndex values to a List and saving it to
Now, to retrieve this List once we've navigated away and back to the page. Add a variable to the class:
private List<int> _selectionList = null;
Then add the following code to the
if (pageState != null && pageState.ContainsKey("listBoxSettings"))
_selectionList = (List<int>)pageState["listBoxSettings"];
Here I check to see if the "
listBoxSettings" key is populated (since this same method will be called the first time the page is loaded, it could be empty...), and then assign it to the variable. Notice that the
_categoryID) statement has moved from the
ChooseCategory() method; I want to make sure it's called after
pageState has been retrieved.
Next, add this code to the
AddListBox() method, right before the
ListBox is added to the
if (_selectionList != null && _selectionList.Count >= _listBoxCount)
listBox1.SelectedIndex = _selectionList[_listBoxCount - 1];
When a new
ListBox is created, I'm checking to see if the
ListBox in that position has a selection in the List variable. If so, set the
SelectionChanged event will fire again, and the code will check again to see if another selection has already been made.
At this point you should be able to test the app and verify that everything works. Fire it up, drill all the way down in the ListBoxes, go to the next page, and return. You should see all your selections preserved. There's one last thing that we have to do, though. Try this: Drill down as far as you can go into a category, go to the next page and return. Now, at the top level, select a different category. You'll see the app automatically drill down again! This is because the List is still held in the
_selectionList variable, and the app doesn't know the difference between a human clicking and the automatic process that happens when we return to the page. The easy way to fix this is to simply clear the List when clicking in a ListBox to the left of another ListBox (i.e. a higher level). Add this code to the
ComboBox_SelectionChanged event handler:
Keep in mind, these settings are only going to be preserved while you're using the app - if it's suspended or terminated, they're not available. If you need to preserve them after the app is terminated, you can use the
When you hit the back button, you'll probably notice a delay as each new ListBox appears. This is because it's fetching the contents from the eBay API, just as it did the first time you selected it. If you don't like this, then you could simply store the contents of each ListBox in
pageState and repopulate.
You can download the code for this at SaveStateDemo.zip.