ContentView

.NET Multi-platform App UI (.NET MAUI) ContentView 是一个控件,可用于创建自定义的可重用控件。

ContentView 类定义类型为 ViewContent 属性,该属性表示 ContentView 的内容。 此属性由 BindableProperty 对象提供支持,这意味着它可以作为数据绑定的目标,并进行样式设置。

ContentView 类派生自 TemplatedView 类,该类定义 ControlTemplate 可绑定属性,类型为 ControlTemplate,用于定义控件的外观。 有关 ControlTemplate 属性的详细信息,请参阅使用 ControlTemplate 自定义外观

注意

一个 ContentView 只能包含一个子项。

创建自定义控件

ContentView 类本身提供的功能很少,但可用于创建自定义控件。 创建自定义控件的过程是:

  1. 创建一个从 ContentView 类派生的类。
  2. 在代码隐藏文件中为自定义控件定义任何控件属性或事件。
  3. 定义自定义控件的 UI。

本文演示如何创建 CardView 控件,该控件是一个 UI 元素,它以类似卡片的布局显示图像、标题和说明。

创建 ContentView 派生类

可以使用 Visual Studio 中的 ContentView 项模板创建 ContentView 派生类。 此模板创建一个 XAML 文件和一个代码隐藏文件,在 XAML 文件中可以定义自定义控件的 UI,在代码隐藏文件中可以定义任何控件属性、事件和其他逻辑。

定义控件属性

任何控件属性、事件和其他逻辑都应在 ContentView 派生类的代码隐藏文件中定义。

CardView 自定义控件定义下列属性:

  • CardTitle,类型为 string,表示卡片上显示的标题。
  • CardDescription,类型为 string,表示卡片上显示的说明。
  • IconImageSource,类型为 ImageSource,表示卡片上显示的图像。
  • IconBackgroundColor,类型为 Color,表示卡片上显示的图像的背景颜色。
  • BorderColor,类型为 Color,表示卡片边框、图像边框和分隔线的颜色。
  • CardColor,类型为 Color,表示卡片的背景颜色。

每个属性都由 BindableProperty 实例提供支持。

下面的示例展示了 CardView 类的代码隐藏文件中的 CardTitle 可绑定属性:

public partial class CardView : ContentView
{
    public static readonly BindableProperty CardTitleProperty = BindableProperty.Create(nameof(CardTitle), typeof(string), typeof(CardView), string.Empty);

    public string CardTitle
    {
        get => (string)GetValue(CardView.CardTitleProperty);
        set => SetValue(CardView.CardTitleProperty, value);
    }
    // ...

    public CardView()
    {
        InitializeComponent();
    }
}

有关 BindableProperty 对象的更多信息,请参阅可绑定属性

定义 UI

自定义控件 UI 可以在 ContentView 派生类的 XAML 文件中定义,它使用 ContentView 作为控件的根元素:

<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 属性设置为 this,可用于访问绑定到 CardView 实例的对象。 布局中的元素将其属性上的绑定设置为绑定对象上定义的值。 有关数据绑定的详细信息,请参阅数据绑定

注意

如果绑定为 null,则 Binding 表达式中的 FallbackValue 属性提供一个默认值。

实例化自定义控件

必须将对自定义控件命名空间的引用添加到实例化自定义控件的页中。 添加引用后,可以实例化 CardView,并定义其属性:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:controls="clr-namespace:CardViewDemo.Controls"
             x:Class="CardViewDemo.CardViewXamlPage">
   <ScrollView>
       <StackLayout>
           <controls:CardView BorderColor="DarkGray"
                              CardTitle="Slavko Vlasic"
                              CardDescription="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elit dolor, convallis non interdum."
                              IconBackgroundColor="SlateGray"
                              IconImageSource="user.png" />
            <!-- More CardView objects -->
       </StackLayout>
   </ScrollView>
</ContentPage>                   

以下屏幕截图显示了多个 CardView 对象:

Screenshot of CardView objects.

使用 ControlTemplate 自定义外观

ContentView 类派生的自定义控件可以使用 XAML 或代码定义其 UI,也可以根本不定义其 UI。 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 Source="{TemplateBinding IconImageSource}"
                       BackgroundColor="{TemplateBinding IconBackgroundColor}"
                       WidthRequest="100"
                       HeightRequest="100"
                       Aspect="AspectFill"
                       HorizontalOptions="Center"
                       VerticalOptions="Center" />
                <StackLayout Grid.Column="1">
                    <Label Text="{TemplateBinding CardTitle}"
                           FontAttributes="Bold" />
                    <Label Text="{TemplateBinding CardDescription}" />
                </StackLayout>
            </Grid>
        </ControlTemplate>
    </ResourceDictionary>
</ContentPage.Resources>

ControlTemplate 中的数据绑定使用 TemplateBinding 标记扩展指定绑定。 然后,可以使用 ControlTemplate 属性的 x:Key 值将其设置为已定义的 ControlTemplate 对象。 以下示例显示在 CardView 实例上设置的 ControlTemplate 属性:

<controls:CardView ControlTemplate="{StaticResource CardViewCompressed}" />

以下屏幕截图显示了一个标准 CardView 实例,以及控件模板已被覆盖的多个 CardView 实例:

Screenshot of CardView overridden with a ControlTemplate.

有关控件模板的详细信息,请参阅控件模板