首页 > 解决方案 > “后期绑定”期间的数据在真机上不显示(Xamarin.Forms + Prism + CarouselViewController)

问题描述

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

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


1.有PageA/PageAViewModel(linked BindableBase(Prism))、PageB/PageBViewModel(linked BindableBase(Prism))和logical 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.ViewModelC作为属性存在,而在PageBViewModel构造函数中不声明,主要在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,除其他外,有一个标签云 - 它从 中生成的按钮的集合ObservableCollection CustomControlTagsCollection,位于ViewModelC(在控制中它是 BindablePropertyCustomViewModel)。

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

        }

概括

总结一下,我们可以这么说:


我将不胜感激任何帮助。

我为谷歌翻译道歉。

给你们所有人(我们 :))好的和干净的代码!

标签: xamarinxamarin.formsxamarin.iosprism

解决方案


你好!

我在使用 Prism 的背景下解决了我的问题:

  1. 我用 替换了逻辑模型ViewModelCServiceC同时我创建IServiceCServiceC注册了它们App.xaml.cs

    containerRegistry.Register<IServiceC, ServiceC>();

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

  3. 感兴趣的处理ServiceC数据的 ViewModel 实现了它:

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

  4. 在 ViewModels 中,ServiceC需要通过 xaml 进行绑定,这样实现它(不确定这在安全性方面是否正确):

    //宣言
    私有 IServiceC _serviceC;
    公共 IServiceC 服务C
    {
       得到 => _serviceC;
       设置 => 设置属性(参考 _serviceC,值);
    }
    //初始化
    公共 ViewModelB(ServiceC serviceC)
    {
        服务 C = 服务 C;
    }

  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;
    
    
        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 并设计与第三方基本实体的 view/viewmodels 数据交换逻辑时,没有必要尝试通过在 viewmodels ( MyClass myClass = new MyClass () {}) 中声明的类来实现这些实体,然后传递链接或克隆视图模型之间的此类 - 这会导致其中一个阶段的数据混乱和可能的丢失(及时欠载)。

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

  3. 我将不胜感激有关此事的任何建议、意见和建议。

  4. 谢谢你们!


推荐阅读