Si ya está utilizando MVVM Light, una opción es hacer uso del bus de mensajes que incluye. Así que vincula su botón a un RelayCommand en el modelo de vista, como ya dijo que ya está haciendo. En el controlador para su RelayCommand, puede tomar la decisión de a qué vista navegar. Esto mantiene toda esa lógica en el modelo de vista.
Una vez que el controlador de comando haya decidido a qué vista navegar, puede publicar un mensaje en el bus de mensajes. Su vista escuchará ese mensaje y luego usará NavigationService para realizar la navegación. Por lo tanto, no está haciendo otra cosa que esperar a que le digan que navegue en algún lugar y luego navegue donde se lo dice.
He estado haciendo esto definiendo una clase de NavigationMessage que mis modelos de vista pueden publicar, y una clase base de vista que mi vista hereda de la que contiene el oyente. El NavigationMessage se ve así:
public class NavigationMessage : NotificationMessage
{
public string PageName
{
get { return base.Notification; }
}
public Dictionary<string, string> QueryStringParams { get; private set; }
public NavigationMessage(string pageName) : base(pageName) { }
public NavigationMessage(string pageName, Dictionary<string, string> queryStringParams) : this(pageName)
{
QueryStringParams = queryStringParams;
}
}
Esto permite simplemente pasar el nombre de la página, o incluyendo también opcionalmente cualquier parámetro de cadena de consulta necesarios. Un controlador RelayCommand sería publicar este mensaje como este:
private void RelayCommandHandler()
{
//Logic for determining next view, then ...
Messenger.Default.Send(new NavigationMessage("ViewToNavigate"));
}
Por último, la clase vista base se parece a esto:
public class BasePage : PhoneApplicationPage
{
public BasePage()
{
Messenger.Default.Register<NavigationMessage>(this, NavigateToPage);
}
protected void NavigateToPage(NavigationMessage message)
{
//GetQueryString isn't shown, but is simply a helper method for formatting the query string from the dictionary
string queryStringParams = message.QueryStringParams == null ? "" : GetQueryString(message);
string uri = string.Format("/Views/{0}.xaml{1}", message.PageName, queryStringParams);
NavigationService.Navigate(new Uri(uri, UriKind.Relative));
}
}
Esto es suponiendo una convención donde todos los puntos de vista están en una carpeta "Vistas" en la raíz de la aplicación. Esto funciona bien para nuestra aplicación, pero por supuesto, esto podría ampliarse para admitir diferentes escenarios sobre cómo organizar sus vistas.
Excelente sugerencia, gracias! –
Admitiré que no estoy muy familiarizado con el sistema Messenger que MVVM-Light ofrece. Si se reflexiona más, ¿no significa que todas las vistas se registrarán y escucharán este NavigationMessage? –
Supongo que podría ser un problema. Estoy usando esta técnica en el contexto de una aplicación Windows Phone 7 donde solo tengo una vista activa a la vez, así que funciona perfectamente. Si está trabajando en la versión de escritorio de Silverlight, o WPF, y tiene varias vistas activas a la vez, puedo ver dónde podría haber un problema. Tendrá que pensar en eso un poco más. –