Используя несколько представлений с Template10, не всегда показывая главную страницу?

Я новичок в T10 и пытаюсь научиться этому. Это продолжение шаблона 10 Несколько окон

В "обычном" (то есть не в Template10) приложении UWP я научился делать что-то вроде этого (в качестве краткого примера) для поддержки нескольких представлений:

public App() { InitializeComponent(); Suspending += OnSuspending; }

readonly List<CoreDispatcher> _dispatchers = new List<CoreDispatcher>();
protected override async void OnLaunched(LaunchActivatedEventArgs e)
{
    Frame rootFrame = Window.Current.Content as Frame;
    if (rootFrame == null) 
    {
        rootFrame = new Frame();
        rootFrame.NavigationFailed += OnNavigationFailed;

        Window.Current.Content = rootFrame;
        if (rootFrame.Content == null)
        {
            rootFrame.Navigate(typeof(MainPage), e.Arguments);
        }

        Window.Current.Activate();
        _dispatchers.Add(CoreWindow.GetForCurrentThread().Dispatcher);
    }
    else 
    {
        var view = CoreApplication.CreateNewView();
        int windowId = 0;
        await view.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            windowId = ApplicationView.GetApplicationViewIdForWindow(CoreWindow.GetForCurrentThread());
            var frame = new Frame();
            frame.Navigate(typeof(MainPage), null);
            Window.Current.Content = frame;
            Window.Current.Activate();
            ApplicationView.GetForCurrentView().Consolidated += View_Consolidated;
        });

        await _dispatchers[_dispatchers.Count - 1].RunAsync
        (
            CoreDispatcherPriority.Normal, async () => { var _ = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(windowId); }
        );
        _dispatchers.Add(view.Dispatcher);
    }
}

private void View_Consolidated(ApplicationView sender, ApplicationViewConsolidatedEventArgs args)
{
    _dispatchers.Remove(CoreWindow.GetForCurrentThread().Dispatcher);
    ApplicationView.GetForCurrentView().Consolidated -= View_Consolidated;
}

Теперь: как мне это сделать с Template10? Я посмотрел пример https://github.com/Windows-XAML/Template10/wiki/Multiple-Views но не могу понять. Более конкретно, я хочу перейти на определенную страницу при использовании активации протокола (с использованием шаблона Hamburger). Вот что я дошел до сих пор:

public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
{
    var protocolArgs = args as ProtocolActivatedEventArgs;
    if (protocolArgs != null && protocolArgs.Uri != null)
    {
        await NavigationService.OpenAsync(typeof(Views.DetailPage)); // protocol activation
    }
    else
    {
        await NavigationService.NavigateAsync(typeof(Views.MainPage)); // regular activation
    }
}

Это работает за исключением того, что главная страница также отображается (вместе с DetailPage) с OpenAsync. При использовании "обычного" подхода UWP, описанного выше, у меня нет проблемы. Как я могу заставить это работать, как я хотел бы? Я уверен, что это что-то простое.

Мне пока нравится T10 - спасибо Джерри и команде за вклад.

РЕДАКТИРОВАТЬ Подробнее

На основании приведенных ниже предложений я изменил код (в App.xaml.cs) на:

public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
{
    var protocolArgs = args as ProtocolActivatedEventArgs;
    if (protocolArgs != null)
    {
        var pageName = protocolArgs.Uri.AbsolutePath;
        if (!string.IsNullOrEmpty(pageName))
        {
            string pageId = protocolArgs.Uri.LocalPath;
            var pageQuery = protocolArgs.Uri.Query;
            // Here would navigate to the page specified by "pageId"... as an example:
            if (pageId == "foo")
                await NavigationService.OpenAsync(typeof(Views.FooPage), null, pageQuery);
            else if (pageId == "bar")
                await NavigationService.OpenAsync(typeof(Views.BarPage), null, pageQuery);
            else
                await NavigationService.NavigateAsync(typeof(Views.MainPage));
        }
    }
    else
    {
        await NavigationService.NavigateAsync(typeof(Views.MainPage));
    }

}

а также:

public override UIElement CreateRootElement(IActivatedEventArgs args)
{
    var service = NavigationServiceFactory(BackButton.Attach, ExistingContent.Exclude);

    var protocolArgs = args as ProtocolActivatedEventArgs;
    var pageName = protocolArgs?.Uri.AbsolutePath;
    if (!string.IsNullOrEmpty(pageName))
    {
        return new Frame();  <<---------- WRONG?
    }

    return new ModalDialog
    {
        DisableBackButtonWhenModal = true,
        Content = new Views.Shell(service),
        ModalContent = new Views.Busy(),
    };

}

Теперь у меня есть пустая форма, которая также отображается при использовании активации протокола (и больше не форма Shell, как отмечает Sunteen), потому что (я думаю) строки помечены как "НЕПРАВИЛЬНО" выше. Насколько я понимаю, CreateRootElement необходимо выполнить, но когда приложение активируется по протоколу, у меня нет / не хочу отображать корневой фрейм; но CreateRootElement должен что-то вернуть. Как вы можете видеть из моего примера, это не совсем как пример MultipleViews, потому что в этом примере всегда есть корневой фрейм. Примечание: Кроме того, я думаю, что с T10 я не должен / не могу использовать прямую навигацию, как предлагает Sunteen: навигация должна быть обработана T10.

Благодарю.

2 ответа

Это работает за исключением того, что главная страница также отображается (вместе с DetailPage) с OpenAsync

Я думаю, что вы имеете в виду Shell.xaml страница также отображается. Это потому, что в настоящее время NavigationService принадлежит к кадру, который без Shell страница внутри, Shell страница уже создана до навигации CreateRootElement метод.

Я хочу перейти на определенную страницу при использовании активации протокола (с использованием шаблона Hamburger)

Чтобы удовлетворить ваши требования, я бы рекомендовал вам не нарушать структуру навигации в вашем проекте, а создать новый фрейм для специального сценария, запускаемого по протоколу. Например:

public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
{
    // TODO: add your long-running task here    
    var protocolArgs = args as ProtocolActivatedEventArgs;
    if (protocolArgs != null && protocolArgs.Uri != null)
    {
        Frame newframe = new Frame();
        newframe.Navigate(typeof(Views.DetailPage));
        Window.Current.Content = newframe; // protocol activation
    }
    else
    {
        await NavigationService.NavigateAsync(typeof(Views.MainPage)); // regular activation
    }
}

В новом коде уже есть полный пример, который вскоре будет выпущен. Его под веткой источника v 1.1.3p

https://github.com/Windows-XAML/Template10/tree/version_1.1.13p/Samples/MultipleViews/ViewModels

последний выпуск V 1.1.2_vs2017, который является обновлением шаблона для VS2017, также имеет тот же пример, который выложенный код более или менее такой же под обложками с некоторыми изменениями, чтобы заставить его работать должным образом с T10

Другие вопросы по тегам