Pergunta

Eu estou procurando uma forma de navegar entre as telas em meu aplicativo.Basicamente, o que eu vi até agora consiste em passar uma string URI para o NavigationService, completo com parâmetros de cadeia de consulta., exemplo:

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

Eu realmente não estou interessado neste embora, em última análise, porque requer cordas mágicas, e podem levar a problemas na estrada.

Idealmente, eu gostaria de criar uma instância da classe eu quero navegar, passando os parâmetros como argumentos para o construtor.Isso é possível?Se sim, como?

Foi útil?

Solução

Enquanto a navegação real terá que usar seqüências de caracteres, eventualmente, você pode criar ou usar um invólucro que é tipo de seguro.

Gostaria de sugerir olhando para Caliburn Micro mesmo se você só usou-o para o tipo de navegação segura.Aqui é um trecho a partir de um tutorial sobre como usar ele no WP8:

O NavigationService que vem com o kit de ferramentas oferece suporte a uma modelo de modo de exibição primeira abordagem:em vez de declarar que é a URL da página onde queremos levar o usuário (que é o padrão de abordagem), declaramos que é o ViewModel que queremos exibir. O serviço terá o cuidado de criar a URL correta e exibir o modo de exibição que está associado com o modelo de modo de exibição.

Alternativamente, você poderia olhar O Windows Phone MVC que também tem algum tipo de segurança de navegação.Você pode até mesmo ser capaz de puxar o código de navegação para usar em seu próprio país, já que é licenciado sob MS-PL.

Outras dicas

Basicamente, não, não, isto é built-in.Parâmetros complexos como IRepository instâncias são, infelizmente, além da capacidade das instalações de navegação no Silverlight;Eu costumo usar algum tipo de contêiner IoC para lidar com esses.Mais simples POCO parâmetros são facilmente serializado para uma seqüência de caracteres, mas que ainda requer cordas mágicas e manual de consulta-análise de cadeia de caracteres.

No entanto, você pode facilmente construir algo typesafe si mesmo.Por exemplo, aqui está a minha abordagem.

Para o parâmetro de dados, eu tenho uma classe que eu chamo de 'Extras', que envolve um Dictionary<string, object> com métodos como GetBool(string), GetInt32(string), etc., e tem um estático método de fábrica CreateFromUri(Uri);isso é bom o suficiente para os meus objetivos.

Eu uso isso em conjunto com a segurança do tipo de navegação.Eu realmente gosto do padrão MVVM, e cada uma das minhas páginas tem um ViewModel englobando quase toda a lógica.O um-para-um relação de página para ViewModel faz o último, um ideal a tecla de navegação.Isso, combinado com atributos e reflexão, nos dá uma solução simples:

public class NavigationTargetAttribute : Attribute
{
    private readonly Type target;

    public ViewModelBase Target
    {
        get { return target; }
    }

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

Colocar um desses em cada uma de suas páginas, com a devida ViewModel tipo.

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

Em seguida, em um singleton NavigationManager-esque classe, você pode fazer:

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

E só assim, você tem uma coleção de todos os navegável tipo em seu aplicativo.A partir daí, não muito mais trabalho para colocá-los em um dicionário, por exemplo.Se você seguir uma convenção para onde você colocar as suas páginas, você pode, por exemplo, traduzir entre o tipo e Uri com bastante facilidade...por exemplo, new Uri("/Pages/" + myPageType.Name + ".xaml", UriKind.Relative).Não é muito mais para adicionar suporte a parâmetros de consulta.Finalmente, você vai acabar com um método, assim:

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
}

Finalmente, na página do OnNavigatedTo método de eu fazer algo como:

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

Este, finalmente, dá uma aparência de rigidez de tipos de navegação.Este é um bare-bones abordagem;em cima da minha cabeça, isso poderia ser melhorado, adicionando parâmetros necessários na navegação atributo e validando-os em navegação de tempo.Ele também não suporta mais complexos tipos de navegação, onde o valor de nav argumentos iria determinar o destino final.No entanto, este atende as minhas 90% de casos de uso - talvez isso vai funcionar para você também.

Há definitivamente alguns detalhes omitidos aqui, como exatamente para obter uma instância de NavigationService - Eu posso trabalhar até obter um exemplo mais completo, mais tarde, hoje à noite, mas isso deve ser o suficiente para começar.

Você pode usar PhoneApplicationService.State

É um Dictionary<String,Object>

PhoneApplicationService.State é comumente utilizado na marcação para exclusão para armazenar o estado atual do aplicativo.No entanto, ele pode ser convenientemente utilizado para transmitir dados entre páginas.

Documentação do MSDN

Aplicativos do Windows Phone são desativados quando o usuário navega para outra aplicação.Quando o usuário retorna para o aplicativo, por usando o botão Voltar ou através do preenchimento de um Iniciador ou o Seletor de tarefa, o a aplicação é reativada.Um aplicativo pode armazenar transitórias o estado da aplicação no Estado de dicionário no manipulador para o Desativado evento.No manipulador de eventos Ativado, um aplicativo pode use os valores armazenados no dicionário de Estado para transitório de aplicação do estado.

Basicamente o que você deve fazer é

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

Em seguida, no seu navegado muito método, você pode recuperá-lo

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

Aqui está uma olhada mais aprofundada de como usar esse recurso

O WPF oferece suporte a navegação para uma já criada objeto, mas WP8 falta que Navigate sobrecarga.

Se você não deseja rígido código XAML página URIs, você pode, você pode usar o seguinte (um pouco sujo) função auxiliar para obter o .recurso xaml URI de alguma classe.

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

Em seguida, você pode modificar a URL e navegue para:

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

Nossa solução que funciona muito bem:
1. Não usar seqüências de caracteres de consulta na Página Uris, isto é completamente contra MVVM, onde o modo de exibição deve apenas mostrar coisas, mas a lógica real para o carregamento e a seleção de itens é em ViewModel.
2.Criar classe com const nomes de Página e sempre que você quiser navegar, use apenas essa:

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));
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top