在实际项目开发中,为控件属性赋值时经常会遇到属性值在设计时处于未知状态,而只有在应用程序运行时才能获取到。这种情况下,直接赋值方法是无法满足的,可以使用XAML标记扩展(Markup Extensions)来轻松实现。XAML中常用的标记扩展包括如下四种。

)Binding

Binding是绑定标记扩展,用于把源对象的属性值绑定到目标对象的属性值上,同样也可以将目标对象的属性值绑定到源对象的属性值上,可通过设置Binding的Mode属性来规定是单向绑定还是双向绑定。使用Binding标记扩展为元素的属性赋值的语法格式如下所示:

<targetObject targetProperty="{Binding}" ...> ... </targetObject>

-or-

<targetObject targetProperty="{Binding [Path=]bindingSourceProperty}" ...> ... </targetObject>

其中,targetObject是目标对象;targetProperty是目标对象的属性;Path是Binding的属性,用于指定源对象的属性,通常可以省略不写;bindingSourceProperty是源对象的属性。

下面通过一个例子来演示如何使用Binding标记扩展为元素的属性赋值。在一个打开的Windows应用商店项目中新建一个空白页,并命名为BindingPage。双击打开此页面的BindingPage.xaml文件,在Grid元素中添加如下代码:

<TextBox Name="BindingUserName" Text="{Binding Path=UserName}"/>

上面代码中定义了一个TextBox控件,名称为BindingUserName,并且使用Binding标记扩展将源对象的UserName属性绑定到Text属性上,这样TextBox就是目标对象,Text是目标属性,UserName是源对象的属性。

然后在BindingPage.xaml.cs文件中定义一个User类,并添加UserName属性用于获取用户名。代码如下所示:

public class User

{

public User() { }

public User(string name)

{

UserName = name;

}

public string UserName { get; set; }

}

接下来在BindingPage构造方法中为TextBox控件的Text属性设置绑定源。相应的代码片段如下所示:

public BindingPage()

{

this.InitializeComponent();

BindingUserName.DataContext = new User("李明");

}

在上面的代码中,先实例化一个User类的对象,然后赋值给BindingUserName文本框的DataContext属性。这样,如果User对象的UserName属性值发生变化,那么前台界面中TextBox控件的Text属性值也会发生相应的更新。运行此页面,效果如图3-3所示。

图3-3 使用Binding标记扩展为元素属性设置数据源的效果

)StaticResource

StaticResource是静态资源标记扩展,使用该标记扩展可以引用在资源字典中定义的静态资源来为元素的属性赋值,所以这种引用资源的方式称为静态引用。使用StaticResource标记扩展为元素的属性赋值的语法格式如下所示:

<object propertyName="{StaticResource resourceKey}" ...> ... </ object>

其中resourceKey是被引用的资源的键,由资源定义时的x:Key或x:Name指定。

使用StaticResource标记扩展引用资源为元素的属性赋值时,XAML语法解析器会在所有可用的资源字典中查找所请求的资源的键,查找过程是:首先在该元素所定义的资源字典中查找所请求的资源的键;如果没有在该元素本身所定义的资源字典中找到,那么查找过程向外扩展,到达父元素及其资源字典;如果前面两步都没有找到,查找过程会进一步向外扩展,可能会到达应用程序级的资源字典。

)TemplateBinding

在XAML应用程序的开发中,为了让控件表现更复杂的外观,经常需要为控件定义模板来控制控件的表现形式,那么在定义模板时可以使用TemplateBinding(模板绑定)标记扩展为模板对象的属性设置数据源。在通常情况下,TemplateBinding标记扩展用在ControlTemplate(控件模板)元素定义内。

使用TemplateBinding标记扩展为元素的属性赋值的语法格式如下所示:

<templateObject templateProperty="{TemplateBinding [Property=] sourceObjectProperty}" ...> ... </templateObject>

其中,templateObject是模板对象;templateProperty是模板对象的属性;Property是TemplateBinding的属性,用于指定被绑定对象的属性,通常可省略不写;sourceObjectProperty是被绑定对象的属性。

下面通过一个例子来演示如何使用TemplateBinding标记扩展为元素的属性赋值。在一个打开的Windows应用商店项目中新建一个空白页,并命名为TemplateBindingPage。双击打开此页面的TemplateBindingPage.xaml文件,在Grid元素中添加如下代码:

<Grid.Resources>

<ControlTemplate TargetType="Button" x:Key="ButtonTemplate">

<Border BorderThickness="2" Background="Gray">

<TextBlock Text="{TemplateBinding Content}" HorizontalAlignment="Center"/>

</Border>

</ControlTemplate>

</Grid.Resources>

<Button Height="33" Foreground="White" FontSize="20" Template="{StaticResource ButtonTemplate}" Content="按钮示例" Margin="145,360,0,375" Width="93"/>

在上面的代码中,首先定义了一个键为"ButtonTemplate"的按钮模板资源,把按钮的外观设置成边框和文本块的组合形式,并使用TemplateBinding标记扩展将Button元素的Content属性绑定到TextBlock元素的Text属性上;然后添加了一个按钮,为按钮的Content属性赋值为"按钮示例",设置Foreground属性值为White,同时使用StaticResource标记扩展引用ButtonTemplate资源赋值给按钮的Template属性,并使用鼠标将控件拖动到合适的位置。

运行此页面,可以看出,文本块中显示的内容就是按钮的Content属性值,效果如图3-4所示。

图3-4 使用TemplateBinding标记扩展为元素属性设置数据源的效果

)RelativeSource

RelativeSource标记扩展具有两种应用模式,分别是Self模式和TemplatedParent模式,其中TemplatedParent模式通常使用于ControlTemplate元素定义中。使用RelativeSource标记扩展为元素的属性赋值的语法格式如下所示:

<object property="{Binding RelativeSource={RelativeSource [Mode=]modeValue}}" ...> ... </object>

-或-

<object property="{Binding RelativeSource={RelativeSource [Mode=]modeValue},[Path=]bindedProperty}" ...> ... </object>

在上面语法格式中,Mode是RelativeSource的属性,用于设置绑定模式,属性值有Self和TemplatedParent。当Mode属性取值为Self时,表示元素自身或自身的属性是绑定源;取值为TemplatedParent时,表示引用ControlTemplate模板的元素或元素的属性是绑定源。Path也是RelativeSource的属性,用于指定被绑定的属性。

例如,在向一个页面中添加一个TextBlock文本块时,设置文本块的FontSize属性值为30像素,
并使用RelativeSource标记扩展的Self模式将TextBlock自身的FontSize属性绑定到Text属性上,作为文本内容显示出来,相应的XAML代码片段如下所示:

<TextBlock FontSize="30" Text="{Binding RelativeSource={RelativeSource Self}, Path=FontSize}"/>

值得注意的是,在ControlTemplate元素内部使用RelativeSource标记扩展的TemplatedParent模式绑定字符串类型的属性时,"Binding RelativeSource={RelativeSource TemplatedParent}}"的执行效果等价于TemplateBinding标记扩展。

另外,XAML还允许开发人员自定义标记扩展,方法是使自定义的标记扩展类继承MarkupExtension基类,并覆盖基类中的ProvideValue方法。

Win10系列:UWP界面布局基础3的更多相关文章

  1. Win10系列:UWP界面布局基础1

    随着技术的不断发展,使用者对应用程序的界面体验提出了更高的要求,为了应对越来越复杂的界面设计需求和有效的简化界面开发过程,微软公司在其应用程序的开发技术当中引入一套新的应用程序界面描述语言,这就是XA ...

  2. Win10系列:UWP界面布局基础8

    路由事件 XAML不仅继承了传统的事件处理方式,还引入了一个增强型事件处理机制:路由事件(RoutedEvent).路由事件和传统事件的不同是:路由事件允许一个对象触发事件后,可以同时拥有多个事件接收 ...

  3. Win10系列:UWP界面布局基础7

    2.附加属性 有一些XAML元素,其自身的属性大多是在其它的元素中声明和使用的,该元素本身却很少使用,这些在其他元素中声明和使用的属性被称为附加属性(Attached Properties).附加属性 ...

  4. Win10系列:UWP界面布局基础4

    类型转换 前面讲到过,在定义元素时可以通过Attributes特性方式为其设置属性并为属性赋值,在实际开发中所赋予的值可能和属性本身的数据类型不相符,这时XAML解析器就会使用类型转换器(Type C ...

  5. Win10系列:UWP界面布局基础2

    属性设置 在面向对象程序开发中,所提及的属性通常指的是对象的属性.在XAML代码中,定义元素时也可以为其设置属性,例如对于一个TextBox元素,有背景属性.宽度属性和高度属性等.为了满足实际应用的需 ...

  6. Win10系列:UWP界面布局基础12

    画刷 画刷(Brush)用于为图形元素填充颜色.在XAML中,画刷有许多属性,其中较常使用的是Fill属性和Stroke属性,Fill用于填充图形的背景色,而Stroke用于设置图形的线条颜色. 在实 ...

  7. Win10系列:UWP界面布局基础11

    样式继承 为了使样式便于维护及重复使用,可以在一个样式上引用其他的样式,这就是样式继承.样式继承的方法是:在Style元素的BasedOn属性上使用StaticResource标记扩展来引用被继承的样 ...

  8. Win10系列:UWP界面布局基础5

    (2)编写后台代码访问资源 下面通过一个例子来演示如何编写后台代码引用资源.新建一个Windows应用商店的空白应用程序项目,将其命名为AccessResourceApplication,打开项目下的 ...

  9. Win10系列:UWP界面布局基础9

    在XAML中,样式.模板.画笔和动画等都被看做是资源,它们最终的作用都是相同的,就是让设计人员可以使用这些资源创建更好的视觉效果,对其设计的产品外观进行标准化统一,那么如何使用这些资源并组织和重用呢, ...

随机推荐

  1. C++.构造函数(超出范围)_01

    环境:Win7x64.Qt5.3.2 MSVC2010 OpenGL.vs2010 1.ZC:在 构造函数 中,基类访问子类的成员 会报内存错误,如果访问的是 基本类型的话(如int) 可能还不会出错 ...

  2. Grunt、Gulp区别 webpack、 requirejs区别

    1. 书写方式 grunt 运用配置的思想来写打包脚本,一切皆配置,所以会出现比较多的配置项,诸如option,src,dest等等.而且不同的插件可能会有自己扩展字段,导致认知成本的提高,运用的时候 ...

  3. js 垃圾回收机制和引起内存泄漏的操作

    垃圾回收机制 JS中最常见的垃圾回收方式是标记清除. 工作原理:是当变量进入环境时,将这个变量标记为“进入环境”.当变量离开环境时,则将其标记为“离开环境”.标记“离开环境”的就回收内存. 工作流程: ...

  4. 《剑指offer》第四十一题(数据流中的中位数)

    // 面试题41:数据流中的中位数 // 题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么 // 中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值, // ...

  5. kbengine学习1 安装

    KBengine一年前就知道了,但是没来得及学(只记得是C++ + python脚本),前一个项目unity3d+fkask+socketio+sqlite硬怼出来的.这半年也没来得及管.(好像当时看 ...

  6. Qt--信号槽传递自定义结构体参数

    自定义结构体参数的信号槽连接 (1) 对于自定义的结构体参数,信号槽无法识别参数,导致信号槽连接不起作用.所以需要注册结构体参数.在结构体中声明结束的地方加上结构体注册. struct DealDet ...

  7. web component的理解

    https://www.zhihu.com/question/58731753 https://www.zhihu.com/question/39328603 http://www.cnblogs.c ...

  8. Java 多线程 fork-join

    fork-join我们可以理解为分而治之,就是说当一个任务非常大的时候,我们可以按照一定的业务需求拆分为若干个小的任务,最后把这些小的任务再聚合起来. 下面就通过fork-join实现一个从1加到10 ...

  9. python中集合及运算

    一.集合set()的特点: 集合的特点:有的可变,有的不可变:元素无次序,不可重复. 集合中的元素不能重复,可作为一种简单高效的元素去重方式. 集合没有索引,它的元素无次序,不是序列. 利用set() ...

  10. python爬虫学习(三):使用re库爬取"淘宝商品",并把结果写进txt文件

    第二个例子是使用requests库+re库爬取淘宝搜索商品页面的商品信息 (1)分析网页源码 打开淘宝,输入关键字“python”,然后搜索,显示如下搜索结果 从url连接中可以得到搜索商品的关键字是 ...