Pregunta

Estoy buscando una manera de navegar entre pantallas en mi aplicación.Básicamente, lo que he visto hasta ahora consiste en pasar una cadena URI al NavigationService, completa con parámetros de cadena de consulta, por ejemplo.

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

Sin embargo, en última instancia, no estoy muy interesado en esto porque requiere hilos mágicos y pueden generar problemas en el futuro.

Lo ideal sería crear una instancia de la clase a la que quiero navegar y pasar los parámetros como argumentos al constructor.es posible?¿Si es así, cómo?

¿Fue útil?

Solución

Si bien la navegación real eventualmente tendrá que usar cadenas, puede crear o usar un contenedor que sea seguro para escribir.

Yo sugeriría mirar Caliburn Micro incluso si solo lo usaste para el tipo navegación segura.Aquí hay un fragmento de un tutorial sobre su uso en WP8:

El NavigationService que viene con el kit de herramientas admite una ver el modelo primero acercarse:en lugar de declarar cuál es la URL de la página a la que queremos llevar al usuario (ese es el enfoque estándar), declaramos cuál es el ViewModel que queremos mostrar. El servicio se encargará de crear la URL correcta y mostrar la vista asociada con el modelo de vista..

Alternativamente podrías mirar MVC de Windows Phone que también cuenta con algún tipo de navegación segura.Es posible que incluso puedas extraer el código de navegación para usarlo por tu cuenta, ya que tiene licencia bajo MS-PL.

Otros consejos

Básicamente, no, eso no está integrado.Desafortunadamente, los parámetros complejos como las instancias de IRepository están más allá de la capacidad de las funciones de navegación de Silverlight;Normalmente uso algún tipo de contenedor de IoC para manejarlos.Los parámetros POCO más simples se serializan fácilmente en una cadena, pero eso aún requiere cadenas mágicas y análisis manual de cadenas de consulta.

Sin embargo, usted mismo puede crear fácilmente algo seguro para tipos.Por ejemplo, este es mi enfoque.

Para los datos de parámetros, tengo una clase que llamo 'Extras', que envuelve un Dictionary<string, object> con métodos como GetBool(string), GetInt32(string), etc., y tiene un método de fábrica estático CreateFromUri(Uri);esto es lo suficientemente bueno para mis propósitos.

Lo uso junto con la navegación con seguridad de escritura.Realmente me gusta el patrón MVVM y cada una de mis páginas tiene un ViewModel que encapsula casi toda la lógica.La relación uno a uno entre la página y ViewModel hace que este último sea una clave de navegación ideal.Eso, combinado con atributos y reflexión, nos da una solución simple:

public class NavigationTargetAttribute : Attribute
{
    private readonly Type target;

    public ViewModelBase Target
    {
        get { return target; }
    }

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

Coloque uno de estos en cada una de sus páginas, con el tipo de ViewModel adecuado.

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

Luego, en una clase singleton tipo NavigationManager, puedes hacer:

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

Y así, tienes una colección de cada tipo navegable en tu aplicación.A partir de ahí, no supone mucho más trabajo ponerlos en un diccionario, por ejemplo.Si sigues una convención sobre dónde colocar tus páginas, puedes (por ejemplo) traducir entre tipo y Uri con bastante facilidad...Por ejemplo, new Uri("/Pages/" + myPageType.Name + ".xaml", UriKind.Relative).No es mucho más agregar soporte para parámetros de consulta.Finalmente, terminarás con un método como este:

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, en la página OnNavigatedTo método, hago algo como:

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

Esto, finalmente, da una apariencia de navegación fuertemente tipada.Este es un enfoque básico;Se me ocurre que esto podría mejorarse agregando los parámetros requeridos en el atributo de navegación y validándolos en el momento de la navegación.Tampoco admite tipos de navegación más complejos, donde el valor de los argumentos de navegación determinaría el destino final.Sin embargo, esto se adapta a mi caso de uso del 90%; tal vez también funcione para usted.

Definitivamente se omiten algunos detalles aquí, como cómo obtener exactamente una instancia de NavigationService - Puedo preparar una muestra más completa más tarde esta noche, pero esto debería ser suficiente para empezar.

Puedes usar PhoneApplicationService.State

Es un Dictionary<String,Object>

PhoneApplicationService.State se usa comúnmente en desecho para almacenar el estado actual de la aplicación.Sin embargo, se puede utilizar para pasar datos cómodamente entre páginas.

documentación de MSDN

Las aplicaciones de Windows Phone se desactivan cuando el usuario navega a otra aplicación.Cuando el usuario vuelve a la aplicación, utilizando el botón Atrás o completando una tarea de lanzador o selección, se reactiva la aplicación.Una aplicación puede almacenar el estado de aplicación transitoria en el diccionario estatal en el controlador para el evento desactivado.En el controlador de eventos activados, una aplicación puede usar los valores almacenados en el diccionario estatal al estado de aplicación transitoria.

Básicamente lo que harías es

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

Luego, en el método navegado también, puedes recuperarlo.

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

A continuación se ofrece una descripción más detallada de cómo utilizar esta función.

WPF Admite la navegación a un objeto ya creado, pero WP8 le falta esa sobrecarga de Navigate.

Si no desea que URIS de Page XAML de código duro, puede usar la siguiente función de ayuda (un poco sucia) para obtener la URI de recurso .xaml de alguna clase.

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

Luego, puede modificar esa URL y navegar a él:

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

Nuestra solución que funciona bien:

1. No utilice las cadenas de consulta en la página URIS, esto es completamente de nuevo MVVM donde la vista debe mostrar cosas, pero la lógica real para cargar y seleccionar elementos está en ViewModel.
2. Cree clase con los nombres de la página const y siempre que desee navegar, solo use esto:

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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top