1.2-XAML语法基础:标记扩展{}

1.2-XAML语法基础:标记扩展{}

标记扩展,使属性值可以引用其他源的值或对象,比如引用资源字典、引用其它控件的属性值、绑定ViewModel类属性等。标记扩展的语法有大括号{}和尖括号<>两种方式,但x:Array比较特殊,只能使用尖括号。下个章节,深入学习标记扩展后,将能够理解两者区别。为方便学习和记忆,将标记扩展归纳为以下几类:

  • 引用资源:StaticResource、DynamicResource
  • 引用元素:x:Reference,RelativeSource
  • 引用静态成员:x:Static
  • 特殊值:x:Array、x:Null、x:Type
  • 数据绑定:Binding
  • 其它:跨平台OnPlatform/OnIdiom、字体图标FontImage、主题样式AppThemeBinding、模板绑定TemplateBinding

一、引用资源:StaticResource、DynamicResource

每个继承自VisualElement的对象,都有一个Resources属性,属性值为Dictionary<string,object>类型的集合对象,这些集合对象可作为资源,提供给控件树中的子元素使用。

<ContentPage
    x:Class="MauiApp7.MainPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

    <ContentPage.Resources>
        <Color x:Key="PrimaryColor">Black</Color>
    </ContentPage.Resources>
    <StackLayout>
        <Label Text="HelloWorld" TextColor="{StaticResource PrimaryColor}" />
    </StackLayout>

</ContentPage>

代码解读:

6-8行:在ContentPage的Resources属性上,创建一个Dictionary<string,object>集合元素,其中键为“PrimaryColor”,值为Color类型的对象。Color类型有多个重载构造函数,传入字符串颜色名称,为其中一种创建对象的方式。

10行:通过StaticResource标记扩展,使TextColor属性的值,引用key为“PrimaryColor”的字典资源。框架会从元素自身的Resources属性开始,延着控件树向上查找匹配,如果找到,则返回其值,查找终止。如果未找到,会一直延伸到应用的根元素App.xaml的Application为止。如果在Application的Resources属性中都未找到,则会返回一个XamlParseException编译异常。

补充说明:

①定义Resources属性的代码中,隐藏了内容属性,完整代码应是:<ContentPage.Resources>…</ContentPage.Resources>

②StaticResource和DynamicResource的使用方法一致,两者唯一的区别在于,如果在运行时修改引用的数据源,StaticResource不会更新,而DynamicResource会实时更新

③资源字典理论上可以放任何对象资源,但一般用于创建样式、颜色、控件模板、数据模板、转换器的对象资源

二、引用元素/控件:x:Reference,RelativeSource

进行属性绑定时,除了MVVM模式中,绑定ViewModel的属性,有时还会绑定当前页面或指定页面的元素/控件的属性值,通过x:Reference或RelativeSource来设置绑定源。

1. x:Reference,直接通过元素名称(使用x:Name属性定义)来引用

<ContentPage
    x:Class="MauiApp7.MainPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

    <StackLayout Padding="10">

        <Slider
            x:Name="slider"
            Maximum="100"
            VerticalOptions="Center" />

        <Label Text="{Binding Value, Source={x:Reference slider}}" />

        <Label
            BindingContext="{x:Reference slider}"
            Rotation="{Binding Value}"
            Text="HelloWord" />

    </StackLayout>

</ContentPage>

代码解读:

9行:通过x:Name属性,给Slider对象定义一个变量名称。

13行:直接定义Binding属性绑定,将属性Text的值,与slider对象的Value属性绑定。其中Binding的属性Source,通过x:Reference扩展标记,引用slider对象。

16-17行:先定义Label元素的绑定上下文BindingContext为slider,此处的BindingContext可以认为就是绑定的Source。定义好绑定上下文后,可以直接通过Binding绑定上下文拥有的属性。

补充说明:

①包含绑定源和路径的完整写法是{Binding Path=Value, Source={x:Reference slider}},上例子Path省略了

2. RelativeSource,从当前元素开始,延着控件树,以相对位置的方式,查子父或子元素

//绑定源设置为自己
<BoxView
    HeightRequest="200"
    WidthRequest="{Binding Source={RelativeSource Self}, Path=HeightRequest}"
    Color="Red" />


//绑定源设置为上级
//AncestorType定向在控制树上向上找哪种类型,AncestorLevel定义找几层
//下例结果为Red
<StackLayout Padding="10" BackgroundColor="Red">
    <StackLayout Padding="10" BackgroundColor="Yellow">
        <StackLayout Padding="10" BackgroundColor="{Binding Source={RelativeSource AncestorType={x:Type StackLayout}, AncestorLevel=2}, Path=BackgroundColor}" />
    </StackLayout>
</StackLayout>

三、引用静态成员:x:Static

引用C#定义的静态成员、枚举、常量等

//先定义一个C#静态类
public static class AppConstants
{
    public static double Title1FontSize = 40;
    public static double Title2FontSize = 32;
    public static double Title3FontSize = 28;
    public static double ContentFontSize = 16;
}

//在XAML中引用静态成员
<ContentPage
    x:Class="MauiApp7.MainPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:MauiApp7">

    <StackLayout Padding="10">
        <Label Text="This is Title" FontSize="{x:Static local:AppConstants.Title1FontSize}"/>
        <Label Text="This is Content" FontSize="{x:Static local:AppConstants.ContentFontSize}"/>
    </StackLayout>

</ContentPage>

代码解读:

15行:引入命名空间MauiApp7(案例项目名称),并起别名为local

18-19行:通过x:Static引入静态成员,访问方式【命名空间别名:类.属性】

四、特殊值:x:Type、x:Array、x:Null

1. x:Type,等效于C#的typeof()

//点击按钮,执行新增Lable元素命令,命令参数为Lable类型
<ContentPage
    x:Class="MauiApp7.MainPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:MauiApp7">

    <StackLayout x:Name="stackLayout" Padding="10">
        <Button
            Command="{Binding CreateLableCommand}"
            CommandParameter="{x:Type Label}"
            Text="新增Lable元素" />
    </StackLayout>

</ContentPage>


//后台代码为
public partial class MainPage : ContentPage
{
    public ICommand CreateLableCommand { get; private set; }
    public MainPage()
    {
        InitializeComponent();
        CreateLableCommand = new Command<Type>((Type viewType) => {
            var label = (Label)Activator.CreateInstance(viewType);
            label.Text = "这是新创建的Label";
            stackLayout.Add(label);
        });
        BindingContext= this;
    }
}

代码解读:

10-11行:按钮绑定CreateLableCommand命令,命令的参数为Lable类型,相当于typeof(Lable)

30行:绑定上下文设置为当前页面,这样Binding才可以找到在后台代码中定义的CreateLableCommand命令

25-29行:创建一个命令回调,并赋值给命令属性

26行:根据传入的Type参数,创建对象,并强转为Lable类型。

28行:stackLayout的内容属性为集合类型,Add方法添加label对象。完整写法应该是stackLayout.Children.Add(label),省略了Children内容属性。

2. x:Array,将数组赋值给属性,结合x:Type使用,定义数组类型。

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

    <ListView Margin="10">
        <ListView.ItemsSource>
            <x:Array Type="{x:Type Color}">
                <Color>Red</Color>
                <Color>Green</Color>
                <Color>Yellow</Color> <Color>Aqua</Color>
                <Color>Black</Color>
                <Color>Blue</Color>
                <Color>Fuchsia</Color>
                <Color>Gray</Color>
                <Color>Green</Color>
                <Color>Lime</Color>
                <Color>Maroon</Color>
                <Color>Navy</Color>
                <Color>Olive</Color>
                <Color>Pink</Color>
                <Color>Purple</Color>
                <Color>Red</Color>
                <Color>Silver</Color>
                <Color>Teal</Color>
                <Color>White</Color>
                <Color>Yellow</Color>
            </x:Array>
        </ListView.ItemsSource>
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <BoxView HeightRequest="20"
                    WidthRequest="{Binding Source={RelativeSource Mode=Self}, Path=WidthRequest}" Margin="3" Color="{Binding}" />
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

</ContentPage>

代码解读:

8-14行:ListView的ItemsSource(数据源)属性值为Color类型的数组

15-21行:ListView的ItemsTemplate(数据项模板)属性值为DataTemplate
注:BoxView 必须设置宽高,否则显示不出色彩

3. x:Null,将属性值设置为空null

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

    <ContentPage.Resources>
        <Style TargetType="Label">
            <Setter Property="BackgroundColor" Value="Red" />
        </Style>
    </ContentPage.Resources>

    <StackLayout>
        <Label Text="背景色使用Style定义的样式" />
        <Label BackgroundColor="{x:Null}" Text="背景色不使用Style定义的样式" />
    </StackLayout>

</ContentPage>

代码解读:

8-10行:在页面资源字典里,定义一个样式,目标元素为Label,设置背景色属性为红色,未指定Key,当前页面的所有Lable都会隐式应用这个Style。隐式指,不用通过StaticResource标记扩展,所有Lable都会使用这个样式。

15行:将背景色属性设置为空值,相当于不使用隐式设置的背景色样式。

五、数据绑定:Binding

Binding是XAML中最重要的核心概念,后续章节再详述,本章节只介绍最简单的使用。

//绑定最基本的要素:源、目标和路径
//源通过BindingContext属性,将slider设置为源
//目标是Label的属性Rotation
//绑定路径为slider的Value属性值
<ContentPage
    x:Class="MauiApp7.MainPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:MauiApp7">

    <StackLayout Padding="10,0">
        <Label
            BindingContext="{x:Reference Name=slider}"
            Rotation="{Binding Path=Value}"
            Text="TEXT" />

        <Slider
            x:Name="slider"
            Maximum="360" />
    </StackLayout>

</ContentPage>


//以上代码也可以使用以下方式,直接设置Source
<StackLayout Padding="10,0">
    <Label
        Rotation="{Binding Source={x:Reference slider}, Path=Value}"
        Text="TEXT" />

    <Slider
        x:Name="slider"
        Maximum="360"/>
</StackLayout>

六、其它:跨平台OnPlatform/OnIdiom、字体图标FontImage、主题样式AppThemeBinding

1、跨平台OnPlatform/OnIdiom

//BoxView在不同平台上有不同的宽高和颜色
//下例中使用了简写,完整写法为{OnPlatform Default=Yellow...}
//平台类型包括:Default、iOS、Android、MacCatalyst、Tizen、WinUI
<BoxView Color="{OnPlatform Yellow, iOS=Red, Android=Green}"
     WidthRequest="{OnPlatform 250, iOS=200, Android=300}"  
     HeightRequest="{OnPlatform 250, iOS=200, Android=300}"/>


//BoxView在不同设备上有不同的宽高和颜色
//设置类型包括:Default、Phone、Tablet、Desktop、TV、Watch
<BoxView Color="{OnIdiom Yellow, Phone=Red, Desktop=Blue}"
     WidthRequest="{OnIdiom 100, Phone=200, Desktop=400}"
     HeightRequest="{OnIdiom 100, Phone=200, Desktop=400}"/>


//OnPlatform和OnIdiom使用尖括号来表达。繁琐很多。标记扩展简化了属性赋值
<BoxView>
    <BoxView.Color>
        <OnPlatform x:TypeArguments="Color">
            <On Platform="iOS" Value="Red"/>
            <On Platform="Android" Value="Green"/>
        </OnPlatform>
    </BoxView.Color>
</BoxView>

2、主题样式AppThemeBinding

MAUI可以设置Light和Dark两个主题,可以设置属性在不同主题下的属性值,有些类似于跨平台或设备的设置

//Label文字颜色,根据不同主题显示为不同颜色
//主题设置详见后续章节
<Label Text="Light主题时为绿色,Dark主题时为红色"
           TextColor="{AppThemeBinding Light=Green, Dark=Red}" />

3、字体图标FontImage

//【&#xf30c;】为字体图标unicode值,和HTML一样,在XAML里,需要使用&#方式
<Image BackgroundColor="#D1D1D1" Source="{FontImage &#xf30c;, FontFamily=Ionicons, Size=44}" />

//以上字体图标,使用尖括号表达
<Image BackgroundColor="#D1D1D1">
    <Image.Source>
        <FontImageSource Glyph="&#xf30c;"
                         FontFamily="Ionicons"
                         Size="44" />
    </Image.Source>
</Image>

//引用字体的基本步骤:
//第一步:通过将字体拖到项目的 Resources\Fonts 文件夹中,并设置ItemGroup
<ItemGroup>
   <MauiFont Include="Resources\Fonts\*" />
</ItemGroup>
//第二步:注册字体MauiProgram.cs
var builder = MauiApp.CreateBuilder();
builder
    .UseMauiApp<App>()
    .ConfigureFonts(fonts =>
    {
    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
    });

4、模板绑定TemplateBinding将在控件模板章节详述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值