【问题标题】:Xamarin Forms shared ControlTemplate for ContentPage and CarouselPageXamarin Forms 为 ContentPage 和 CarouselPage 共享 ControlTemplate
【发布时间】:2017-10-13 22:15:20
【问题描述】:

我一直在尝试为独立的ContentPage 以及CarouselPage 中的ContentPage 重用控制模板...

主要问题是CarouselPage 不支持ControlTemplate 属性。因此,我不得不在CarouselPageDataTemplate 中插入ContentPage。这个ContentPage 然后可以分配ControlTemplate,但我遇到了BindingContext 不是ViewModel 的根的问题。

我也会尝试用代码解释问题:

我已经创建了如下所示的模板。

<!-- Loader view template -->
<ControlTemplate x:Key="LoaderViewTemplate">
    <AbsoluteLayout Padding="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">

        <!-- Content -->
        <ContentPresenter AbsoluteLayout.LayoutBounds="0, 0, 1, 1" AbsoluteLayout.LayoutFlags="All" />

        <!-- Loader -->
        <BoxView IsVisible="{TemplateBinding BindingContext.IsBusy}" BackgroundColor="Green" Opacity="0.5" AbsoluteLayout.LayoutBounds="0, 0, 1, 1" AbsoluteLayout.LayoutFlags="All" />
        <StackLayout IsVisible="{TemplateBinding BindingContext.IsBusy}" Padding="6" BackgroundColor="Gray" Orientation="Horizontal" AbsoluteLayout.LayoutBounds="0.5, 0.5, -1, -1" AbsoluteLayout.LayoutFlags="PositionProportional">
            <ActivityIndicator Color="White" IsRunning="{TemplateBinding BindingContext.IsBusy}" VerticalOptions="Center" WidthRequest="20" HeightRequest="20" />
            <Label TextColor="White" Text="Loading..." VerticalOptions="Center" />
        </StackLayout>

    </AbsoluteLayout>
</ControlTemplate>

对于如下所示的ContentPage,模板正常工作

<ContentPage ...
             ControlTemplate="{StaticResource LoaderViewTemplate}">

    <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
        ...
    </StackLayout>

</ContentPage>

但它在CarouselPage不起作用,如下所示。

<CarouselPage ...
              ItemsSource="{Binding Tournament.Rounds}">

    <CarouselPage.ItemTemplate>
        <DataTemplate>
            <ContentPage ControlTemplate="{StaticResource LoaderViewTemplate}">
                ...
            </ContentPage>
        </DataTemplate>
    </CarouselPage.ItemTemplate>

</CarouselPage>

CarouselPage 中的BindingContext 成为Tournament.Rounds 集合中的TournamentRoundModel

有没有人知道我如何在独立的ContentPage 和嵌套的ContentPage 中到达ViewModel 的根?

亲切的问候, 乔普·米德尔坎普

【问题讨论】:

    标签: xamarin xamarin.forms controltemplate controltemplates control-template


    【解决方案1】:

    首先,如果您需要CarousalPage 中的每个ContentPage 能够引用根视图模型,同时为ControlTemplate 的绑定提供相同的内容。

    最简单的方法是扩展 ContentPage 以支持可绑定属性来保存此引用(到根视图模型)。

    public class ExContentPage : ContentPage
    {
        public static readonly BindableProperty RootViewModelProperty =
            BindableProperty.Create(
                "RootViewModel", typeof(object), typeof(ExContentPage),
                defaultValue: default(object));
    
        public object RootViewModel
        {
            get { return (object)GetValue(RootViewModelProperty); }
            set { SetValue(RootViewModelProperty, value); }
        }
    }
    

    然后您可以将共享控件模板更新为:

    <!-- Loader view template -->
    <ControlTemplate x:Key="LoaderViewTemplate">
        <AbsoluteLayout Padding = "0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
    
            <!-- Content -->
            <ContentPresenter .. />
    
            < !--Loader-- >
            <BoxView IsVisible= "{TemplateBinding RootViewModel.IsBusy}" BackgroundColor= "Green" .. />
    
            <StackLayout IsVisible= "{TemplateBinding RootViewModel.IsBusy}" .. >
                <ActivityIndicator Color= "White" IsRunning= "{TemplateBinding RootViewModel.IsBusy}"  />
                <Label TextColor= "White" Text= "Loading..." VerticalOptions= "Center" />
            </StackLayout>
        </AbsoluteLayout>
    </ControlTemplate>
    

    示例用法如下所示:

    <local:ExContentPage ...
            xmlns:local="clr-namespace:CustomNamespace"     
            RootViewModel="{Binding}"
             ControlTemplate="{StaticResource LoaderViewTemplate}">
    
        <StackLayout HorizontalOptions = "Center" VerticalOptions="Center">
            ...
        </StackLayout>
    </local:ExContentPage>
    

    和,

    <CarouselPage...
                 x:Name="Parent" 
                 ItemsSource="{Binding Tournament.Rounds}">
        <CarouselPage.ItemTemplate>
            <DataTemplate>
                <local:ExContentPage
                    ControlTemplate = "{StaticResource LoaderViewTemplate}"
                    RootViewModel="{Binding BindingContext, Source={x:Reference Parent}}">
                    ...
                </ContentPage>
            </DataTemplate>
        </CarouselPage.ItemTemplate>
    </CarouselPage>
    

    此外,如果IsBusy 是您需要在ControlTemplate 中引用的唯一属性 - 您可以在扩展内容页面中创建IsBusy 可绑定属性;而不是RootViewModel

    【讨论】:

      【解决方案2】:

      如果你正在做任何与轮播相关的事情,我建议你使用这个 nuget 包 https://github.com/alexrainman/CarouselView 而不是默认的轮播页面。

      【讨论】:

      • 我刚刚从 CarouselView 切换到 CarouselPage 因为 CarouselView 有问题。当在除第一页之外的任何页面上按下条目时,CarouselView 控件正在远离活动视图...不可行并确认预发布 NuGet 状态。
      • @JopMiddelkamp 是的。我完全同意你的看法。 xaml 创建模板时 CarouselView 不支持 listview。这真有趣。正如你所说,它正在远离活动视图
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-25
      • 2020-08-02
      • 2015-08-17
      • 1970-01-01
      • 1970-01-01
      • 2018-06-30
      • 1970-01-01
      相关资源
      最近更新 更多