"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.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。 CarouselViewControl
在 x: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);
}
摘要
综上所述,我们可以说:
PageA/PageAViewModel
在 PageB/PageBViewModel
上传输 ViewModelC
,后者接收 ViewModelC
作为 "navigation parameter" 方法 OnNavigatingTo
(最初在构造函数 PageBViewModel
ViewModelC
未在 PageBViewModel
中定义为 public 属性 PageBViewModel
最初初始化并在 OnNavigatingTo
方法中)。为此,PageB/PageBViewModel
初始构建
没有 ViewModelС
- 分别
PageB/PageBViewModel
→CarouselViewControler
→
ContentView x:Name:"CW2"
→ CustomControl
在初始初始化时收到一个空的 CustomControlTagsCollection
并且标签云不会
- 当
PageB/PageBViewModel
收到ViewModelС
时,沿着路径PageB/PageBViewModel
→CarouselViewController
->ContentView x:Name="CW2"
→CustomControl
收到传输的ViewModelС
,它执行 propertyChanged BindableProperty CustomViewModelProperty
,更新绑定并调用 panel.CreateStackPanelAsync ()
方法,用标签填充集合。从某种意义上说,这个"late binding".
如有任何帮助,我将不胜感激。
我为 Google 翻译道歉。
你们所有人(我们 :))的好代码!
您好!
我在使用 Prism 时解决了我的问题:
我把逻辑模型ViewModelC
换成ServiceC
,同时创建了IServiceC
和ServiceC
,注册到App.xaml.cs
:
containerRegistry.Register<IServiceC, ServiceC>();
ViewModelC 的所有工作逻辑都转移到了 ServiceC
。
使用 ServiceC
数据的感兴趣的 ViewModels 实现了它:
//Declaration
private IServiceC _serviceC;
//Initialization
public ViewModelB(ServiceC serviceC)
{
__serviceC = serviceC;
}</pre>
在 ViewModels 中,通过 xaml 绑定需要 ServiceC
,实现方式如下(不确定这在安全方面是否正确):
//Declaration
private IServiceC _serviceC;
public IServiceC ServiceC
{
get => _serviceC;
set => SetProperty(ref _serviceC, value);
}
//Initialization
public ViewModelB(ServiceC serviceC)
{
ServiceC = serviceC;
}
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);
}
- 退出视图模型时,实现了 Destroy 方法(为了避免内存泄漏):
public override void Destroy()
{
base.Destroy();
this.ServiceC = null;
}
结果 - 在模拟器和真实环境中一切正常
设备.
调查结果:
我意识到,在使用 Prism 并设计与第三方基本实体的视图/视图模型数据交换逻辑时,没有必要尝试通过 classes 来实现这些实体在视图模型 (MyClass myClass = new MyClass () {}
) 中声明的,然后在视图模型之间传递此 class 的链接或克隆 - 这会导致混淆并可能在其中一个阶段丢失数据(及时欠载)。
如果我对 Prism 中服务的安全性和性能的进一步研究证实了稳定和资源节约工作的假设,我推荐这种方式。
如果您对此事有任何建议、意见和建议,我将不胜感激。
谢谢大家!
你好! 我下面给出的代码在 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.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。 CarouselViewControl
在 x: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);
}
摘要
综上所述,我们可以说:
PageA/PageAViewModel
在PageB/PageBViewModel
上传输ViewModelC
,后者接收ViewModelC
作为 "navigation parameter" 方法OnNavigatingTo
(最初在构造函数PageBViewModel
ViewModelC
未在PageBViewModel
中定义为 public 属性PageBViewModel
最初初始化并在OnNavigatingTo
方法中)。为此,PageB/PageBViewModel
初始构建 没有ViewModelС
- 分别
PageB/PageBViewModel
→CarouselViewControler
→ContentView x:Name:"CW2"
→CustomControl
在初始初始化时收到一个空的CustomControlTagsCollection
并且标签云不会 - 当
PageB/PageBViewModel
收到ViewModelС
时,沿着路径PageB/PageBViewModel
→CarouselViewController
->ContentView x:Name="CW2"
→CustomControl
收到传输的ViewModelС
,它执行propertyChanged BindableProperty CustomViewModelProperty
,更新绑定并调用panel.CreateStackPanelAsync ()
方法,用标签填充集合。从某种意义上说,这个"late binding".
如有任何帮助,我将不胜感激。
我为 Google 翻译道歉。
你们所有人(我们 :))的好代码!
您好!
我在使用 Prism 时解决了我的问题:
我把逻辑模型
ViewModelC
换成ServiceC
,同时创建了IServiceC
和ServiceC
,注册到App.xaml.cs
:containerRegistry.Register<IServiceC, ServiceC>();
ViewModelC 的所有工作逻辑都转移到了
ServiceC
。使用
ServiceC
数据的感兴趣的 ViewModels 实现了它://Declaration private IServiceC _serviceC; //Initialization public ViewModelB(ServiceC serviceC) { __serviceC = serviceC; }</pre>
在 ViewModels 中,通过 xaml 绑定需要
ServiceC
,实现方式如下(不确定这在安全方面是否正确)://Declaration private IServiceC _serviceC; public IServiceC ServiceC { get => _serviceC; set => SetProperty(ref _serviceC, value); } //Initialization public ViewModelB(ServiceC serviceC) { ServiceC = serviceC; }
CustomControl 中的 BindableProperty:
public ServiceC MyServiceC { get => (ServiceC)GetValue(ServiceCProperty ); set => SetValue(serviceCProperty, value); }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(); } }); });
- 退出视图模型时,实现了 Destroy 方法(为了避免内存泄漏):
public override void Destroy() { base.Destroy(); this.ServiceC = null; }
- 退出视图模型时,实现了 Destroy 方法(为了避免内存泄漏):
结果 - 在模拟器和真实环境中一切正常 设备.
调查结果:
我意识到,在使用 Prism 并设计与第三方基本实体的视图/视图模型数据交换逻辑时,没有必要尝试通过 classes 来实现这些实体在视图模型 (
MyClass myClass = new MyClass () {}
) 中声明的,然后在视图模型之间传递此 class 的链接或克隆 - 这会导致混淆并可能在其中一个阶段丢失数据(及时欠载)。如果我对 Prism 中服务的安全性和性能的进一步研究证实了稳定和资源节约工作的假设,我推荐这种方式。
如果您对此事有任何建议、意见和建议,我将不胜感激。
谢谢大家!