Ответ 1
Если вы уже используете MVVM Light, один из вариантов - использовать шину сообщений, которую он включает. Таким образом, вы привязываете свою кнопку к RelayCommand в модели представления, как вы уже сказали, что уже делаете. В обработчике вашей RelayCommand вы можете принять решение о том, к какому представлению перейти. Это сохраняет всю эту логику в модели представления.
Как только ваш командный обработчик определит, к какому представлению переходить, он может опубликовать сообщение на шине сообщений. Ваше представление будет прослушивать это сообщение, а затем использовать NavigationService для фактического выполнения навигации. Таким образом, он не делает ничего, кроме ожидания, когда ему скажут, куда-то перемещаться, а затем - в том месте, где он сказал.
Я делал это, определяя класс NavigationMessage, который могут публиковать мои модели представлений, и базовый класс представлений, наследуемый моими представлениями, который содержит слушателя. NavigationMessage выглядит так:
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;
}
}
Это позволяет просто передавать имя страницы или, необязательно, также включать любые необходимые параметры строки запроса. Обработчик RelayCommand опубликовал бы это сообщение так:
private void RelayCommandHandler()
{
//Logic for determining next view, then ...
Messenger.Default.Send(new NavigationMessage("ViewToNavigate"));
}
Наконец, базовый класс представления выглядит так:
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));
}
}
Предполагается, что все представления находятся в папке "Views" в корне приложения. Это прекрасно работает для нашего приложения, но, конечно, его можно расширить для поддержки различных сценариев организации ваших представлений.