2

We are using a Toolbox:ListPicker control to display an ObservableCollection. We now want to let users optionally navigate through the ListPicker to an editor for the objects in the ObservableCollection.

We added a ContextMenu to the ItemTemplate allowing the user to Navigate to the editor. The user is presented with the context menu after they long-tap on an item. If the user taps on the menu item they are presented with the editor page. After the user presses the back button in the editor, they are returned to a completely blank page - only the system tray is shown. If the user presses the back button again, the ListPicker briefly appears before begin replaced by the page hosting the ListPicker instance.

What is the point of the blank page and is there a way to get rid of it?


Here is the XAML for the ListPicker instance.

<toolkit:ListPicker 
    x:Name="listPicker_Generators" 
    Margin="12,-6,0,12" 
    ExpansionMode="FullScreenOnly" 
    HorizontalAlignment="Left" 
    Width="430" 
    Height="Auto" 
    VerticalAlignment="Top" 
    FullModeHeader="{Binding Source={StaticResource LocalizedStrings}, Path=LocalizedResources.label_AccountEditor_Generator}" 
    >
    <toolkit:ListPicker.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
    </toolkit:ListPicker.ItemTemplate>
    <toolkit:ListPicker.FullModeItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Vertical">
                <TextBlock Text="{Binding Name}" FontSize="36" />
                <TextBlock Text="{Binding Notes}"  Margin="0,0,0,12" FontFamily="Segoe WP" FontSize="{StaticResource PhoneFontSizeSmall}" />
                <toolkit:ContextMenuService.ContextMenu>
                    <toolkit:ContextMenu 
                        Visibility="{Binding Visibility}"
                        Closed="ContextMenu_Closed" 
                        Opened="ContextMenu_Opened">
                        <toolkit:MenuItem 
                            Name="menuItem_Edit" 
                            Header="{Binding Source={StaticResource LocalizedStrings}, Path=LocalizedResources.label_AccountEditor_EditGenerator}" 
                            Click="menuItem_Edit_Click" />
                    </toolkit:ContextMenu>
                </toolkit:ContextMenuService.ContextMenu>
            </StackPanel>
        </DataTemplate>
    </toolkit:ListPicker.FullModeItemTemplate>
</toolkit:ListPicker>

Here is the code behind for the context menu handling.

    private void menuItem_Edit_Click(object sender, RoutedEventArgs e)
    {
        AccountViewModel.GeneratorChoice item = ((AccountViewModel.GeneratorChoice)((sender as FrameworkElement).DataContext));

        if (item != null)
        {
            AccountViewModel vm = DataContext as AccountViewModel;
            vm.HoldingSelectedGeneratorIndex = listPicker_Generators.SelectedIndex;

            NavigationService.Navigate(new Uri("/Views/GeneratorEditor.xaml?id=" + item.Id.ToString(), UriKind.Relative));

            // force the selection to change so we get redrawn when we come back
            if (listPicker_Generators.SelectedIndex > 0)
                listPicker_Generators.SelectedIndex--;
            else
                listPicker_Generators.SelectedIndex++;
        }
    }

    private void ContextMenu_Closed(object sender, RoutedEventArgs e)
    {
        AccountViewModel vm = DataContext as AccountViewModel;
        vm.ContextMenuOpen = false;
    }

    private void ContextMenu_Opened(object sender, RoutedEventArgs e)
    {
        // a work-around from http://stackoverflow.com/questions/15181441/windows-phone-toolkit-context-menu-items-have-wrong-object-bound-to-them-when-an
        ContextMenu contextMenu = (sender as ContextMenu);

        FrameworkElement owner = (contextMenu.Owner as FrameworkElement);
        if (owner.DataContext != contextMenu.DataContext)
            contextMenu.DataContext = owner.DataContext;

        AccountViewModel.GeneratorChoice item = contextMenu.DataContext as AccountViewModel.GeneratorChoice;

        if (item.Id.Value != 0)
        {
            bool factorySupplied = item.FactorySupplied == null ? false : true;

            if (factorySupplied)
            {
                contextMenu.Items.OfType<MenuItem>().First(m => (string)m.Name == "menuItem_Edit").Header = AppResources.label_AccountEditor_ViewGenerator;
            }

            AccountViewModel vm = DataContext as AccountViewModel;
            vm.ContextMenuOpen = true;
        }
    }
Gyle Iverson
  • 661
  • 1
  • 9
  • 17

1 Answers1

0

If there's no need to navigate back to the FullScreen of the listpicker, just override the back key press on the details page and navigate back to the page hosting the listpicker.

Details Page:

protected override void OnBackKeyPress(CancelEventArgs e)
{
    base.OnBackKeyPress(e);
    e.Cancel = true;
    NavigationService.Navigate(
        new Uri("ListPickerView.xaml", UriKind.Relative));
}

}

EDIT

I'm afraid that's not possible by using the listpicker. You will have to write a separate page simulating the listpicker fullscreen mode, for that matter. If you examine the control in the toolkit, you'll notice that it internally navigates to a ListPickerPage.xaml page. The state preservation and DataContext assignment to that page is done by the control.

On details page, when you press the hardware back button, the Frame pops the page sitting οn top of the navigation history stack, that is the ListPickerPage.xaml. At that moment, the page has no DataContext passed to it, this is why you see a blank page.

Pantelis
  • 2,060
  • 3
  • 25
  • 40
  • Thanks @Pantelis. We'd prefer the editor to return to the FullScreen of the ListPicker, thereby providing the user the opportunity to edit/view other items, rather than be kicked back to the page hosting the ListPicker. The UX suggested may be awkward. – Gyle Iverson Jun 23 '14 at 03:35
  • Thanks for that analysis of the ListPickerPage.xaml, @Pantelis. Why wouldn't ListPickerPage.xaml keep state so it would reestablish the DataContext. This sounds like a bug. It's a shame. – Gyle Iverson Jun 23 '14 at 20:44
  • Because the state is provided to the ListPickerPage when you tap on the control. When tapped, you navigate to a separate page. What happens is normal behavior if you're aware of the navigation system on the platform. Like I mentioned, the back key press, pops and loads to the frame the top page from the history stack. Also the control was designed as a replacement for the combobox present in other frameworks, that is single item selection. The functionality you want to achieve might fail certification for this reason. – Pantelis Jun 23 '14 at 21:49