Xamarin.FormsContentView 类是一种包含单个子元素的 Layout 类型,通常用于创建自定义、可重用的控件。 ContentView 类继承自 TemplatedView。 本文和相关示例介绍了如何基于 ContentView 类创建自定义 CardView 控件。
以下屏幕截图显示了派生自 ContentView 类的 CardView 控件:
ContentView 类定义单个属性:
- Content是一个- View对象。 此属性由- BindableProperty对象提供支持,因此它可以是数据绑定的目标。
ContentView 还从 TemplatedView 类继承属性:
- ControlTemplate是可以定义或替代控件外观的- ControlTemplate。
要详细了解 ControlTemplate 属性,请参阅使用 ControlTemplate 自定义外观。
创建自定义控件
ContentView 类本身提供的功能很少,但可用于创建自定义控件。 示例项目定义一个 CardView 控件-一个 UI 元素,用于在类似卡片的布局中显示图像、标题和说明。
创建自定义控件的过程是为了:
- 使用 Visual Studio 2019 中的 ContentView模板创建新类。
- 为新的自定义控件定义代码隐藏文件中的任何唯一属性或事件。
- 为自定义控件创建 UI。
注意
可以创建自定义控件,该控件的布局是在代码中定义的,而不是 XAML。 为简单起见,示例应用程序仅定义具有 XAML 布局的单个 CardView 类。 但是,示例应用程序包含一个 CardViewCodePage 类,该类显示在代码中使用自定义控件的过程。
创建代码隐藏属性
CardView 自定义控件定义以下属性:
- CardTitle:表示卡片上显示的标题的- string对象。
- CardDescription:表示卡片上显示的说明的- string对象。
- IconImageSource:表示卡片上显示的图像的- ImageSource对象。
- IconBackgroundColor:表示卡片上显示的图像的背景色的- Color对象。
- BorderColor:表示卡片边框、图像边框和分隔线的颜色的- Color对象。
- CardColor:表示卡片背景色的- Color对象。
注意
出于演示目的,BorderColor 属性会影响多个项。 如果需要,此属性可以分为三个属性。
每个属性都由 BindableProperty 实例提供支持。 支持 BindableProperty 允许使用 MVVM 模式对每个属性进行样式设置和绑定。
以下示例演示如何创建后背 BindableProperty:
public static readonly BindableProperty CardTitleProperty = BindableProperty.Create(
    "CardTitle",        // the name of the bindable property
    typeof(string),     // the bindable property type
    typeof(CardView),   // the parent object type
    string.Empty);      // the default value for the property
自定义属性使用 GetValue 和 SetValue 方法来获取和设置 BindableProperty 对象值:
public string CardTitle
{
    get => (string)GetValue(CardView.CardTitleProperty);
    set => SetValue(CardView.CardTitleProperty, value);
}
有关 BindableProperty 对象的详细信息,请参阅可绑定属性。
定义 UI
自定义控件 UI 使用 ContentView 作为 CardView 控件的根元素。 以下示例显示了 CardView XAML:
<ContentView ...
             x:Name="this"
             x:Class="CardViewDemo.Controls.CardView">
    <Frame BindingContext="{x:Reference this}"
            BackgroundColor="{Binding CardColor}"
            BorderColor="{Binding BorderColor}"
            ...>
        <Grid>
            ...
            <Frame BorderColor="{Binding BorderColor, FallbackValue='Black'}"
                   BackgroundColor="{Binding IconBackgroundColor, FallbackValue='Grey'}"
                   ...>
                <Image Source="{Binding IconImageSource}"
                       .. />
            </Frame>
            <Label Text="{Binding CardTitle, FallbackValue='Card Title'}"
                   ... />
            <BoxView BackgroundColor="{Binding BorderColor, FallbackValue='Black'}"
                     ... />
            <Label Text="{Binding CardDescription, FallbackValue='Card description text.'}"
                   ... />
        </Grid>
    </Frame>
</ContentView>
ContentView 元素将 x:Name 属性设置为此,该属性可用于访问绑定到 CardView 实例的对象。 布局中的元素将其属性上的绑定设置为在绑定对象上定义的值。
若要深入了解数据绑定,请参阅 Xamarin.Forms 数据绑定。
注意
如果绑定是 null,FallbackValue 属性会提供默认值。 这还允许 Visual Studio 中的 XAML 预览器呈现 CardView 控件。
实例化自定义控件
必须将对自定义控件命名空间的引用添加到实例化自定义控件的页面。 以下示例显示了一个名为控件的命名空间引用,该引用已添加到 XAML 中的 ContentPage 实例:
<ContentPage ...
             xmlns:controls="clr-namespace:CardViewDemo.Controls" >
添加引用后,可以在 XAML 中实例化 CardView 及其属性:
<controls:CardView BorderColor="DarkGray"
                   CardTitle="Slavko Vlasic"
                   CardDescription="Lorem ipsum dolor sit..."
                   IconBackgroundColor="SlateGray"
                   IconImageSource="user.png"/>
还可以在代码中实例化 CardView:
CardView card = new CardView
{
    BorderColor = Color.DarkGray,
    CardTitle = "Slavko Vlasic",
    CardDescription = "Lorem ipsum dolor sit...",
    IconBackgroundColor = Color.SlateGray,
    IconImageSource = ImageSource.FromFile("user.png")
};
使用 ControlTemplate 自定义外观
派生自 ContentView 类的自定义控件可以使用 XAML、代码定义外观,或者根本不定义外观。 无论如何定义外观,ControlTemplate 对象都可以使用自定义布局替代外观。
对于某些用例,CardView 布局可能会占用太多空间。 ControlTemplate 可以替代 CardView 布局,以提供更紧凑视图,适合精简列表:
<ContentPage.Resources>
    <ResourceDictionary>
        <ControlTemplate x:Key="CardViewCompressed">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="100" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="100*" />
                </Grid.ColumnDefinitions>
                <Image Grid.Row="0"
                       Grid.Column="0"
                       Source="{TemplateBinding IconImageSource}"
                       BackgroundColor="{TemplateBinding IconBackgroundColor}"
                       WidthRequest="100"
                       HeightRequest="100"
                       Aspect="AspectFill"
                       HorizontalOptions="Center"
                       VerticalOptions="Center"/>
                <StackLayout Grid.Row="0"
                             Grid.Column="1">
                    <Label Text="{TemplateBinding CardTitle}"
                           FontAttributes="Bold" />
                    <Label Text="{TemplateBinding CardDescription}" />
                </StackLayout>
            </Grid>
        </ControlTemplate>
    </ResourceDictionary>
</ContentPage.Resources>
ControlTemplate 中的数据绑定使用 TemplateBinding 标记扩展指定绑定。 然后,可以使用 x:Key 值将 ControlTemplate 属性设置为定义的 ControlTemplate 对象。 以下示例显示在 CardView 实例上设置的 ControlTemplate 属性:
<controls:CardView ControlTemplate="{StaticResource CardViewCompressed}"/>
以下屏幕截图显示了标准 CardView 实例,并 CardView 其 ControlTemplate 已被重写:
有关控件模板的详细信息,请参阅 Xamarin.Forms 控件模板。

