Windows Phone 8 ListPicker использует ContextMenu для перехода, но при возврате страница совершенно пуста.

Мы используем элемент управления Toolbox:ListPicker для отображения ObservableCollection. Теперь мы хотим, чтобы пользователи могли по выбору перемещаться по ListPicker к редактору объектов в ObservableCollection.

Мы добавили ContextMenu в ItemTemplate, позволяющую пользователю переходить к редактору. Пользователю предоставляется контекстное меню после долгого нажатия на элемент. Если пользователь нажимает на пункт меню, ему предоставляется страница редактора. После того, как пользователь нажимает кнопку «Назад» в редакторе, он возвращается на совершенно пустую страницу — отображается только системный трей. Если пользователь снова нажимает кнопку «Назад», ListPicker ненадолго появляется перед началом и заменяется страницей, на которой размещается экземпляр ListPicker.

В чем смысл пустой страницы и есть ли способ от нее избавиться?


Вот XAML для экземпляра ListPicker.

<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>

Вот код обработки контекстного меню.

    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;
        }
    }

person Gyle Iverson    schedule 22.06.2014    source источник


Ответы (1)


Если нет необходимости возвращаться в полноэкранный режим средства выбора списка, просто переопределите нажатие клавиши «Назад» на странице сведений и вернитесь на страницу, на которой размещено средство выбора списка.

Страница сведений:

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

}

ИЗМЕНИТЬ

Боюсь, это невозможно с помощью списка. Если на то пошло, вам придется написать отдельную страницу, имитирующую полноэкранный режим списка. Если вы изучите элемент управления в наборе инструментов, вы заметите, что он внутренне переходит на страницу ListPickerPage.xaml. Сохранение состояния и присвоение DataContext этой странице выполняется элементом управления.

На странице сведений, когда вы нажимаете аппаратную кнопку «Назад», фрейм выталкивает страницу, расположенную поверх стека истории навигации, то есть ListPickerPage.xaml. В этот момент на страницу не передается DataContext, поэтому вы видите пустую страницу.

person Pantelis    schedule 22.06.2014
comment
Спасибо @Pantelis. Мы бы предпочли, чтобы редактор возвращался в полноэкранный режим ListPicker, тем самым предоставляя пользователю возможность редактировать/просматривать другие элементы, а не возвращаться на страницу, на которой размещен ListPicker. Предлагаемый UX может быть неудобным. - person Gyle Iverson; 23.06.2014
comment
Спасибо за анализ ListPickerPage.xaml, @Pantelis. Почему бы ListPickerPage.xaml не сохранить состояние, чтобы восстановить DataContext. Это похоже на ошибку. Это позор. - person Gyle Iverson; 24.06.2014
comment
Поскольку состояние предоставляется ListPickerPage, когда вы нажимаете на элемент управления. При нажатии вы переходите на отдельную страницу. То, что происходит, является нормальным поведением, если вы знаете о системе навигации на платформе. Как я уже упоминал, нажатие клавиши «Назад» открывает и загружает в кадр верхнюю страницу из стека истории. Кроме того, элемент управления был разработан как замена поля со списком, присутствующего в других фреймворках, то есть выбора одного элемента. По этой причине функциональность, которой вы хотите достичь, может не пройти сертификацию. - person Pantelis; 24.06.2014