热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

WPF学习笔记4.XAML

Microsoft将XAML定义为简单、通用、声明式的编程语言。这意味着我们会在更多的地方看到它(比如Silverlight),而且它显然比其原始版本

Microsoft 将 XAML 定义为 "简单"、"通用"、"声明式" 的 "编程语言"。这意味着我们会在更多的地方看到它(比如 Silverlight),而且它显然比其原始版本 XML (XAML 是一种基于 XML 且遵循 XML 结构规则的语言) 多了更多的逻辑处理手段。如果愿意的话,我们完全可以抛开 XAML 来编写 WPF 程序。只不过这有点类似用记事本开发 .NET 程序的意味,好玩不好用。XAML 的定义模式使得非编程人员可以用 "易懂" 的方式来刻画 UI,并且这种方式我们早已熟悉,比如 WebForm,亦或者是我一直念念不忘的 Delphi Form (偶尔想起而已,其实早将 Object Pascal 忘得精光了)。

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Window1">
  
  



这是一个非常简单的 XAML,它定义了一个空白 WPF 窗体(Window)。XAML 对应于 .NET 代码,只不过这个过程由特定的 XAML 编译器和运行时解释器完成。当解释器处理上面这段代码时,相当于:

new Window1 { Title = "Window1" };


从这里我们可以体会两者的区别,用 XAML 的好处是可以在设计阶段就能看到最终的展现效果,很显然这是美工所需要的。你可以从 VS 命令行输入 "xamlpad.exe",这样你会看到直观的效果。

作为一种应用于 .NET 平台的 "语言",XAML 同样支持很多我们所熟悉也是必须的概念。

1. Namespace

XAML 默认将下列 .NET Namespace 映射到 "http://schemas.microsoft.com/winfx/2006/xaml/presentation":

System.Windows
System.Windows.Automation
System.Windows.Controls
System.Windows.Controls.Primitives
System.Windows.Data
System.Windows.Documents
System.Windows.Forms.Integration
System.Windows.Ink
System.Windows.Input
System.Windows.Media
System.Windows.Media.Animation
System.Windows.Media.Effects
System.Windows.Media.Imaging
System.Windows.Media.Media3D
System.Windows.Media.TextFormatting
System.Windows.Navigation
System.Windows.Shapes

除了这个包含绝大多数 WPF 所需类型的主要命名空间外,还有一个是 XAML 专用的命名空间 (System.Windows.Markup) —— "http://schemas.microsoft.com/winfx/2006/xaml"。使用非默认命名空间的语法有点类似于 C# Namespace Alias, 我们需要添加一个前缀,比如下面示例中的 "x"。

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Window1">
  
    
  



我们还可以引入 CLR Namespace。

  xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"
  xmlns:sys="clr-namespace:System;assembly=mscorlib">
  1


2. Property

我们可以用下面两种方式来设置 XAML 元素的属性。

方式1


 

方式2



WPF 会按下列顺序将 XAML 中的属性字符串转换为实际属性值。

(1) 属性值以大括号开始,或者属性是从 MarkupExtension 派生的元素,则使用标记扩展处理。
(2) 属性用指定的 TypeConverter 声明的,或者使用了转换特性(TypeConverterAttribute),则提交到类型转换器。
(3) 尝试基元类型转换,包括枚举名称检查。


  


3. TypeConverter

WPF 提供了大量的类型转换器,以便将类似下面示例中的 Red 字符串转换城 SystemWindows.Media.Brushes.Red。



等价于

this.label10.Foreground = System.Windows.Media.Brushes.Red;


不过下面的代码更能反应运行期的实际转换行为

var typeConverter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(Brush));
this.label10.Foreground = (Brush)typeConverter.ConvertFromInvariantString("Red");


有关转换器列表,可参考:ms-help://MS.MSDNQTR.v90.chs/fxref_system/html/35bffd5f-b9aa-1ccd-99fe-b0833551e562.htm

4. MarkupExtension

对 XAML 的一种扩展,以便支持复杂的属性值。这些标记扩展通常继承自 MarkupExtension,并使用大括号包含。WPF 提供了一些常用的标记扩展,诸如 NullExtension、StaticExtension、DynamicResourceExtension、 StaticResourceExtension、Binding 等。和 Attribute 规则类似,我们通常可以省略 Extension 这个后缀。需要注意的是某些标记扩展属于 System.Windows.Markup,因此我们需要添加命名空间前缀。

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Window1">
  
    
  



我们可以为标记扩展提供其所需的构造参数。

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Window1">
  
    



这 个例子中,我们将 System.Windows.SystemParameters.IconHeight 值作为参数传递给 "public StaticExtension(string member)" 构造方法,这种参数通常被称作定位参数。而另外一种参数是将特定的值传给标记扩展对象属性,语法上必须指定属性名称,故被称之为命名参数。下面的例子表示 将 textBox1.Text 参数绑定到 Label.Content 上,这样当编辑框内容发生变化时,标签内容自动保持同步。

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Window1">
  
    
    



标记扩展允许嵌套,并可以引用自身。我们看另外一个例子。

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Window1">
  
    
  



这个例子的意思是将 TextBox.Text 内容绑定为其自身(Self)的高度值(Width)。

标记扩展带来一个问题就是大括号的转义,毕竟很多时候我们需要在内容显示中使用它。解决方法是在前面添加一对额外的大括号。

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Window1">
  
    



如果觉得难看,也可以写成下面这样。

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Window1">
  
    
  



5. Content

XAML 这点和 HTML 非常类似,我们可以将任何内容添加到元素内容项中,这带来更加丰富的 UI 表达能力,再也不像 WinForm 那样 "能做什么,不能做什么"。



有一点需要注意,内容项并不一定就是 Content。像 ComboBox、ListBox、TabControl 使用 Items 作为内容项。

6. XamlReader & XamlWriter

通 常情况下,XAML 在项目编译时会被压缩成 BAML (Binary Application Markup Language) 保存到资源文件中。BAML 只是包含 XAML 的纯格式声明,并没有任何事件之类的执行代码,切记不要和 MSIL 相混淆。XAML 运行期解释器解读 BAML 并生成相应的元素对象。

System.Windows.Markup 命名空间中提供了 XamlReader、XamlWriter 两个类型,允许我们手工操控 XAML 文件。

var window = (Window)XamlReader.Parse("");
window.ShowDialog();


当然,我们还可以从文件流中读取。

using (var stream = new FileStream(@"test.xaml", FileMode.Open))
{
  var window = (Window)XamlReader.Load(stream);

  var button = (Button)window.FindName("btnOK");
  button.Click += (s, ex) => MessageBox.Show("Hello, World!");

  window.ShowDialog();
}


test.xaml

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Window2" Height="300" Width="300">
  
    
  



需要注意的是 XamlReader 载入的 XAML 代码不能包含任何类型(x:Class)以及事件代码(x:Code)。

我们可以用 XamlWriter 将一个编译的 BAML 还原成 XAML。

var xaml = XamlWriter.Save(new Window2());
MessageBox.Show(xaml);


输出:

  Title="Window2" Width="300" Height="300"
  xmlns="clr-namespace:Learn.WPF;assembly=Learn.WPF"
  xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  
    OK
  



XAML 的动态载入在使用动态皮肤场景时非常有用,现在只要了解一下即可。


推荐阅读
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 加密世界下一个主流叙事领域:L2、跨链桥、GameFi等
    本文介绍了加密世界下一个主流叙事的七个潜力领域,包括L2、跨链桥、GameFi等。L2作为以太坊的二层解决方案,在过去一年取得了巨大成功,跨链桥和互操作性是多链Web3中最重要的因素。去中心化的数据存储领域也具有巨大潜力,未来云存储市场有望达到1500亿美元。DAO和社交代币将成为购买和控制现实世界资产的重要方式,而GameFi作为数字资产在高收入游戏中的应用有望推动数字资产走向主流。衍生品市场也在不断发展壮大。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • WPF开发心率检测大数据曲线图的高性能实现方法
    本文介绍了在WPF开发中实现心率检测大数据曲线图的高性能方法。作者尝试过使用Canvas和第三方开源库,但性能和功能都不理想。最终作者选择使用DrawingVisual对象,并结合局部显示的方式实现了自己想要的效果。文章详细介绍了实现思路和具体代码,对于不熟悉DrawingVisual的读者可以去微软官网了解更多细节。 ... [详细]
  • 使用eclipse创建一个Java项目的步骤
    本文介绍了使用eclipse创建一个Java项目的步骤,包括启动eclipse、选择New Project命令、在对话框中输入项目名称等。同时还介绍了Java Settings对话框中的一些选项,以及如何修改Java程序的输出目录。 ... [详细]
  • 通过Anaconda安装tensorflow,并安装运行spyder编译器的完整教程
    本文提供了一个完整的教程,介绍了如何通过Anaconda安装tensorflow,并安装运行spyder编译器。文章详细介绍了安装Anaconda、创建tensorflow环境、安装GPU版本tensorflow、安装和运行Spyder编译器以及安装OpenCV等步骤。该教程适用于Windows 8操作系统,并提供了相关的网址供参考。通过本教程,读者可以轻松地安装和配置tensorflow环境,以及运行spyder编译器进行开发。 ... [详细]
author-avatar
儒雅的aaaaaaaaaaa
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有