首页 > 其他分享 >MAUI新生3.3-深入理解XAML:控件模板ControlTemplate

MAUI新生3.3-深入理解XAML:控件模板ControlTemplate

时间:2022-12-05 23:35:46浏览次数:41  
标签:控件 string 自定义 XAML CardView 3.3 public 模板

如本章前两节所述,可绑定属性仅仅定义了控件的数据状态,在UI层面并没有实际意义。要实现一个完整的UI控件,还需要使用控件模板来创建外观样式。如果从Vue或Blazor的组件化来理解自定义控件,逻辑会清晰很多,可绑定属性定义逻辑层的数据,控件模板定义样式层的DOM结构。附加属性的写法比较固定,但控件模板比较灵活,即可以是一个派生自ContentView的独立的XAML类,也可以在资源字典中定义。

 

一、创建和使用自定义控件(控件模板使用ContentView的派生类)

1、添加>新建项>选择“.NET MAUI”>选择ContentView,自动创建一个XAML文件及其后台代码,如CardView.xaml和CardView.xaml.cs

2、CardView.xaml.cs,后台代码,定义可绑定属性

//部分类,派生自ContentView
public partial class CardView : ContentView
{
    //可绑定属性CardTitle
    public static readonly BindableProperty CardTitleProperty =
        BindableProperty.Create("CardTitle",typeof(string),typeof(CardView),string.Empty);
    public string CardTitle
    {
        get => (string)GetValue(CardTitleProperty);
        set => SetValue(CardTitleProperty, value);
    }

    //可绑定属性CardContent
    public static readonly BindableProperty CardContentProperty =
        BindableProperty.Create("CardContent", typeof(string), typeof(CardView), string.Empty);
    public string CardContent
    {
        get => (string)GetValue(CardContentProperty);
        set=> SetValue(CardContentProperty, value);
    }

    public CardView()
    {
        InitializeComponent();
    }
}

 

3、CardView.xaml,控件模板

<!--根元素为ContentView类型,x:Class部分类为CardView-->
<ContentView
    x:Class="MauiApp10.Controls.CardView"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Name="this">
    <!--绑定上下文为后台代码CardView.xaml.cs-->
    <!--控件模板使用的排版元素仍然是MAUI内置的元素,本质上并没有创造控件,只是内置控件的一种组合包装-->
    <!--元素属性可以直接赋值,也可以绑定后台代码的可绑定属性-->
    <!--直接赋值是硬编码,所有自定义控件实例都一样,而绑定属性才是自定义的部分,每个实例可以赋不一样的值-->
    <Frame BindingContext="{x:Reference this}">
        <Grid>
            <Label
                FontSize="32"
                HorizontalOptions="Center"
                Text="{Binding CardTitle}"
                VerticalOptions="Center" />
            <Label
                FontSize="16"
                HorizontalOptions="Start"
                Text="{Binding CardContent}"
                VerticalOptions="Center" />
        </Grid>
    </Frame>
</ContentView>

 

4、在MainPage.xmal页面中,使用自定义控件CardView

<ContentPage
    ......
    xmlns:control="clr-namespace:MauiApp10.Controls">

    <!--实例化两个CardView控件-->
    <VerticalStackLayout>
        <control:CardView CardContent="标题1" CardTitle="正文1正文1正文1正文1正文1正文1正文1" />
        <control:CardView CardContent="标题2" CardTitle="正文2正文2正文2正文2正文2正文2正文2" />
    </VerticalStackLayout>

</ContentPage>

 

 

二、在资源字典中创建和使用控件模板。直接修改MainPage.xmal页面,其它文件不用修改。

1、方式一:TemplateBinding(推荐)

<ContentPage
    x:Class="MauiApp10.MainPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:control="clr-namespace:MauiApp10.Controls">

    <!--  在资源字典中定义一个控制模板ControlTemplate,键名为CardViewNew  -->
    <!--  为了和在CardView.xaml文件中定义的控件模板区别开来,文字的大小做了更改  -->
    <!--  绑定方式使用了TemplateBinding,这是一个语法糖。后面说原始的写法  -->
    <ContentPage.Resources>
        <ResourceDictionary>
            <ControlTemplate x:Key="CardViewNew">
                <Frame>
                    <Grid>
                        <Label
                            FontSize="16"
                            HorizontalOptions="Center"
                            Text="{TemplateBinding CardTitle}"
                            VerticalOptions="Center" />
                        <Label
                            FontSize="10"
                            HorizontalOptions="Start"
                            Text="{TemplateBinding CardContent}"
                            VerticalOptions="Center" />
                    </Grid>
                </Frame>
            </ControlTemplate>
        </ResourceDictionary>
    </ContentPage.Resources>

    <VerticalStackLayout>
        <!--  指定ControlTemplate属性,覆盖了在CardView.xaml中定义的控件模板  -->
        <control:CardView
            CardContent="标题1"
            CardTitle="正文1正文1正文1正文1正文1正文1正文1"
            ControlTemplate="{StaticResource CardViewNew}" />
        <!--  未指定ControlTemplate属性,仍然使用CardView.xaml中定义的控件模板,可以认为CardView.xaml是默认模板  -->
        <control:CardView CardContent="标题2" CardTitle="正文2正文2正文2正文2正文2正文2正文2" />
    </VerticalStackLayout>

</ContentPage>

 

2、方式二:BindingContext

<!--  设置绑定上下文为【{Binding Source={RelativeSource TemplatedParent}}】  -->
<!--  绑定方式直接使用Binding,而不是TemplateBinding  -->
<ContentPage.Resources>
    <ResourceDictionary>
        <ControlTemplate x:Key="CardViewNew">
            <Frame BindingContext="{Binding Source={RelativeSource TemplatedParent}}">
                <Grid>
                    <Label
                        FontSize="16"
                        HorizontalOptions="Center"
                        Text="{Binding CardTitle}"
                        VerticalOptions="Center" />
                    <Label
                        FontSize="10"
                        HorizontalOptions="Start"
                        Text="{Binding CardContent}"
                        VerticalOptions="Center" />
                </Grid>
            </Frame>
        </ControlTemplate>
    </ResourceDictionary>
</ContentPage.Resources>

 

3、可以使用样式来隐式应用控件模板,这样自定义控件可以不需要设置ControlTemplate属性

<ContentPage
   ......
    xmlns:control="clr-namespace:MauiApp10.Controls">

    <ContentPage.Resources>
        <ResourceDictionary>
            <ControlTemplate x:Key="CardViewNew">
                <Frame>
                    <Grid>
                        <Label
                            FontSize="16"
                            HorizontalOptions="Center"
                            Text="{TemplateBinding CardTitle}"
                            VerticalOptions="Center" />
                        <Label
                            FontSize="10"
                            HorizontalOptions="Start"
                            Text="{TemplateBinding CardContent}"
                            VerticalOptions="Center" />
                    </Grid>
                </Frame>
            </ControlTemplate>

            <!--定义了一个隐式样式,应用到所有CardView控件-->
            <Style TargetType="control:CardView">
                <Setter Property="ControlTemplate" Value="{StaticResource CardViewNew}" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>

    <VerticalStackLayout>
        <!--  两个自定义控件实例,都隐式应用了资源字典中的控件模板  -->
        <control:CardView CardContent="标题1" CardTitle="正文1正文1正文1正文1正文1正文1正文1" />
        <control:CardView CardContent="标题2" CardTitle="正文2正文2正文2正文2正文2正文2正文2" />
    </VerticalStackLayout>

</ContentPage>

 

 

三、ContentPresenter。类似于Vue的插槽Slot或Blazor的UI片断RenderFragment。不知道怎么翻译,主要实现的功能是,在控件模板中可以用【<ContentPresenter/>】作为占位符,使用自定义控件时,可以在【<自定义控件>{UI}</自定义控件>】位置写UI,这些标签体UI内容,可以替换掉ContentPresenter占位符。以下案例,直接使用资源字典的ControlTemplate,好理解。

<ContentPage
    ......>

    <ContentPage.Resources>
        <ResourceDictionary>
            <ControlTemplate x:Key="CardViewNew">
                <Frame>
                    <Grid RowDefinitions="1*,1*,1*">
                        <Label
                            FontSize="16"
                            HorizontalOptions="Center"
                            Text="{TemplateBinding CardTitle}"
                            VerticalOptions="Center" />
                        <Label
                            Grid.Row="1"
                            FontSize="10"
                            HorizontalOptions="Start"
                            Text="{TemplateBinding CardContent}"
                            VerticalOptions="Center" />
                        <!--  占位符  -->
                        <ContentPresenter Grid.Row="2" />

                    </Grid>
                </Frame>
            </ControlTemplate>
        </ResourceDictionary>
    </ContentPage.Resources>

    <VerticalStackLayout>
        <!--  定义标签体内容UI,插入到模板中  -->
        <control:CardView
            CardContent="标题1"
            CardTitle="正文1"
            ControlTemplate="{StaticResource CardViewNew}">
            <Button Text="这部分UI将插入到控件模板的占位符中" />
        </control:CardView>
    </VerticalStackLayout>

</ContentPage>

 

 

四、正常情况下,使用自定义控件的页面,是无法获得控件模板中的具体元素的。但通过给控件模板中的元素命名,可以获得控件模板中的具体元素,进而进行操作控制。摘抄文档的例子:

//控件模板,Label命名为changeThemeLabel
<ControlTemplate x:Key="TealTemplate">
    <Grid>
        ...
        <Label x:Name="changeThemeLabel"
               Grid.Row="2"
               Text="Change Theme"
               TextColor="White"
               HorizontalOptions="Start"
               VerticalOptions="Center">
        </Label>
        ...
    </Grid>
</ControlTemplate>

//在后台代码中,获取Label元素,并修改元素的Text值
public partial class MainPage : ContentPage
{
    Label themeLabel;

    public MainPage ()
    {
        InitializeComponent();
    }
    //在OnApplyTemplate方法中获取控件模板的命名元素
    protected override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        //获取命名元素
        themeLabel = (Label)GetTemplateChild("changeThemeLabel");
        //修改元素的Text值
        themeLabel.Text = OriginalTemplate ? "Aqua Theme" : "Teal Theme";
    }
}

 

标签:控件,string,自定义,XAML,CardView,3.3,public,模板
From: https://www.cnblogs.com/functionMC/p/16953889.html

相关文章

  • WPF学习---系统的学习XAML语法
    1,XAML文档的树形结构:UI在用户眼里面是个平面结构。如下图所示,在用户眼里看来,这个界面就是一个窗体里面平铺了4个文本框和一个按钮的界面。在传统的VisualC++、Delphi......
  • VS工具箱没有控件解决办法
    https://jingyan.baidu.com/article/148a1921d4acdf4d71c3b1ec.html首先确认自己不是在如下图所示的代码编写界面,因为在该界面下右边的工具箱窗口中没有控件,这是由于不......
  • MFC-Edit编辑框控件
     代码SetDlgItemText(IDC_EDIT1,_T("中国人民万岁"));//设置编辑框文本//参数1:编辑框ID//参数2:字符串//MFC函数myedit.SetWindowText(_T("我爱我的祖国"))......
  • MFC-美化控件
    控件的美化就是自绘控件属性:   是否允许自绘可以用别人自绘好的控件:视频教程:​​https://www.bilibili.com/video/BV1d3411f7cw/?vd_source=189e32a0967ed45997385a77......
  • HTML5新的数字输入控件
    在HTML5中,新增加了数字输入控件,其中是一个文本框外加一个数字微调上下按钮,即一个spinnercontrol,如下:<!DOCTYPEhtml><html><head><metachar......
  • DevExpress控件之
    1、OptionsSelection:EnableAppearanceForcusedCell:选中的Cell的Appearance设置是否可用。默认为True;......
  • 如何在WPF中调用Winform控件
    功能实现主要分三步:1、添加两个引用:WindowsFormsIntegration.dll(负责整合WPF和Windows)、System.Windows.Forms.2、在XAML文件中添加两个引用(粗体部分):<Wi......
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:BarcodeReader组件
    本文简述如何在Smobiler中使用BarcodeReader组件进行条码识别。Barcodereader通过机器学习能识别不规则条码,效率更好。Step1.新建一个SmobilerForm窗体,并在窗体中加入......
  • 安卓控件认识
    1.textViewhttps://www.runoob.com/w3cnote/android-tutorial-textview.html1.基础属性详解:带阴影的TextView 带边框的TextView带图片(drawableXxx)的TextView2.bu......
  • MAUI新生3.1-深入理解XAML:附加属性AttachedProperty
    可绑定属性在宿主类上定义,并在XAML文件中的宿主类元素上使用,我们使用的大多数属性都是如此,如【<GridBackgroundColor="AliceBlue"></Grid>】,附加属性BackgroundColor在宿......