Xamarin Forms 为 ContentPage 和 CarouselPage 共享 ControlTemplate

Xamarin Forms shared ControlTemplate for ContentPage and CarouselPage

我一直在尝试为独立 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

有没有人知道如何在独立 ContentPageCarouselPage 嵌套 ContentPage 中找到 ViewModel 的根?

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

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

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

最简单的方法是扩展 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.