Using multiple views with Template10 without always showing the Main Page?

淺唱寂寞╮ 提交于 2019-12-10 11:16:47

问题


I am new to T10 and trying to learn it. This is a follow-up to Template 10 Multiple Windows

In 'regular' (meaning non-Template10) UWP app I've learned to do something like this (as a short example) in order to support multiple views:

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;
}

Now: how do I do this with Template10? I've looked at the https://github.com/Windows-XAML/Template10/wiki/Multiple-Views sample but can't figure it out. More specifically, I want to go to a specific page when using protocol activation (using Hamburger template). Here's what I've come up so far :

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
    }
}

This works EXCEPT that the Main page is also displayed (along with the DetailPage) with the OpenAsync. Using the 'regular' UWP approach described above I do not have the issue. How can I get this to work as I'd like? I'm sure this is something simple.

I like T10 so far - thanks Jerry and team for the contribution.

EDIT More Details

Based on suggestions below, I changed the code (in App.xaml.cs) to:

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));
    }

}

and:

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(),
    };

}

Now, I have a blank form that is also displayed when using protocol activation (and no longer the Shell form as noted by Sunteen), because (I think) of the line flagged 'WRONG' above. My understanding is that CreateRootElement needs to be executed, but when the app is activated by protocol I don't have / don't want a root frame to display; but CreateRootElement must return something. As you can see by my example, it's not exactly as the MultipleViews sample because that example always have a root frame. Note: Furthermore, I think that with T10 I should not/cannot use direct navigation as suggested by Sunteen: the navigation must all be handled by T10.

Thanks.


回答1:


This works EXCEPT that the Main page is also displayed (along with the DetailPage) with the OpenAsync

I think you mean the Shell.xaml page is also displayed. This is because the currently NavigationService is belonged to the frame that without Shell page inside, the Shell page already created before navigation by CreateRootElement method.

I want to go to a specific page when using protocol activation (using Hamburger template)

To meet your requirements,I'd recommend you not to break the navigation structure in your project, but create a new frame for the special scenario that launched by protocol. For example:

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
    }
}



回答2:


There is a complete sample already in the newer code that is being pushed out shortly. Its under source branch v 1.1.3p

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

the most recent release V 1.1.2_vs2017 which is the template update for VS2017 also has the same sample, which the code that you posted is more or less the same under the covers with some tweaks to make it work proper with T10



来源:https://stackoverflow.com/questions/45340770/using-multiple-views-with-template10-without-always-showing-the-main-page

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!