"late binding"期间的数据在真机上不显示(Xamarin.Forms + Prism + CarouselViewController)

Data during "late binding" is not displayed on the real device (Xamarin.Forms + Prism + CarouselViewController)

你好! 我下面给出的代码在 IOS 模拟器上工作正常,但在真实设备上不起作用(Iphone 6S Plus) - 标签集合(在我的情况下是什么 - 你看得更远)没有填写。 (Xamarin.Forms、IOS 项目、Prism、CarouselViewController)

我提前为大量代码道歉 - 这是正在开发的大型程序的一部分,我立即决定带来所有必要的列表。


1.There 是 PageA/PageAViewModel(链接的 BindableBase (Prism)),PageB/PageBViewModel(链接的 BindableBase (Prism))和逻辑 ViewModelС。在 PageAViewModel 上创建一个逻辑 ViewModelС 并作为导航参数传输到 PageBViewModel

async Task GoPageB()
{
    var navigationParams = new NavigationParameters();
    navigationParams.Add("ViewModelС", ViewModelС);
    await NavigationService.NavigateAsync(new System.Uri("http://.../PageB",
                    System.UriKind.Absolute), navigationParams);
}

2。在执行代码的过程中,由PageB收集,然后是PageBViewModel收集,然后计算出PageB接收导航参数的方法,其中PageBViewModel接收ViewModelC:

public override void OnNavigatingTo(INavigationParameters parameters)
{
    var modelInParameters = parameters["ViewModelC"] as ViewModelC;
    MyViewModelC = modelInParameters;
}

3.ViewModelCPageBViewModel中作为属性,而在构造函数中没有声明,主要是在OnNavigatingTo方法中获取和赋值

public ViewModelC MyViewModelC
        {
            get => _myViewModelC;
            set => SetProperty(ref _myViewModelC, value);
        }

4.PageB/PageBViewModel 实际上是建立在 CarouselViewControler (https://github.com/alexrainman/CarouselView) 之上的入职培训。在 XAML 中,它看起来像这样:

 <ContentPage.Content>
        <abstractions:CarouselViewControl x:Name="OnBrdngPg_CrslVwCntrl"
                                          VerticalOptions="FillAndExpand"
                                          HorizontalOptions="FillAndExpand"
                                          Orientation="Horizontal"
                                          InterPageSpacing="0"
                                          IsSwipeEnabled="True"
                                          IndicatorsTintColor="{StaticResource ClrGreyLight}"
                                          CurrentPageIndicatorTintColor="{StaticResource ClrLightorange}"
                                          AnimateTransition="True"
                                          Position="0"
                                          ShowIndicators="True"
                                          ShowArrows="False">
            <abstractions:CarouselViewControl.ItemsSource>
                <x:Array Type="{x:Type ContentView}">
                    <ContentView x:Name="CW1"/>
                    <ContentView x:Name="CW2"/>
                    <ContentView x:Name="CW3"/>
                    <ContentView x:Name="CW4"/>
                    <ContentView x:Name="CW5"/>
                </x:Array>
            </abstractions:CarouselViewControl.ItemsSource>
        </abstractions:CarouselViewControl>
 </ContentPage.Content>

5。 CarouselViewControlx:Array 中包括五个 ContentViews。每个 ContentView 都有五个视图变体(Statecontainer 的实现 - 一页的五个状态 Normal, Loading, Error, NoInternet, NoData - 页面状态设置在代码根据程序逻辑,在XAML中Statecontainer订阅了状态变化并显示对应的ContentView:

<ContentView x:Name="CW2"
                Style="{DynamicResource ContentViewBoardingStyle}"
                BackgroundColor="{StaticResource ClrGeneralwhite}">
                <ContentView.Content>
                        <Grid BackgroundColor="Transparent">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>
                            <Grid.Children>
                                <StackLayout Grid.Row="0"
                                              Style="{StaticResource StLt_BaseStyle}">
                                    <StackLayout.Children>
                                        <Images:ImageFit Source="{Binding HeaderImageSource}"/>
                                    </StackLayout.Children>
                                </StackLayout>
                                <stateContainer:StateContainer State="{Binding OnBoardingInState}"
                                                               Grid.Row="1"
                                                               Style="{StaticResource StateContainerNormalStateStyle}"
                                                               BackgroundColor="{StaticResource ClrGeneralwhite}">
                                    <stateContainer:StateCondition State="Normal">
                                        <stateContainer:StateCondition.Content>
                                            <StackLayout x:Name="OnbdngPg_RootStack2"
                                                         Orientation="Vertical"
                                                         Spacing="12">
                                                <StackLayout.Children>
                                                    <StackLayout Padding="0,15,0,10">
                                                        <StackLayout.Children>
                                                            <labels:LblLvl2 Text="{markupExtension:Translate OnBrdPg_Pg2_HdrTxt}"
                                                                    TextColor="{StaticResource ClrGeneraldark}"
                                                                    HorizontalTextAlignment="Start"/>
                                                        </StackLayout.Children>
                                                    </StackLayout>
                                                    <StackLayout>
                                                        <StackLayout.Children>
                                                            <custom:GdyStackPanel x:Name="CustomControl"
                                                                                  CustomViewModel="{Binding ViewModelC, Mode=OneTime}"/>
                                                        </StackLayout.Children>
                                                    </StackLayout>
                                                </StackLayout.Children>
                                            </StackLayout>
                                        </stateContainer:StateCondition.Content>
                                    </stateContainer:StateCondition>
                                    <stateContainer:StateCondition State="Error"/>
                                    <stateContainer:StateCondition State="Loading"/>
                                    <stateContainer:StateCondition State="NoInternet"/>
                                    <stateContainer:StateCondition State="NoData"/>
                                </stateContainer:StateContainer>
                            </Grid.Children>
                        </Grid>
            </ContentView.Content>
</ContentView>

6。正如您在 CW2 上看到的那样,有一个 CustomControl - 这是一个自定义 Grid,除此之外,还有一个标签云 - 它从 [= 生成的按钮集合42=],位于ViewModelC(在控件中是BindableProperty CustomViewModel)。

public static readonly BindableProperty CustomViewModelProperty = BindableProperty.Create(
            nameof(CustomViewModel),
            typeof(ViewModelC),
            typeof(CustomControl),
            null,
            BindingMode.TwoWay,
            propertyChanged: (bindable, oldValue, newValue) =>
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    var panel = bindable as CustomControl;
                    var oldbinding = oldValue as ViewModelC;
                    var newbinding = newValue as ViewModelC;

                    if (oldbinding == null)
                    {
                        panel.CustomViewModel = newbinding;

                        panel.ButtonNewTag.BindingContext = newbinding;
                        panel.EntryNewTag.BindingContext = newbinding;
                    }
                 // This method collects the tag cloud from the collection.
                    panel.CreateStackPanelAsync();
                });
            });


        public ViewModelC CustomViewModel
        {
            get => (ViewModelC)GetValue(CustomViewModelProperty);
            set => SetValue(CustomViewModelProperty, value);

        }

摘要

综上所述,我们可以说:


如有任何帮助,我将不胜感激。

我为 Google 翻译道歉。

你们所有人(我们 :))的好代码!

您好!

我在使用 Prism 时解决了我的问题:

  1. 我把逻辑模型ViewModelC换成ServiceC,同时创建了IServiceCServiceC,注册到App.xaml.cs:

    containerRegistry.Register<IServiceC, ServiceC>();

  2. ViewModelC 的所有工作逻辑都转移到了 ServiceC

  3. 使用 ServiceC 数据的感兴趣的 ViewModels 实现了它:

    //Declaration
    private IServiceC _serviceC;
    //Initialization 
    public ViewModelB(ServiceC serviceC)
    {
        __serviceC =  serviceC;
    }</pre>

  4. 在 ViewModels 中,通过 xaml 绑定需要 ServiceC,实现方式如下(不确定这在安全方面是否正确):

    //Declaration
    private IServiceC _serviceC;
    public IServiceC  ServiceC
    {
       get => _serviceC;
       set => SetProperty(ref _serviceC, value);
    }
    //Initialization 
    public ViewModelB(ServiceC serviceC)
    {
        ServiceC =  serviceC;
    }

  5. CustomControl 中的 BindableProperty:

    public static readonly BindableProperty serviceCProperty = BindableProperty.Create(
        nameof(MyServiceC),
        typeof(ServiceC),
        typeof(CustomControl),
        null,
        BindingMode.OneTime,
        propertyChanged: (bindable, oldValue, newValue) =>
        {
            var panel = bindable as CustomControl;
    
    <pre><code>    Device.BeginInvokeOnMainThread(() =>
        {
            var oldbinding = oldValue as ServiceC;
            var newbinding = newValue as ServiceC;
    
            if (oldbinding == null)
            {
                panel.MyServiceC = newbinding;
    
                panel.ButtonNewTag.BindingContext = newbinding;
                panel.EntryNewTag.BindingContext = newbinding;
    
                //This is where the panel is filled with tags
                panel.CreateStackPanelAsync();
            }
        });
    });
    
    public ServiceC MyServiceC { get => (ServiceC)GetValue(ServiceCProperty ); set => SetValue(serviceCProperty, value); }
    1. 退出视图模型时,实现了 Destroy 方法(为了避免内存泄漏):
       public override void Destroy()
      {
      base.Destroy();
      this.ServiceC = null;
      }
      
  6. 结果 - 在模拟器和真实环境中一切正常 设备.

调查结果

  1. 我意识到,在使用 Prism 并设计与第三方基本实体的视图/视图模型数据交换逻辑时,没有必要尝试通过 classes 来实现这些实体在视图模型 (MyClass myClass = new MyClass () {}) 中声明的,然后在视图模型之间传递此 class 的链接或克隆 - 这会导致混淆并可能在其中一个阶段丢失数据(及时欠载)。

  2. 如果我对 Prism 中服务的安全性和性能的进一步研究证实了稳定和资源节约工作的假设,我推荐这种方式。

  3. 如果您对此事有任何建议、意见和建议,我将不胜感激。

  4. 谢谢大家!