MVVM Silverlight и навигация по страницам

#silverlight #mvvm #navigation

#silverlight #mvvm #навигация

Вопрос:

Я только начинаю работать с Silverlight, а также с моделью MVVM. При выполнении навигации по страницам и отправке аргументов с одной страницы на другую .. является ли использование querystring наиболее приемлемым методом?

Кажется, существует большая путаница в том, как должна выполняться передача аргументов при выполнении навигации по странице. По крайней мере, я нахожу несколько тем об этом на различных веб-ресурсах, но, похоже, никто не согласен с методом «наилучшей практики».

Ответ №1:

ПРИМЕЧАНИЕ: Приведенное ниже решение по использованию строк запроса в NavigationContext работает как в браузере, так и вне его.

Обычно вы настраиваете свой UriMapper примерно так:

            <navigation:Frame Source="/Home" >
                <navigation:Frame.UriMapper>
                    <uriMapper:UriMapper>
                        <uriMapper:UriMapping Uri="" 
                                   MappedUri="/Views/Home.xaml"/>
                        <uriMapper:UriMapping Uri="/{pageName}/{key}" 
                                   MappedUri="/Views/{pageName}.xaml?entityGuid={key}"/>
                        <uriMapper:UriMapping Uri="/{pageName}" 
                                   MappedUri="/Views/{pageName}.xaml"/>
                    </uriMapper:UriMapper>
                </navigation:Frame.UriMapper>
            </navigation:Frame>
  

И затем, чтобы включить NavigationContext в модель представления, вы добавляете вспомогательный элемент в свое представление следующим образом:

 <navigation:Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:helpers="clr-namespace:MyApp.Helpers"
                 xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
                 DataContext="{Binding Path=Entity, Source={StaticResource Locator}}"
                 helpers:Navigator.Source="{Binding}">
  

И затем у вас есть прикрепленный помощник по свойствам, подобный этому (я модифицировал это у кого-то другого, хотя я забыл, у кого):

 using System.Windows;
using System.Windows.Controls;

namespace MyApp.Helpers
{

    public interface INavigable
    {
        System.Windows.Navigation.NavigationService NavigationService { get; set; }
        System.Windows.Navigation.NavigationContext NavigationContext { get; set; }
    }


    public static class Navigator
    {
        public static INavigable GetSource(DependencyObject obj)
        {
            return (INavigable)obj.GetValue(SourceProperty);
        }

        public static void SetSource(DependencyObject obj, INavigable value)
        {
            obj.SetValue(SourceProperty, value);
        }

        public static readonly DependencyProperty SourceProperty =
             DependencyProperty.RegisterAttached("Source", typeof(INavigable), typeof(Navigator), new PropertyMetadata(OnSourceChanged));

        private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Page page = (Page)d;

            page.Loaded  = PageLoaded;
        }

        private static void PageLoaded(object sender, RoutedEventArgs e)
        {
            Page page = (Page)sender;

            INavigable navSource = GetSource(page);

            if (navSource != null)
            {
                navSource.NavigationService = page.NavigationService;
                navSource.NavigationContext = page.NavigationContext;
            }
        }
    }
}
  

А затем добавьте следующее в свою ViewModel:

     private NavigationContext _NavigationContext;
    public NavigationContext NavigationContext {
        get { return _NavigationContext; }
        set {
            if (_NavigationContext == value)
                return;
            _NavigationContext = value;
            RaisePropertyChanged("NavigationContext");
        }
    }
    protected override void RaisePropertyChanged(string propertyName) {
        base.RaisePropertyChanged(propertyName);

        switch (propertyName) {
            case "NavigationContext":
                if (NavigationContext.QueryString.ContainsKey("entityGuid")) {
                    if (NavigationContext.QueryString["entityGuid"].Equals("new", StringComparison.InvariantCultureIgnoreCase)) {
                        LoadNewEntity();  // your 'new' logic
                    } else {
                        this.EntityGuid = new Guid(NavigationContext.QueryString["entityGuid"]);
                        LoadExistingEntity(EntityGuid);  // your 'existing' logic
                    }
                }
                break;
        }
    }
  

Комментарии:

1. Я не совсем понимаю эту строку из xaml: DataContext=»{Путь привязки = Сущность, источник = {Локатор StaticResource}}» Локатор не найден в моем проекте

2. Извините, это MVVM light, что делают многие люди. Ознакомьтесь с этим сообщением, это действительно намного лучше, чем установка вашей ViewModel в ресурсе:

3. johnpapa.net/…

4. Спасибо 🙂 Это должно вернуть меня в нужное русло!

5. Для справки, я думаю, что нашел ваш оригинальный источник: garfoot.com/blog/2010/09 /…