Xamarin Forms 为 ContentPage 和 CarouselPage 共享 ControlTemplate
Xamarin Forms shared ControlTemplate for ContentPage and CarouselPage
我一直在尝试为独立 ContentPage
以及 CarouselPage
中的 ContentPage
重用控制模板...
主要问题是 CarouselPage
不支持 ControlTemplate
属性。因此,我不得不在 CarouselPage
的 DataTemplate
中插入一个 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
和 CarouselPage
嵌套 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
.
我一直在尝试为独立 ContentPage
以及 CarouselPage
中的 ContentPage
重用控制模板...
主要问题是 CarouselPage
不支持 ControlTemplate
属性。因此,我不得不在 CarouselPage
的 DataTemplate
中插入一个 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
和 CarouselPage
嵌套 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
.