2010-09-16 12 views
7

Tengo un proyecto de Silverlight 4 que muestra un gráfico y algunos botones para permitir al usuario cambiar el rango de fechas del gráfico. El rango de fechas también se puede pasar a través de un parámetro de cadena de consulta, algo así como http://myserver/MySilverlightPage/#?DateRange=OneMonth, y cuando el usuario hace clic en un botón también me gustaría actualizar la URL.¿Hay alguna manera de llamar a Navigate desde el ViewModel?

Entiendo que la forma de hacerlo es llamar al this.NavigationService.Navigate(new Uri(...)), pero hasta donde puedo decir esto solo se puede hacer desde el código de la página de Silverlight. Y dado que estoy usando MVVM, todo el procesamiento del comando tiene lugar en la clase ViewModel. ¿Hay alguna manera de llamar al Navigate o cambiar la URL desde ViewModel?

Para aclarar, el XAML incluye lo siguiente Button:

<Button Content="1 Month View" 
     Command="{Binding OneMonthCommand}" /> 

Y la clase ViewModel contiene una propiedad OneMonthCommand:

public ICommand OneMonthCommand { get; set; } 

Cuando el botón se hace clic en el método de mi implementación ICommand Execute se llama. La pregunta es: ¿cómo puedo cambiar la URL desde dentro de ese método?

Respuesta

8

He encontrado que esto es un problema común en las aplicaciones de Silverlight que escribo usando el patrón MVVM. Utilizo una clase NavigationHelper para centralizar la lógica en torno a la navegación. Se ve algo como esto:

public interface INavigationHelper 
{ 
    void Home(); 
    void SomeOtherPage(); 
} 

public class NavigationHelper : INavigationHelper 
{ 
    private NavigationService _navSvc; 

    public NavigationHelper(NavigationService navSvc) 
    { 
     _navSvc = navSvc; 
    } 

    public void Home() 
    { 
     _navSvc.Navigate(new Uri("/Home", UriKind.Relative)); 
    } 

    public void SomeOtherPage() 
    { 
     _navSvc.Navigate(new Uri("/SomeOtherPage", UriKind.Relative)); 
    } 
} 

Entonces, tengo el modelo de vista tiene una propiedad NavigationHelper, que es fijado por la página cuando se construye el modelo de vista.

Por cierto, parece que sería más simple tener el NavigationHelper pasado en el constructor de ViewModel. Pero tener constructores no predeterminados para ViewModel hace que sea más difícil hacer que las cosas funcionen en tiempo de diseño en Blend, en mi experiencia.

+0

¿Quién construye ViewModel en su caso? ¿Un código detrás de una vista? ¿O una tercera clase que crea ambas, la vista y el modelo de vista? –

+0

En general, generalmente prefiero que ViewModel se cree como recurso en el XAML de la página. Pero cuando eso no es lo suficientemente robusto, me muevo a un creador externo. Creo que este patrón funcionaría en ambos casos. – RationalGeek

1

El uso de MVVM no excluye el uso de botones de hipervínculo si harán el trabajo que necesita.

El problema, como ha encontrado, con NavigationService.Navigate es que requiere el conocimiento de una página para su contexto.

No creo que se considere "demasiado malo" para inyectar su vista actual nuevamente en su modelo de vista cuando establece el contexto de datos en código subyacente. En general, es peor para la Vista saber demasiado acerca de su ViewModel.

2

Si solo está navegando de forma regular, debe usar los botones de hipervínculo normales. Sin embargo, si intenta navegar en respuesta a otros eventos, puede usar la mensajería.

Una alternativa es hacer que la Vista pase la clase NavigationService a su ViewModel, y si usa una página base y un modelo de vista base podrá hacer que suceda en aquellos sin el requisito de cada modelo de vista y ver sobre la entrega se lleva a cabo.

Cuestiones relacionadas