Существует ли типобезопасный способ навигации между экранами в Windows Phone?

StackOverflow https://stackoverflow.com//questions/20004086

Вопрос

Я ищу способ навигации между экранами в моем приложении.По сути, то, что я видел до сих пор, состоит из передачи строкового URI в NavigationService вместе с параметрами строки запроса.

NavigationService.Navigate(new Uri("/MainPage.xaml?selectedItem=" +bookName.Id, UriKind.Relative));

Хотя мне это не очень нравится, в конечном счете, потому что для этого нужны волшебные струны, а они могут привести к проблемам в будущем.

В идеале я бы просто создал экземпляр класса, к которому хочу перейти, передав параметры в качестве аргументов конструктору.Это возможно?Если да, то как?

Это было полезно?

Решение

Хотя фактическая навигация должна в конечном итоге использовать строки, вы можете создавать или использовать обертку, которая является безопасным.

Я бы предложил смотреть на caliburn micro Даже если вы только использовали его только для безопасной навигации типа. Вот фрагмент Из учебного пособия по использованию его в WP8 :

Навигация Услуги, который поставляется с Toolkit, поддерживает модуль RESIONAL FORE подход: вместо того, чтобы объявить, что является URL страницы, где мы хотим взять пользователь (это стандартный подход), мы Объявите, что представляет собой модел, который мы хотим отображать. Сервис позаботится о создании правильного URL и отображает представление, связанное с моделью представления .

В качестве альтернативы вы можете посмотреть на Windows Phone MVC который также имеет некоторую безопасную навигацию типа. Вы даже можете просто иметь возможность вытащить код навигации, используемый самостоятельно, поскольку он лицензирован под MS-PL < / a>.

Другие советы

В принципе нет, не встроено.К сожалению, сложные параметры, такие как экземпляры IRepository, недоступны средствам навигации в Silverlight;Для их обработки я обычно использую какую-то форму IoC-контейнера.Более простые параметры POCO легко сериализуются в строку, но для этого по-прежнему требуются магические строки и ручной анализ строки запроса.

Однако вы можете легко создать что-то типобезопасное самостоятельно.Например, вот мой подход.

Для данных параметров у меня есть класс, который я называю «Дополнительно», который обертывает Dictionary<string, object> с такими методами, как GetBool(string), GetInt32(string), и т. д., и имеет статический фабричный метод CreateFromUri(Uri);этого достаточно для моих целей.

Я использую это в сочетании с типобезопасной навигацией.Мне очень нравится шаблон MVVM, и на каждой моей странице есть ViewModel, инкапсулирующая почти всю логику.Отношения страницы и ViewModel «один к одному» делают последнюю идеальным ключом навигации.Это, в сочетании с атрибутами и отражением, дает нам простое решение:

public class NavigationTargetAttribute : Attribute
{
    private readonly Type target;

    public ViewModelBase Target
    {
        get { return target; }
    }

    public NavigationTargetAttribute(Type target)
    {
        this.target = target;
    }
}

Поместите по одному из них на каждую страницу с соответствующим типом ViewModel.

[NavigationTarget(typeof(LoginViewModel))]
public class LoginPage : PhoneApplicationPage
{ ... }

Затем в одноэлементном классе в стиле NavigationManager вы можете сделать:

GetType().Assembly
    .GetTypes()
    .Select(t => new { Type = t, Attr = t.GetCustomAttributes(false).FirstOrDefault(attr => attr is NavigationTargetAttribute) })
    .Where(t => t.Attr != null);

Таким образом, в вашем приложении есть коллекция всех типов навигации.После этого не составит большого труда поместить их, например, в словарь.Если вы следуете соглашению о том, где вы размещаете свои страницы, вы можете (например) довольно легко переводить между типом и Uri...например, new Uri("/Pages/" + myPageType.Name + ".xaml", UriKind.Relative).Осталось добавить поддержку параметров запроса.Наконец, вы получите метод, например:

public void Navigate(Type target, Extras extras)
{
    Type pageType;
    if (navigationTargets.TryGetValue(target, out pageType))
    {
        var uri = CreateUri(pageType, extras);
        navigationService.NavigateTo(uri);
    }

    // error handling here
}

Наконец, на странице OnNavigatedTo метод, я делаю что-то вроде:

var extras = Extras.CreateFromUri(e.Uri);
((ViewModelBase) DataContext).OnNavigatedTo(extras);

Это, наконец, создает видимость строго типизированной навигации.Это простой подход;Мне пришло в голову, что это можно улучшить, добавив необходимые параметры в атрибут навигации и проверив их во время навигации.Он также не поддерживает более сложные типы навигации, где значение аргументов навигации будет определять конечный пункт назначения.Тем не менее, это соответствует моему варианту использования на 90% — возможно, это подойдет и вам.

Здесь определенно опущены некоторые детали, например, как именно получить экземпляр NavigationService - Я могу подготовить более полный образец позже сегодня вечером, но для начала этого должно быть достаточно.

Вы можете использовать PhoneApplicationService.State

Это генеракодицетагкод

Dictionary<String,Object> обычно используется в надгробинге для хранения текущего состояния приложения. Однако его можно использовать для удобства передачи данных между страницами.

MSDN Документация

Приложения Windows Phone деактивированы, когда пользователь навигается к другое приложение. Когда пользователь возвращается к приложению, Использование кнопки назад или заполните задачу Launcher или Chooser, Применение активируется. Приложение может хранить преходящие Состояние приложения в словаре государства в обработчике для Деактивированное событие. В обработчике активированного события приложение может Используйте значения, хранящиеся в словаре штата, к преходящему приложению состояние.

в основном то, что вы сделаете, это

PhoneApplicationService.State.add(selectedName,yourobjectInstance);
NavigationService.Navigate((new Uri("/MainPage.xaml?selectedItem="+selectedName,UriKind.Relative));
.

Затем в вашем навигации тоже метод вы можете получить его

YourObject yourObjectInstance;
var yourObj = PhoneApplicationService.State["yourObjectName"];
yourObjectInstance = yourObj is YourObject ? (yourObj as YourObject) : null;
.

Вот более независимый внешний вид, как использовать эту функцию

WPF поддерживает переход к уже созданному объекту, но в WP8 этого нет. Navigate перегрузка.

Если вы не хотите жестко закодировать URI-страницы XAML, вы можете использовать следующую (немного грязную) вспомогательную функцию, чтобы получить URI ресурса .xaml некоторого класса.

static Uri GetComponentUri<T>() where T : DependencyObject, new() {
    return BaseUriHelper.GetBaseUri(new T());
}

Затем вы можете изменить этот URL-адрес и перейти к нему:

var baseUri = GetComponentUri<SomePage>(); //Uri="pack://application:,,,/MyProject;component/MainWindow.xaml"
var pageUri = new UriBuilder(baseUri) { Query = "selectedItem=" + bookName.Id };
NavigationService.Navigate(pageUri);

Наше решение, которое работает просто хорошо:

1. <Сильные> не используйте строки запросов на странице URI, это просто полностью снова MVVM, где представление должно просто отображать вещи, но фактическая логика для загрузки и выбора элементов в ViewModel.


2. Создание класс с именами страниц Const И всякий раз, когда вы хотите навигаться, просто используйте это:

public static class P
{
    public const string ArticlePage = "/Pages/ArticlePage.xaml";
    public const string OnlineSectionPage = "/Pages/OnlineSectionPage.xaml";
    public const string GalleryPage = "/Pages/GalleryPage.xaml";
    ...
}

// in our viewModel
NavigationService.Navigate(P.ArticlePage);

// In navigation service
public void Navigate(string pagePath)
{
    if (EnsureMainFrame())
    {
        mainFrame.Navigate(new Uri(pagePath, UriKind.RelativeOrAbsolute));
    }
}
.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top