Студия шаблонов Windows: справочная ссылка

Я создал проект с типом панель навигации и узором призма , у меня есть настройки и несколько страниц.

Вот файл App.xaml.cs:

[Windows.UI.Xaml.Data.Bindable]
public sealed partial class App : PrismUnityApplication
{
    public App()
    {
        InitializeComponent();
    }

    protected override void ConfigureContainer()
    {
        // register a singleton using Container.RegisterType<IInterface, Type>(new ContainerControlledLifetimeManager());
        base.ConfigureContainer();
        Container.RegisterInstance<IResourceLoader>(new ResourceLoaderAdapter(new ResourceLoader()));
        Container.RegisterType<ISampleDataService, SampleDataService>();
    }

    protected override async Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
    {
        await LaunchApplicationAsync(PageTokens.MainPage, null);
    }

    private async Task LaunchApplicationAsync(string page, object launchParam)
    {
        await ThemeSelectorService.SetRequestedThemeAsync();
        NavigationService.Navigate(page, launchParam);
        Window.Current.Activate();
    }

    protected override async Task OnActivateApplicationAsync(IActivatedEventArgs args)
    {
        await Task.CompletedTask;
    }

    protected override async Task OnInitializeAsync(IActivatedEventArgs args)
    {
        await base.OnInitializeAsync(args);
        await ThemeSelectorService.InitializeAsync().ConfigureAwait(false);

        //We are remapping the default ViewNamePage and ViewNamePageViewModel naming to ViewNamePage and ViewNameViewModel to
        //gain better code reuse with other frameworks and pages within Windows Template Studio
        ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
        {
            var viewModelTypeName = string.Format(CultureInfo.InvariantCulture, "App1.ViewModels.{0}ViewModel, App1", viewType.Name.Substring(0, viewType.Name.Length - 4));
            return Type.GetType(viewModelTypeName);
        });
    }

    protected override IDeviceGestureService OnCreateDeviceGestureService()
    {
        var service = base.OnCreateDeviceGestureService();
        service.UseTitleBarBackButton = false;
        return service;
    }

    public void SetNavigationFrame(Frame frame)
    {
        var sessionStateService = Container.Resolve<ISessionStateService>();
        CreateNavigationService(new FrameFacadeAdapter(frame), sessionStateService);
    }

    protected override UIElement CreateShell(Frame rootFrame)
    {
        var shell = Container.Resolve<ShellPage>();
        shell.SetRootFrame(rootFrame);
        return shell;
    }
}

Я хочу показать SignInPage перед показом ShellPage , поэтому я создал SignInPage в папке Views и создал SignInPageViewModel в папке ViewModels .

Я попытался изменить OnLaunchApplicationAsync на:

protected override async Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
    {
        await LaunchApplicationAsync("SignIn", null);
    }

И удалили:

protected override UIElement CreateShell(Frame rootFrame)
    {
        var shell = Container.Resolve<ShellPage>();
        shell.SetRootFrame(rootFrame);
        return shell;
    }

Теперь моей стартовой страницей приложения является моя SignInPage , у меня есть LogInButton на этой странице, и я привязал команду к моей команде делегата viewmodel, но мне не удалось найти мою модель просмотра (ViewModelLocator .AutoWireViewModel = "True"), поэтому я добавил это в свой App.xaml.cs:

protected override void ConfigureViewModelLocator()
    {
        base.ConfigureViewModelLocator();

        ViewModelLocationProvider.Register<SignInPage, ViewModels.SignInPageViewModel>();
    }

ВОПРОС 1: Почему он не может найти мою модель просмотра, даже если она имеет то же пространство имен, что и автоматически созданные страницы?

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

Вопрос 2: Как я могу инициализировать ShellPage при навигации?

1
NicoTing 10 Окт 2019 в 04:58

1 ответ

Лучший ответ

Проблема может быть в вашем именовании.

Измените SignInPageViewModel на SignInViewModel.

protected override async Task OnInitializeAsync(IActivatedEventArgs args)
{
    await base.OnInitializeAsync(args);

    //We are remapping the default ViewNamePage and ViewNamePageViewModel naming to ViewNamePage and ViewNameViewModel to
    //gain better code reuse with other frameworks and pages within Windows Template Studio
    ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
    {
        var viewModelTypeName = string.Format(CultureInfo.InvariantCulture, "App1.ViewModels.{0}ViewModel, App1", viewType.Name.Substring(0, viewType.Name.Length - 4));
        return Type.GetType(viewModelTypeName);
    });
}

Обратите внимание на эту функцию, которая используется для регистрации ViewModel текущей страницы. Согласно соответствующему соглашению об именах, если имя страницы - {name}Page.xaml, то ViewModel - это {name}ViewModel.cs.


Обновить

Как я могу инициализировать ShellPage при навигации?

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

Если вы настаиваете, я предлагаю здесь метод, но он не будет правильно сохранять session state при закрытии программного обеспечения.

App.xaml.cs

public static App Instance;
public App()
{
    InitializeComponent();
    Instance = this;
}

SignInPage.xaml.cs

Прослушайте событие SignInButton_Click в xaml

private void SignInButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
    var rootFrame = Window.Current.Content as Frame;
    var frame = new Frame();
    App.Instance.SetNavigationFrame(frame);
    rootFrame.Navigate(typeof(ShellPage), frame);
}

ShellPage.xaml.cs

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if(e.Parameter is Frame frame)
    {
        SetRootFrame(frame);
        frame.Navigate(typeof(MainPage));
    }
}

С уважением.

1
Richard Zhang - MSFT 10 Окт 2019 в 07:13