Как создать отдельную модель представления для представления содержимого в формах Xamarin, имеющих призму? - PullRequest
0 голосов
/ 20 ноября 2018

Постановка проблемы Я хочу создать пользовательский элемент управления для просмотра контента, имеющий собственную модель представления, которую можно использовать на нескольких страницах контента.

Проблема в нижеприведенной реализации. Я расширил свой App.xaml.cs, как указано ниже.Но как только навигация работает со страницы контента, имеющей пользовательский элемент управления контентом, но если я снова перейду на эту страницу, навигация не будет работать.Просто чтобы добавить к этому, view.Parent также оказывается нулевым в приведенном ниже коде.

Пожалуйста, помогите.

using OEP.Views;
using Prism;
using Prism.Common;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Navigation;
using Prism.Unity;
using Unity.Resolution;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace OEP
{
    public partial class App : PrismApplication
    {
        public App() : this(null) { }

        public App(IPlatformInitializer initializer) : base(initializer) { }

        protected override async void OnInitialized()
        {
            InitializeComponent();
            //await NavigationService.NavigateAsync("NewOrderPage");
            await NavigationService.NavigateAsync("LoginPage");
            //await NavigationService.NavigateAsync("HomePage");
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<LoginPage>();
            containerRegistry.RegisterForNavigation<ForgotPasswordPage>();
            containerRegistry.RegisterForNavigation<HomePage>();
            containerRegistry.RegisterForNavigation<CustomerDetailsPage>();
            containerRegistry.RegisterForNavigation<NewOrderPage>();
            //Container.Resolve<HomePageCustomersUserControl>("Customers");
            //containerRegistry.Register<HomePageCustomersUserControl, HomePageCustomersUserControlViewModel>();
            //ViewModelLocationProvider.Register<HomePageCustomersUserControl>(() => Container.Resolve<HomePageCustomersUserControlViewModel>());
        }

        protected override void ConfigureViewModelLocator()
        {
            ViewModelLocationProvider.SetDefaultViewModelFactory((view, type) =>
            {
                Page page = null;
                switch (view)
                {
                    case Page page1:
                        page = page1;
                        break;
                    case Element customView:
                        page = GetPageFromElement(customView);
                        // Existing parameter with the Page
                        break;
                }

                var navService = CreateNavigationService(page);
                ParameterOverrides overrides = new ParameterOverrides
                {
                        { "navigationService", navService }
                };
                return Container.GetContainer().Resolve(type, type.GetType().Name, overrides);

            });
        }

        // Currently exists
        protected INavigationService CreateNavigationService(Page page)
        {
            var navigationService = NavigationService;
            ((IPageAware)navigationService).Page = page;
            return navigationService;
        }

        protected INavigationService CreateNavigationService(object view)
        {
            switch (view)
            {
                case Page page:
                    return CreateNavigationService(page);
                case Element element:
                    var parentPage = GetPageFromElement(element);
                    if (parentPage == null)
                    {
                        return null;
                    }
                    return CreateNavigationService(parentPage);
                default:
                    return null;
            }
        }

        private Page GetPageFromElement(Element view)
        {
            switch (view.Parent)
            {
                case Page page:
                    return page;
                case null:
                    return null;
                default:
                    return GetPageFromElement(view.Parent);
            }
        }

        protected override void OnStart()
        {
            // Handle when your app starts
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 25 апреля 2019

Я думаю, что нет необходимости определять новые ViewModel для ContentView.Вам просто нужно использовать свойство AutowirePartialView в Page, где вы используете ContentView.Вот так

<DataTemplate>
    <ViewCell>
        <local:CardViewTemplatePage prism:ViewModelLocator.AutowirePartialView="true"/>
    </ViewCell>
</DataTemplate>

Ваш ContentView должен связывать поля вот так

 <StackLayout HorizontalOptions="Fill" VerticalOptions="Start">
    <Label TextColor="Denim" Text="{Binding Title}" />
    <Label TextColor="DimGray" Text="{Binding Description}" />
</StackLayout>
0 голосов
/ 21 ноября 2018

Это поддерживается в Prism 7.1.Следующее взято непосредственно из Призматических тестов.Если вы придерживаетесь соглашения об именах, вам на самом деле ничего не нужно регистрировать, вам просто нужно установить ViewModelLocator.AutowirePartialView со ссылкой на родительскую страницу.

<ContentView
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="Prism.DI.Forms.Tests.Mocks.Views.PartialView">
    <StackLayout>
        <Label Text="{Binding SomeText}" />
        <Button Command="{Binding NavigateCommand}"
                x:Name="navigateButton" />
    </StackLayout>
</ContentView>

<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:Prism.DI.Forms.Tests.Mocks.Views"
    xmlns:prism="clr-namespace:Prism.Ioc;assembly=Prism.Forms"
    xmlns:mvvm="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
    xmlns:converters="using:Prism.Forms.Tests.Mocks.Converters"
    Title="{Binding Title}"
    x:Name="xamlViewMock"
    x:Class="Prism.DI.Forms.Tests.Mocks.Views.XamlViewMock">
    <ContentPage.Resources>
        <ResourceDictionary>
            <prism:ContainerProvider x:TypeArguments="converters:MockValueConverter" x:Key="mockValueConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout>
        <local:PartialView mvvm:ViewModelLocator.AutowirePartialView="{x:Reference xamlViewMock}" />
        <Entry x:Name="testEntry"
        Text="{Binding Test,Converter={StaticResource mockValueConverter}}" />
    </StackLayout>

</ContentPage>

В случае, если вам нужно следовать какой-то пользовательской схеме именования, вам просто нужно позвонить:

ViewModelLocationProvider.Register<MyView, SomeViewModel>();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...