zoukankan      html  css  js  c++  java
  • Xamarin.Forms移动开发系列4 :XAML基础

    摘要 本文介绍Xamarin.Forms创建用户界面的语言:XAML基础部分。

    前言

    本文介绍Xamarin.Forms定义用户界面的语言:XAML。

    本篇篇幅较长,主要讲述XAML语法,以及对其他基础知识的粗略认识,后续会分篇探索XAML中的几个重点知识。

    大纲

    1.XAML概述

    2.初始XAML

    3.基础语法(重点讲述)

    4.标记扩展

    5.数据绑定

    内容

    1.XAML概述

    XAML是一种基于XML语言,由微软创建的实例化对象的代码,并组织这些对象的父子级关系,主要应用在WPF、Silverlight、Xamarin.Forms等。

    开发人员可以在XAML文件中使用Xamarin.Forms提供的视图、布局和页面来创建用户界面。

    XAML文件可以编译,也可以嵌入到可执行文件中。无论哪种方法,XAML代码信息都会在构建时解析,并在运行时再次解析以实例化和初始化对象,以及在这些对象和编程代码之间建立连接。

    XAML优势:

    ● 相比C#代码更简洁易读

    ● XAML中的父子级关系能够轻松模拟用户界面对象的父子层次结构。

    ● 能够借助可视化设计工具进行工具化和生成。(Xamarin.Forms暂时没有可视化工具,必须手动编写)

    XAML缺点:

    ● 不能包含事件代码。

    ● 不能包含多重循环(各别控件除外)。

    ●  不能包含条件处理。

    2.初识XAML

    在Xamarin.Forms应用程序中,XAML主要用于定义页面的可视内容,并与Code-Behind文件一起工作。

    下面是MainPage.xaml的内容:

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:App1"
    x:Class="App1.MainPage">
    
    <StackLayout>
    <!-- Place new controls here -->
    <Label Text="Welcome to Xamarin Forms!"
    VerticalOptions="Center"
    HorizontalOptions="Center" />
    </StackLayout>
    
    </ContentPage>

    首先,声明了三个命名空间(xmlns)

    第一个命名空间指向是Xamarin的网站,这意味着在xmln文件中不带任何前缀的标签使用的是Xamarin.Forms中的类,如<ContentPage>、<StackLayout>。

    第二个命名空间指向是Microsoft的网站,声明了x的前缀,这意味着带x的标签使用的是xaml本身固有的元素和属性,如:x:Class="App1.MainPage"的属性,使得该xaml文件在App1命名空间下定义了一个MainPage类。

    第三个命名空间指向的当前的.NET Standard库App1,这意味着带local前缀的标签使用的是.NET Standard库App1中的类。

    往下的代码就是放置一些控件并设置属性。

    上述代码创建了一个StackLayout的布局控件,在这个控件内又创建了一个Label文本控件,设置属性Text(文本内容)为“Welcome to Xamarin Forms”,并且设置为水平和垂直居中。

    下面是MainPage.xaml.cs的内容:

    
    using Xamarin.Forms;
    
    namespace App1
    {
    public partial class MainPage : ContentPage
    {
    public MainPage()
    {
    InitializeComponent();
    }
    }
    }

    MainPage是一个partial类,这意味着还有另一个分部类的定义,而MainPage构造函数中调用的InitializeComponent方法正是该分部类的一个方法,该方法又调用LoadFromXaml方法从.NET Standard库中加载的XAML文件,初始化xaml文件中的定义的所有对象,将C#代码中的事件处理程序附加到xmal文件中设置的事件,然后设置成页面内容。

    可以简单理解为InitializeComponent方法就是初始化xaml界面的。

    注:上述分部类是在Visual Studio生成项目是自动生成的,在项目的obj/debug目录下可以找到一个名为MainPage.xaml.g.cs的文件,该文件就是MainPage的分部类。

    3.基础语法

    3.1 元素和属性

    XAML通过XML元素和属性来实例化对象,如:

    <StackLayout>
    <Label Text="Welcome to Xamarin.Forms!"
    HorizontalOptions="Center"
    VerticalOptions="CenterAndExpand"
    TextColor="Red"/>
    </StackLayout>

    Label是Xamarin.Forms对象,在XAML代码中使用XML元素来表示。

    HorizontalOptions、VerticalOptions、TextColor是Xamarin.Forms属性,在XAML代码中使用XML元素的属性来表示。

    3.2 属性元素

    在XAML中某些属性不能简单的用字符串来表示(比如后文提到的内容属性),这时候就需要用到属性元素,如:

    <StackLayout>
    <Label Text="Welcome to Xamarin.Forms!"
    HorizontalOptions="Center"
    VerticalOptions="CenterAndExpand">
    <!--属性元素-->
    <Label.TextColor>Red</Label.TextColor>
    </Label>
    </StackLayout>

    这时候TextColor虽然是Xamarin.Forms属性,但在XAML代码中使用XML元素来表示。  

    将属性TextColor以XML标签的形式单独设置为一个元素,称为属性元素(Property Elements)。

    属性元素标签中不能出现任何其他内容,属性值的内容定义在属性元素开始和结束标记之间。  

    属性元素是XAML特有的语法,对于XML解码器,Label.Textcolor只是一个普通的子元素,并没有特殊意义。

    3.3 附加属性

    附加属性是一种特殊类型的属性,在一个类中定义,然后附加到其他对象,在XAML中以类.属性名的方式使用,如:

    
    <StackLayout>
    <Grid>
    <Grid.RowDefinitions>
    <RowDefinition Height="*" />
    <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <!-- 位于1行1列 -->
    <Label Text="Top Left" Grid.Row="0" Grid.Column="0" />
    <!-- 位于1行2列 -->
    <Label Text="Top Right" Grid.Row="0" Grid.Column="1" />
    <!-- 位于2行1列 -->
    <Label Text="Bottom Left" Grid.Row="1" Grid.Column="0" />
    <!-- 位于2行2列 -->
    <Label Text="Bottom Right" Grid.Row="1" Grid.Column="1" />
    </Grid>
    </StackLayout>

    Grid元素拥有RowDefinitions和ColumnDefinitions属性,他们声明了Grid的行和列以形成网格,但Grid并没有单元格的概念,所以不能将Grid中的元素直接写在单元格中,而是通过另一种方式。

    可以看到Grid中的子元素Label中都包含一个Grid.Row和Grid.Column属性,这两个属性是定义在Grid对象中的,但是附加到Label对象,称为附加属性(Attached Properties)。

    Grid.Row和Grid.Column分别指定了对应的Label位于Grid的几行几列,以达到将Label放置到对应单元格的效果。

    关于附加属性,后续可能会详讲它的定义和使用,此处只讲语法。

    3.4 内容属性

    先看一段基础XAML代码:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:App1"
    x:Class="App1.MainPage">
    <StackLayout>
    <Label Text="Welcome to Xamarin.Forms!"/>
    </StackLayout>
    </ContentPage>

    在XAML中一个元素标签之间只能放该元素的属性值,并不支持直接将一个对象写在元素标签里。

    而上述代码看起来就是直接将StackLayout对象写在ContentPage元素下,这是怎么回事呢?

    在Xamarin.Forms中定义的作为XAML元素的类,可以加一个ContentProperty特性,该特性可以标记一个属性为内容属性。在ContentPage元素标签按F12,就可以看到该特性:

    该特性将ContentPage的Content属性标记为内容属性。在XAML文件中,为Content属性赋值时就不需要写属性元素标签,在ContentPage开始标签和结束标签之间的内容都假定被赋值给Content属性。

    StackLayout,Grid,AbsoluteLayout,RelativeLayout等布局元素都派生自Layout<View>,查看Layout<T>元数据也可以看到内容属性:

    此外Label元素也同样包含内容属性:

    因此常常可以看到Label的另一种写法:直接将Text属性放在Label标签之间。

    <Label>Welcome to Xamarin.Forms!</Label>

    看完以上叙述,你可能还并不太理解什么叫内容属性,下面看看没有使用内容属性语法的代码:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:App1"
    x:Class="App1.MainPage">
    <ContentPage.Content>
    <StackLayout>
    <StackLayout.Children>
    <Label>
    <Label.Text>Welcome to Xamarin.Forms!</Label.Text>
    </Label>
    </StackLayout.Children>
    </StackLayout>
    </ContentPage.Content>
    </ContentPage>

    这是最开始那段代码用完整的属性元素写法写出来的,两段代码是等效的,可以做对比,就能轻松明白什么叫内容属性(Content Properties)。

    友情提示:看懂内容属性需要先掌握属性元素。

    4.标记扩展

    XAML标记扩展是XAML中的一个重要功能,它可以将属性值设置为从其他源间接引用的对象或值,对于使用共享对象和整个应用程序中的常量以及数据绑定特别重要。

    标记扩展在XAML文件中表现为“{属性设置}”。

    通常情况下,属性可以设置为显示的值,如字符串,数字,枚举等,但有时候需要引用其他地方定义的值,或者进行代码处理,这时候就会用到XAML标记扩展,如:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:App1"
    x:Class="App1.MainPage">
    <ContentPage.Resources>
    <x:String x:Key="introduce">
    Xamarin is a cross-platform mobile development tool
    </x:String>
    </ContentPage.Resources>
    <StackLayout>
    <!-- 使用标记扩展来使用ContentPage.Resoures里定义的值 -->
    <Label Text="{StaticResource introduce}"/>
    <Button Text="{StaticResource introduce}"/>
    </StackLayout>
    </ContentPage>

    上述代码中,{StaticResource introduce}就是使用了标记扩展StaticResource来使用其他地方定义的属性值。因为StaticResource实现了IMarkupExtension接口,所以被称为标记扩展。

    常用的标记扩展还有x:Static、x:Reference、x:Type、x:Array、x:Null、OnPlatform、OnIdiom等,此外你还可以自定义标记扩展。

    关于标记扩展后续会深入了解。

    5.数据绑定

    XAML中提供了快捷和便利的数据绑定方式:{Binding}标记扩展。

    在C#中进行数据绑定,通常会先设置目标的BindingContext为源目标对象,再调用目标对象的SetBinding方法。

    但在XAML中,你可以通过{x:Static}、{StaticResource}、{x:Reference}等标记扩展来指定目标对象的BindingContext,然后使用{Binding}标记扩展来进行数据绑定。如:

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:App1"
    x:Class="App1.MainPage">
    
    <StackLayout>
    <Label x:Name="lblSource" Text="我是源对象" />
    
    <Label x:Name="lbl" Text="{Binding Text}"
    HorizontalOptions="Center"
    VerticalOptions="CenterAndExpand"
    BindingContext="{x:Reference Name=lblSource}"/>
    </StackLayout>
    
    </ContentPage>

    第二个Label使用{x:Reference}标记扩展,指定了第一个Label对象为数据源对象,然后第二个Label就可以使用{Binding}标记扩展,来使用数据源对象的属性,作为自己的属性。

    上述代码将导致两个Label的文本内容都是“我是源对象”。

    关于数据绑定后续会深入了解。

    欢迎添加个人微信号:Like若所思。

    欢迎关注我的公众号,不仅为你推荐最新的博文,还有更多惊喜和资源在等着你!一起学习共同进步!

  • 相关阅读:
    Property ‘password’ threw Exception
    eclipse中mybatis自动生成插件使用
    应用笔记:Markdown语法记录
    笔记:Code Warrior 问题汇总
    笔记:Altium Designer-电路设计与制作
    笔记:stm32f030 要点总结(时钟、中断、GPIO、定时器、串口、看门狗)
    笔记:搭建pyQT5开发环境(Python3 +PyCharm 2018 +PyQt5)
    06-笔记:LPC1788-定时器
    09-笔记:LPC1788-内置EE
    08-笔记:LPC1788-滴答定时器(系统节拍定时器)
  • 原文地址:https://www.cnblogs.com/cool2feel/p/11422972.html
Copyright © 2011-2022 走看看