Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WPF, Silverlight Новый топик    Ответить
 Принять параметр навигации  [new]
vb_sub
Member

Откуда:
Сообщений: 589
Всем привет, пишу UWP-приложение с постраничной навигацией(MVVM).

Интерфейс навигации
    /// <summary>
    /// Provides a mechanism to navigate between pages.
    /// </summary>
    public interface INavigationService
    {
        /// <summary>
        /// Gets the name of the currently displayed page.
        /// </summary>
        string CurrentPage { get; }

        /// <summary>
        /// Navigates to the specified page.
        /// </summary>
        /// <param name="page"></param>
        void NavigateTo(string page);

        /// <summary>
        /// Navigates to the specified page and
        /// supply additional page-specific parameters.
        /// </summary>
        /// <param name="page"></param>
        /// <param name="parameter"></param>
        void NavigateTo(string page, object parameter);

        /// <summary>
        /// Navigates to the previous page in the navigation history.
        /// </summary>
        void GoBack();
    }
}



Его реализация
    /// <summary>
    /// Provides a mechanism to navigate between pages.
    /// </summary>
    public sealed class NavigationService : INavigationService
    {
        private readonly IDictionary<string, Type> pages_
            = new Dictionary<string, Type>();

        /// <summary>
        /// The name of the virtual "root" page at the top of the navigation history.
        /// </summary>
        public const string RootPage = "(Root)";

        /// <summary>
        /// A moniker for an "unknown" page when navigation happens without
        /// using the <see cref="NavigationService"/>.
        /// </summary>
        public const string UnknownPage = "(Unknown)";


        private static Frame AppFrame
        {
            get
            {  
                return ((Window.Current.Content as Frame)?.Content as MainPage)?.AppFrame;
            }
        }
             

        public void Configure(string page, Type type)
        {
            lock (pages_)
            {
                if (pages_.ContainsKey(page))
                    throw new ArgumentException("The specified page is already registered.");

                if (pages_.Values.Any(v => v == type))
                    throw new ArgumentException("The specified view has already been registered under another name.");

                pages_.Add(page, type);
            }
        }


        public NavigationService()
        {

        }
  
        #region INavigationService Implementation

        /// <summary>
        /// Gets the name of the currently displayed page.
        /// </summary>
        public string CurrentPage
        {
            get
            {
                var frame = AppFrame;
                if (frame.BackStackDepth == 0)
                    return RootPage;

                if (frame.Content == null)
                    return UnknownPage;

                var type = frame.Content.GetType();

                lock (pages_)
                {
                    if (pages_.Values.All(v => v != type))
                        return UnknownPage;

                    var item = pages_.Single(i => i.Value == type);

                    return item.Key;
                }
            }
        }

        /// <summary>
        /// Navigates to the specified page.
        /// </summary>
        /// <param name="page"></param>
        public void NavigateTo(string page)
        {
            NavigateTo(page, null);
        }

        /// <summary>
        /// Navigates to the specified page and
        /// supply additional page-specific parameters.
        /// </summary>
        /// <param name="page"></param>
        /// <param name="parameter"></param>
        public void NavigateTo(string page, object parameter)
        {
            lock (pages_)
            {
                if (!pages_.ContainsKey(page))
                    throw new ArgumentException("Unable to find a page registered with the specified name.");

                //System.Diagnostics.Debug.Assert(AppFrame != null);
                AppFrame.Navigate(pages_[page], parameter);
            }
        }

        /// <summary>
        /// Navigates to the previous page in the navigation history.
        /// </summary>
        public void GoBack()
        {
            //System.Diagnostics.Debug.Assert(AppFrame != null);
            if (AppFrame.CanGoBack)
                AppFrame.GoBack();
        }

        #endregion
    }


Регистрирую в контейнере зависимости ViewModels

 public class ViewModelLocator
    {

        private IKernel Kernel { get; }

        public ViewModelLocator()
        {
            Kernel = new StandardKernel();

            string UserPath = ApplicationData.Current.LocalFolder.Path;

            Kernel.Bind<ApplicationDbContext>()
                .ToSelf()
                .InTransientScope()
                .WithConstructorArgument("DbPath", UserPath);

            //Создаем папку для хранения файлов

            var WorkedDir = Path.Combine(UserPath, "DataStore");


            if (!Directory.Exists(WorkedDir))
                Directory.CreateDirectory(WorkedDir);


            Get<ApplicationDbContext>().Database.EnsureCreated();

            MapperConfiguration configuration = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<Container, SelectedContainerDto>();
                cfg.CreateMap<SelectedContainerDto, VisualContainer>();
            });

            IMapper mapper = configuration.CreateMapper();

            Kernel.Bind<IMapper>().ToConstant(mapper);


            var nav = new NavigationService();
            nav.Configure("MainPage", typeof(MainPage));
            nav.Configure("ContainerSprav", typeof(ContainerSprav));
            nav.Configure("AddContainer", typeof(AddContainer));
            nav.Configure("AddFlightType", typeof(FlightTypeSprav));
            nav.Configure("CreateDiagram", typeof(CreateDiagram));
            nav.Configure("FilledElementSprav", typeof(FilledElementSprav));
            nav.Configure("ServingSprav", typeof(ServingSprav));
            nav.Configure("ServingClassSprav", typeof(ServingClassSprav));
            nav.Configure("MeasureUnitSprav", typeof(MeasureUnitSprav));
            nav.Configure("CreateNewItemContainer", typeof(CreateNewItemContainer));
            nav.Configure("AddContainerItemToLevel", typeof(AddContainerItemToLevel));

            Kernel.Bind<INavigationService>().ToConstant(nav);
            Kernel.Bind<MenuVM>().ToConstant(new MenuVM(Get<INavigationService>()));
            Kernel.Bind<ApplicationViewModel>().ToConstant(new ApplicationViewModel());
            Kernel.Bind<ICbaseFlightInfo>().ToConstant(new OracleDataFetcher());


            Kernel.Bind<IFlightsData>()
                .To<FlightDataFetcher>()
                .InTransientScope();


            //Создание диаграммы
            Kernel
                .Bind<CreateDiagramViewModel>()
                .ToSelf()
                .InSingletonScope()
                .WithConstructorArgument("flightsData",Get<IFlightsData>())
                .WithConstructorArgument("mapper", Get<IMapper>())
                .WithConstructorArgument("navigationService", Get<INavigationService>());

            Kernel.Bind<AddContainerItemToLevelViewModel>()
                .ToSelf()
                .WithConstructorArgument("containerItems", Get<EFCoreGenericRepository<ContainerItem>>());

        }


        private T Get<T>() => Kernel.Get<T>();

         
		///Раздаем ViewModel для Pages
        
		public ApplicationViewModel ApplicationViewModel => Get<ApplicationViewModel>();

        public MenuVM MenuViewModel => Get<MenuVM>();

        public ContainersViewModel ContainersViewModel => Get<ContainersViewModel>();

        public AddContainerViewModel AddContainerViewModel => Get<AddContainerViewModel>();

        public AddContainerItemToLevelViewModel AddContainerItemToLevelViewModel => Get<AddContainerItemToLevelViewModel>();

    }


Регистрирую локатор для всего приложения в App.xaml

<Application
    x:Class="App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CbaseDiagram"
    xmlns:locator="using:Locator.Locator">
    <Application.Resources>
        <locator:ViewModelLocator x:Key="Locator" />
    </Application.Resources>
</Application>




В Page получаю ViewModel из конструктора
<Page
    x:Class="CbaseDiagram.Views.AddContainer"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CbaseDiagram.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    DataContext="{Binding AddContainerViewModel,Source={StaticResource Locator}}"/>



Если из ViewModel нужно перейти на другую страницу, то делаю инъекцию сервиса навигации в конструктор и вызываю метод навигации

// вызов команды навигации
 NavigateToCreationOfNewContainerItem = new RelayCommand(() => navigationService.NavigateTo("CreateNewItemContainer"));


Проблема в том, что если хочу вместе с навигацией передавать параметр,
NavigateToCreationOfNewContainerItem = new RelayCommand(() => navigationService.NavigateTo("CreateNewItemContainer",parameter))

то я не могу его поймать во принимающей ViewModel, страницы на которую переходят.

Пытался у принимающей Page привязать событие OnNavigatedTo, но почему-то падает в ошибку, типа нет такого события.

<Page>
    <interactivity:Interaction.Behaviors>
        <core:EventTriggerBehavior EventName="OnNavigatingTo">
            <core:InvokeCommandAction Command="{Binding OnNavigatedToCommand}" />
        </core:EventTriggerBehavior>
    </interactivity:Interaction.Behaviors>


$exception {Windows.UI.Xaml.Markup.XamlParseException: Не удалось найти текст, связанный с этим кодом ошибки.
Cannot add instance of type 'Microsoft.Xaml.Interactions.Core.EventTriggerBehavior' to a collection of type 'Microsoft.Xaml.Interactivity.BehaviorCollection'. [Line: 19 Position: 82]
at Windows.UI.Xaml.Application.LoadComponent(Object component, Uri resourceLocator, ComponentResourceLocation componentResourceLocation)
at CbaseDiagram.Views.AddContainerItemToLevel.InitializeComponent()
at CbaseDiagram.Views.AddContainerItemToLevel..ctor()} Windows.UI.Xaml.Markup.XamlParseException

Как можно без прокси поймать передаваемый параметр в принимающей ViewModel?
23 авг 19, 09:43    [21956205]     Ответить | Цитировать Сообщить модератору
 Re: Принять параметр навигации  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 5248
vb_sub,

https://www.google.com/search?q=Cannot add instance of type 'Microsoft.Xaml.Interactions.Core.EventTriggerBehavior' to a collection of type 'Microsoft.Xaml.Interactivity.BehaviorCollection -> SOF
Исключение c кривой формулировкой, конечно. Его причина в том, что у класса Page нет события OnNavigatingTo. События Navigating/Navigated есть у класса Frame.
23 авг 19, 10:07    [21956229]     Ответить | Цитировать Сообщить модератору
 Re: Принять параметр навигации  [new]
vb_sub
Member

Откуда:
Сообщений: 589
Сон Веры Павловны,
как то странно
у Page нет события, но есть метод OnNavigatedTo(я думал он вызывается как событие, когда страница делается текущей).

К сообщению приложен файл. Размер - 33Kb
23 авг 19, 10:35    [21956254]     Ответить | Цитировать Сообщить модератору
 Re: Принять параметр навигации  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 5248
vb_sub
Сон Веры Павловны,
как то странно
у Page нет события, но есть метод OnNavigatedTo(я думал он вызывается как событие, когда страница делается текущей).

А, это ж UWP, а я смотрел в справке по обычной десктопной разработке.
Тогда не знаю. Единственное, что могу посоветовать - изучать стектрейсы вложенных исключений, и смотреть в исходниках, что там, как, и почему.
Ну, либо отказаться от событий в пользу какого-либо обходного пути.
23 авг 19, 17:06    [21956650]     Ответить | Цитировать Сообщить модератору
Все форумы / WPF, Silverlight Ответить