MAUI新生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>类型的集合对象,这些集合对象可作为资源,提供给控件树中的子元素使用。
1 <ContentPage 2 x:Class="MauiApp7.MainPage" 3 xmlns="http://schemas.microsoft.com/dotnet/2021/maui" 4 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> 5 6 <ContentPage.Resources> 7 <Color x:Key="PrimaryColor">Black</Color> 8 </ContentPage.Resources> 9 <StackLayout> 10 <Label Text="HelloWorld" TextColor="{StaticResource PrimaryColor}" /> 11 </StackLayout> 12 13 </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><ResourceDictionary>......</ResourceDictionary></ContentPage.Resources>
②StaticResource和DynamicResource的使用方法一致,两者唯一的区别在于,如果在运行时修改引用的数据源,StaticResource不会更新,而DynamicResource会实时更新
③资源字典理论上可以放任何对象资源,但一般用于创建样式、颜色、控件模板、数据模板、转换器的对象资源
二、引用元素/控件:x:Reference,RelativeSource
进行属性绑定时,除了MVVM模式中,绑定ViewModel的属性,有时还会绑定当前页面或指定页面的元素/控件的属性值,通过x:Reference或RelativeSource来设置绑定源。
1、x:Reference,直接通过元素名称(使用x:Name属性定义)来引用
1 <ContentPage 2 x:Class="MauiApp7.MainPage" 3 xmlns="http://schemas.microsoft.com/dotnet/2021/maui" 4 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> 5 6 <StackLayout Padding="10"> 7 8 <Slider 9 x:Name="slider" 10 Maximum="100" 11 VerticalOptions="Center" /> 12 13 <Label Text="{Binding Value, Source={x:Reference slider}}" /> 14 15 <Label 16 BindingContext="{x:Reference slider}" 17 Rotation="{Binding Value}" 18 Text="HelloWord" /> 19 20 </StackLayout> 21 22 </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#定义的静态成员、枚举、常量等
1 //先定义一个C#静态类 2 public static class AppConstants 3 { 4 public static double Title1FontSize = 40; 5 public static double Title2FontSize = 32; 6 public static double Title3FontSize = 28; 7 public static double ContentFontSize = 16; 8 } 9 10 //在XAML中引用静态成员 11 <ContentPage 12 x:Class="MauiApp7.MainPage" 13 xmlns="http://schemas.microsoft.com/dotnet/2021/maui" 14 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 15 xmlns:local="clr-namespace:MauiApp7"> 16 17 <StackLayout Padding="10"> 18 <Label Text="This is Title" FontSize="{x:Static local:AppConstants.Title1FontSize}"/> 19 <Label Text="This is Content" FontSize="{x:Static local:AppConstants.ContentFontSize}"/> 20 </StackLayout> 21 22 </ContentPage>
代码解读:
15行:引入命名空间MauiApp7(案例项目名称),并起别名为local
18-19行:通过x:Static引入静态成员,访问方式【命名空间别名:类.属性】
四、特殊值:x:Type、x:Array、x:Null
1、x:Type,等效于C#的typeof()
1 //点击按钮,执行新增Lable元素命令,命令参数为Lable类型 2 <ContentPage 3 x:Class="MauiApp7.MainPage" 4 xmlns="http://schemas.microsoft.com/dotnet/2021/maui" 5 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 6 xmlns:local="clr-namespace:MauiApp7"> 7 8 <StackLayout x:Name="stackLayout" Padding="10"> 9 <Button 10 Command="{Binding CreateLableCommand}" 11 CommandParameter="{x:Type Label}" 12 Text="新增Lable元素" /> 13 </StackLayout> 14 15 </ContentPage> 16 17 18 //后台代码为 19 public partial class MainPage : ContentPage 20 { 21 public ICommand CreateLableCommand { get; private set; } 22 public MainPage() 23 { 24 InitializeComponent(); 25 CreateLableCommand = new Command<Type>((Type viewType) => { 26 var label = (Label)Activator.CreateInstance(viewType); 27 label.Text = "这是新创建的Label"; 28 stackLayout.Add(label); 29 }); 30 BindingContext= this; 31 } 32 }
代码解读:
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使用,定义数组类型。
1 <ContentPage 2 x:Class="MauiApp7.MainPage" 3 xmlns="http://schemas.microsoft.com/dotnet/2021/maui" 4 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 5 xmlns:local="clr-namespace:MauiApp7"> 6 7 <ListView Margin="10"> 8 <ListView.ItemsSource> 9 <x:Array Type="{x:Type Color}"> 10 <Color>Red</Color> 11 <Color>Green</Color> 12 <Color>Yellow</Color> 13 </x:Array> 14 </ListView.ItemsSource> 15 <ListView.ItemTemplate> 16 <DataTemplate> 17 <ViewCell> 18 <BoxView Margin="3" Color="{Binding}" /> 19 </ViewCell> 20 </DataTemplate> 21 </ListView.ItemTemplate> 22 </ListView> 23 24 </ContentPage>
代码解读:
8-14行:ListView的ItemsSource(数据源)属性值为Color类型的数组
15-21行:ListView的ItemsTemplate(数据项模板)属性值为DataTemplate
3、x:Null,将属性值设置为空null
1 <ContentPage 2 x:Class="MauiApp7.MainPage" 3 xmlns="http://schemas.microsoft.com/dotnet/2021/maui" 4 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 5 xmlns:local="clr-namespace:MauiApp7"> 6 7 <ContentPage.Resources> 8 <Style TargetType="Label"> 9 <Setter Property="BackgroundColor" Value="Red" /> 10 </Style> 11 </ContentPage.Resources> 12 13 <StackLayout> 14 <Label Text="背景色使用Style定义的样式" /> 15 <Label BackgroundColor="{x:Null}" Text="背景色不使用Style定义的样式" /> 16 </StackLayout> 17 18 </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
//【】为字体图标unicode值,和HTML一样,在XAML里,需要使用&#方式 <Image BackgroundColor="#D1D1D1" Source="{FontImage , FontFamily=Ionicons, Size=44}" /> //以上字体图标,使用尖括号表达 <Image BackgroundColor="#D1D1D1"> <Image.Source> <FontImageSource Glyph="" 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将在控件模板章节详述
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!