MVVM и NavigationService - PullRequest
       44

MVVM и NavigationService

4 голосов
/ 15 января 2012

Одним из многих преимуществ реализации любого шаблона является разделение задач между различными уровнями приложения.В случае Silverlight и MVVM, я считаю, что NavigationService принадлежит пользовательскому интерфейсу.

Если NavigationService принадлежит пользовательскому интерфейсу, его следует использовать в коде XAML, но команды выполняются в ViewModel,Должен ли я вызвать событие для команды в ViewModel и позволить представлению обработать событие и вызвать навигацию?Это звучит немного абсурдно, если я просто перехожу на другую страницу.Разве я не должен просто обрабатывать событие пользовательского интерфейса напрямую и перемещаться оттуда?

Просмотр события управления -> Команда ViewModel -> Поднять событие -> Просмотр обработанного события -> Навигация

или

Просмотр события управления -> Просмотр обработанного события -> Навигация

Ответы [ 2 ]

6 голосов
/ 18 января 2012

Существует два документированных подхода к этой проблеме

  1. Реализация навигации с использованием функции обмена сообщениями MVVM LightЭтот подход был предложен Джесси Либерти в Часть 3 его MVVM Ligtht суп из орехов серии .Его подход заключается в отправке сообщения из команды в представление, указывающее, что должна быть выполнена навигационная операция.
  2. Реализация ViewService, который обрабатывает навигациюЭтот подход был ответом Лорана Бюньона на пост Джесси.Это реализует сервис, который обрабатывает все навигационные операции, запускаемые моделями представления.

Оба подхода имеют дело только с навигацией в приложениях WP7.Однако они также могут быть адаптированы к приложениям Silverligt.

Подход Джесси легче использовать в SL, так как он не требует доступа к корневому визуалу.Однако навигационный код распространяется в нескольких местах, и для выполнения реальной навигации требуется код.

Подход Лорана требует доступа к корневому визуальному элементу, который используется для доступа к встроенным функциям навигации.Получение доступа к этому, как показано в коде Лорана, не является большой проблемой в приложениях WP7.В приложениях SL, однако, это немного сложнее, так как нет окружающего кадра.Тем не менее, я уже внедрил шаблон для SL в одном из моих проектов, используя присоединенное свойство, которое выполняет требуемую разводку - поэтому, хотя и требует больше работы, его можно использовать и для SL.

Итак, заключение - хотя Джессиподход проще реализовать, лично я предпочитаю подход Лорана, так как это более чистая архитектура - за кодом не требуется, а функциональность заключена в отдельный компонент и, таким образом, расположена в одной точке.

0 голосов
/ 21 июля 2014

Немного опоздал на этот вопрос, но он актуален и, надеюсь, будет кому-то полезен. Я должен был создать приложение SL4 с MvvmLight и хотел использовать обертку службы навигации, которая была бы смоделированной и могла быть введена в ViewModel. Здесь я нашел хорошую отправную точку: примеры кода Лорана Буньона SL4 из Mix11, который включает демонстрацию навигационного сервиса: Deep Dive MVVM Mix11

Вот основные части для реализации моделируемого навигационного сервиса, который может использоваться с Silverlight 4. Ключевой вопрос - получение ссылки на основной фрейм навигации, который будет использоваться в пользовательском классе NavigationService.

1) В MainPage.xaml рамке навигации присваивается уникальное имя, для этого примера это будет ContentFrame :

<navigation:Frame x:Name="ContentFrame" Style="{StaticResource ContentFrameStyle}"
    Source="/Home" Navigated="ContentFrame_Navigated"  
    NavigationFailed="ContentFrame_NavigationFailed">
    <!-- UriMappers here -->
</navigation:Frame>

2) В MainPage.xaml.cs рамка навигации отображается как свойство:

public Frame NavigationFrame
{
    get { return ContentFrame; }
}

3) Класс обслуживания навигации реализует интерфейс INavigationService и использует свойство NavigationFrame файла MainPage.xaml.cs для получения ссылки на фрейм навигации:

public interface INavigationService
{
    event NavigatingCancelEventHandler Navigating;
    void NavigateTo(Uri uri);
    void GoBack();
}

public class NavigationService : INavigationService
{
    private Frame _mainFrame;
    public event NavigatingCancelEventHandler Navigating;
    public void NavigateTo(Uri pageUri)
    {
        if (EnsureMainFrame())
            _mainFrame.Navigate(pageUri);
    }
    public void GoBack()
    {
        if (EnsureMainFrame() && _mainFrame.CanGoBack)
            _mainFrame.GoBack();
    }
    private bool EnsureMainFrame()
    {
        if (_mainFrame != null)
            return true;
        var mainPage = (Application.Current.RootVisual as MainPage);
        if (mainPage != null)
        {
            // **** Here is the reference to the navigation frame exposed earlier in steps 1,2 
            _mainFrame = mainPage.NavigationFrame;
            if (_mainFrame != null)
            {
                // Could be null if the app runs inside a design tool
                _mainFrame.Navigating += (s, e) =>
                {
                    if (Navigating != null)
                    {
                        Navigating(s, e);
                    }
                };
                return true;
            }
        }
        return false;
    }
}
...