首页 > 解决方案 > 从 ContentView(子视图)获取属性值到 ContentPage(父)

问题描述

作为一个经验不足的Xamarin开发人员,我试图从ContentView我的父页面 () 中的子页面 () 中检索属性值ContentPage。我可以找到一些如何从父页面获取/设置值到子页面的示例,但反之则不然。

更多细节:

在我的ContentPage我有一个CarouselView,这CarouselView有一个DataTemplate包含一个ContentView,这个 ContentView 里面还有一个 CarouselView,它有 2 层/2 个垂直轮播项目。

当 CarouselView 在 ContentView(子页面)内的位置,改变位置到第二项时,IndicatorView在父页面中的 应该设置为invisible

我对使用 a 的经验并不多,BindableProperty但我认为这是要走的路。我现在设置如下:

父页面/内容页面:

<local:ExtendedCarouselView
    x:Name="carousel"
    HorizontalScrollBarVisibility="Never"
    IndicatorView="activityIndicatorView"
    IsScrollAnimated="False"
    ItemsSource="{Binding ActivityData}"
    Position="{Binding Position, Mode=TwoWay}"
    VerticalOptions="FillAndExpand">
    <local:ExtendedCarouselView.ItemTemplate>
        <DataTemplate>
            <Frame Style="{StaticResource CarouselWorkaround}">
                <local:PCSActivityOverviewTemplate x:Name="testy" />
            </Frame>
        </DataTemplate>
    </local:ExtendedCarouselView.ItemTemplate>
</local:ExtendedCarouselView>

<IndicatorView
    x:Name="activityIndicatorView"
    Padding="0,0,0,30"
    IndicatorColor="{DynamicResource TranslucidBlack}"
    IsVisible="{Binding InnerCarouselViewPosition, Converter={StaticResource IndicatorVisibilityConverter}, Mode=TwoWay}"
    SelectedIndicatorColor="{DynamicResource BaseTextColor}"
    VerticalOptions="Start" />

子页面/内容视图(XAML):

<ContentView.Content>

    <CarouselView
        x:Name="carousel"

        ItemsSource="{Binding ., Converter={StaticResource OneToManyConverter}, ConverterParameter=2}"
        VerticalOptions="FillAndExpand"
        VerticalScrollBarVisibility="Never"
        PositionChanged="carousel_PositionChanged"> <!-- The event which should change the property 'InnerCarouselViewPosition' -->

        <CarouselView.ItemTemplate>
            <grial:IntMemberTemplateSelector MemberName="Position">
                <grial:IntMemberTemplateSelector.Items>

                    <!--  CAROUSEL'S PAGE 0  -->
                    <grial:IntMemberTemplateSelectorItem Value="0">
                        <DataTemplate>

                            <!-- Other elements... -->

                        </DataTemplate>
                    </grial:IntMemberTemplateSelectorItem>


                    <!--  CAROUSEL'S PAGE 1  -->
                    <grial:IntMemberTemplateSelectorItem Value="1">
                        <DataTemplate>

                            <!-- Other elements... -->

                        </DataTemplate>
                    </grial:IntMemberTemplateSelectorItem>

                </grial:IntMemberTemplateSelector.Items>
            </grial:IntMemberTemplateSelector>
        </CarouselView.ItemTemplate>

    </CarouselView>

</ContentView.Content>

内容视图(C#/.cs):

public partial class PCSActivityOverviewTemplate : ContentView
{
    public static BindableProperty CurrentChildCarouselViewLocationProperty =
       BindableProperty.Create(
           nameof(CurrentChildCarouselViewLocationProperty),
           typeof(int),
           typeof(CarouselView),
           defaultValue: 1);

    public int CurrentChildCarouselViewLocation
    {
        get { return (int)GetValue(CurrentChildCarouselViewLocationProperty); }
        set { SetValue(CurrentChildCarouselViewLocationProperty, value); }
    }

    private void carousel_PositionChanged(object sender, PositionChangedEventArgs e)
    {
        CarouselView _carouselView = (CarouselView)sender;
        CurrentChildCarouselViewLocationProperty = _carouselView.Position;  
    }

    ... code omitted

}

当内部轮播视图位置发生变化时,bindable property应设置,此属性应在父页面中使用转换器设置指示器视图可见/不可见(位置 0 = 可见,位置 1 = 不可见)。对于某些人来说,可能是一个非常明显的原因,上面的方法不起作用。

可见性转换器:

public class CarouselIndicatorVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (int)value != 1; 
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value ? 0 : 1;
    }
}

更新*

我还尝试在我的 ViewModel 中使用绑定作为位置属性,虽然绑定值发生了变化,但我无法在父页面中访问它,没有任何反应,转换器没有被触发),我删除了可绑定属性。

新的内容页面 XAML(父轮播):

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    ...
    >
    <ContentPage.Resources>
        <ResourceDictionary>
            <local:CarouselIndicatorVisibilityConverter x:Key="IndicatorVisibilityConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>

    <ContentPage.Content>

        <Grid>
            
            <Grid>
               
                <local:ExtendedCarouselView
                    x:Name="carousel"
                    HorizontalScrollBarVisibility="Never"
                    IndicatorView="activityIndicatorView"
                    IsScrollAnimated="False"
                    ItemsSource="{Binding ActivityData}"
                    Position="{Binding Position, Mode=TwoWay}"
                    VerticalOptions="FillAndExpand">
                    <local:ExtendedCarouselView.ItemTemplate>
                        <DataTemplate>
                            <Frame Style="{StaticResource CarouselWorkaround}">
                                <local:PCSActivityOverviewTemplate x:Name="testy" />
                            </Frame>
                        </DataTemplate>
                    </local:ExtendedCarouselView.ItemTemplate>
                </local:ExtendedCarouselView>

                <IndicatorView
                    x:Name="activityIndicatorView"
                    Padding="0,0,0,30"
                    IndicatorColor="{DynamicResource TranslucidBlack}"
                    IsVisible="{Binding BindingContext.CurrentChildCarouselViewLocation, Source={x:Reference carousel}, Converter={StaticResource IndicatorVisibilityConverter}, Mode=TwoWay}"
                    SelectedIndicatorColor="{DynamicResource BaseTextColor}"
                    VerticalOptions="Start" />


            </Grid>
        </Grid>

    </ContentPage.Content>
</ContentPage>

子页面的 XAML:

<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
    ...
    >
    
    <ContentView.Content>

        <CarouselView
            x:Name="carousel"
            IsBounceEnabled="False"
            ItemsSource="{Binding ., Converter={StaticResource OneToManyConverter}, ConverterParameter=2}"
            Position="{Binding CurrentCarouselViewLocation}"
            PositionChanged="carousel_PositionChanged"
            VerticalOptions="FillAndExpand"
            VerticalScrollBarVisibility="Never">
            <CarouselView.ItemsLayout>
                <LinearItemsLayout
                    ItemSpacing="0"
                    Orientation="Vertical"
                    SnapPointsAlignment="Start"
                    SnapPointsType="MandatorySingle" />
            </CarouselView.ItemsLayout>

            <CarouselView.ItemTemplate>
                <grial:IntMemberTemplateSelector MemberName="Position">
                    <grial:IntMemberTemplateSelector.Items>

                        <!--  CAROUSEL'S PAGE 0  -->
                        <grial:IntMemberTemplateSelectorItem Value="0">
                            <DataTemplate>
                               
                               .. more elements omitted
                               
                            </DataTemplate>
                        </grial:IntMemberTemplateSelectorItem>

                        <!--  CAROUSEL'S PAGE 1  -->
                        <grial:IntMemberTemplateSelectorItem Value="1">
                            <DataTemplate>
                                
                                .. more elements omitted                                
                                      
                            </DataTemplate>
                        </grial:IntMemberTemplateSelectorItem>

                    </grial:IntMemberTemplateSelector.Items>
                </grial:IntMemberTemplateSelector>
            </CarouselView.ItemTemplate>

        </CarouselView>

    </ContentView.Content>
</ContentView>

视图模型

namespace PCS2.APP.ViewModels
{
    public class ActivityOverviewViewModel : ObservableObject
    {
        private List<ActivityLocation> activityData;
        private readonly IRoutingService _routingService;
        private double _screenOpacity;
        private bool _showLoadingAnimation;
        private int? _clientId;
        private int _position;
        private int _innerCarouselPosition;

        // Position of the Parent page CarouselView
        public int Position
        {
            get { return _position; }
            set { SetProperty(ref _position, value); }
        }

        // Data source for the child data
        public List<ActivityLocation> ActivityData
        {
            get { return activityData; }
            set { SetProperty(ref activityData, value); }
        }

    
        public double ScreenOpacity
        {
            get { return _screenOpacity; }
            set { SetProperty(ref _screenOpacity, value); }
        }

        public bool ShowLoadingAnimation
        {
            get { return _showLoadingAnimation; }
            set { SetProperty(ref _showLoadingAnimation, value); }
        }

        public ActivityOverviewViewModel(int? clientId = null, IRoutingService routingService = null)
            : base(listenCultureChanges: true)
        {
            _clientId = clientId;
            _routingService = routingService ?? Locator.Current.GetService<IRoutingService>();
            LoadData();
        }

        private async void LoadData()
        {
            try
            {
                ShowLoadingAnimation = true;
                ScreenOpacity = 0.1;

                // Getting the data
                var _activitiesData = await App.Database.GetActivityDataAsync(_clientId, DateTime.UtcNow);
                ActivityData = _activitiesData;

            }
            catch (Exception ex)
            {
                throw;
            }
            finally
            {
                ShowLoadingAnimation = false;
                ScreenOpacity = 1.0;
            }

        }


    }
}

标签: c#xamlxamarinxamarin.formsbindableproperty

解决方案


推荐阅读