Здравствуйте! Приведенный ниже код отлично работает на симуляторе IOS, но не работает на реальном устройстве (Iphone 6S Plus) - коллекция тегов (что это в моем случае - вы смотритедалее) не заполняется.(Xamarin.Forms, проект IOS, Prism, CarouselViewController)
Я заранее прошу прощения за большой объем кода - это часть большой разрабатываемой программы, я сразу решил привести все необходимые листинги.
1. Существуют 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
, кроме всего прочего, имеющий облако тегов - коллекцияn кнопок, которые он генерирует из ObservableCollection CustomControlTagsCollection
, расположенного в 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
передает ViewModelC
на PageB/PageBViewModel
, который получает ViewModelC
в качестве «параметра навигации» метода OnNavigatingTo
(первоначально в конструкторе PageBViewModel
ViewModelC
не определено в PageBViewModel
как публичное свойство 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 ()
, который заполняет коллекцию тегами.В некотором смысле это «поздняя привязка».
Буду признателен за любую помощь.
Прошу прощения за переводчик Google.
Хороший и чистый кодвсем вам (нам:))!