XAML 简述

XAML(eXtensible Application Markup Language,可扩展应用程序标记语言)是微软公司创建的一种新的描述性语言,用于搭建应用程序用户界面。XAML实现了用户界面与业务逻辑完全分离。XAML是一种解析性的语言,尽管它也可以被编译。它的优点是简化编程式上的用户创建过程,应用时要添加代码和配置等。
在第1章中,对照了HTMLXAML两者的异同点。发现尽管XAML在元素的声明、程序样式的设置等语法结构上和HTML上有相似之处,但XAML有别于HTML最显著的特征是xmlns指令和标记扩展。其中,xmlns指令需要在标记中关联名称空间。
XAML并不是HTML,而是基于XML的,是WPF的外在表现形式。而HTML只是一种标记语言,仅仅是用来为浏览器呈现页面内容。XAML可以用来呈现信息和请求用户输人等基本的功能,它还支持动画和3D等高级特性。
XAML是可扩展的,开发人员可以创建自定义的控件、元素和函数来扩展XAML。由于XAML各元素在本质上就是WPF类的映射,因此开发人员可以很轻松地使用面向对象的技术对XAML元素进行扩展。也就是说,可以开发一些自定义控件和组合元素,用户界面设计人员和开发人员直接使用即可,软件真正做到了可复用性。
XAML的发音为"Zamel"。虽然XAML包含了许多新规则、元素和语法,但我们并不认为学习它是一个麻烦的过程。只要读者稍微具备一些HTML基础知识,就可以快速地掌握XAML中的大部分内容。


可扩展应用程序标记语言——XAML

  • XAML 简述
  • XAML 文档框架
    • XAML 文档结构
    • XAML 基础语法
      • 标签
      • 属性
      • 内容
  • XAML 中的属性
    • XAML 简单属性
      • 1.字符串简单赋值
      • 2.属性元素复杂赋值
    • XAML 复杂属性
    • XAML 附加属性
    • XAML 处理特殊字符和空白
      • XAML中特殊字符处理方式
  • XAML 名称空间
    • XAML 名称空间的作用
    • XAML 默认名称空间
    • XAML 名称空间的标记扩展
    • XAML 内置 XAML特性名称空间指令及含义
  • XAML 类型转换器
  • XAML 导入程序集
  • 本章小结

XAML 文档框架

创建一个新的WPF项目 WpfApp2

如何创建项目 参见之前的文章:
WPF编程基础———第一章 引言 创建一个WPF项目.

所生成的基本项目结构
我们目前分析的XAML为MainWindow.xaml,后台的cs代码等等之后都会渐渐提到

系统自动生成的代码如下:
VS2019版本自动生成的代码之中有更多默认xmlns指令

<Window x:Class="WpfApp2.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfApp2"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Grid></Grid>
</Window>

在此首先了解XAML文件基本框架,这个文档包含一个顶级元素Window和一个Grid元素。Window代表整个窗口,Grid布局上可以放置所需控件。一个XAML文件只能有一个顶级元素。
WPF中可以当顶级元素的还有Page元素和Application元素。
Page用于可导航的应用程序; Application用于定义应用程序的资源和启动设置。
分析Window开始标签,依照自上而下的顺序,它包含一个类名、五个xmlns指令关联的名称空间,三个属性(Title、Height、Width)以及一个有关于兼容性mc名称空间的指令。

XAML 文档结构

在XAML文件基本框架上,为此程序添加设计要求:在Button上放置一个Image和一个TextBox。在<Grid></Grid>之间,添加XAML代码来实现设计要求。
XAML注释方式 :<!-- -->

<!-- window 代码部分省略 --><Grid><Button Width="600" Height="400"><Button.Content><!-- 设置为垂直方向 --><StackPanel Orientation="Vertical"><Image Source="battle.jpg" Width="600" Height="375"></Image><TextBox Text="Hathaways Flash" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBox></StackPanel></Button.Content></Button></Grid>
</Window>

效果图

根据运行之后的效果图和分析代码的逻辑结构我们可以知道,Window为顶级元素,在Grid布局下有一个Button,在Button下使用StackPanel布局后加入一个Image和TextBox。
此XAML文档树形结构

#mermaid-svg-jnPduDVyQtuQt60G .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-jnPduDVyQtuQt60G .label text{fill:#333}#mermaid-svg-jnPduDVyQtuQt60G .node rect,#mermaid-svg-jnPduDVyQtuQt60G .node circle,#mermaid-svg-jnPduDVyQtuQt60G .node ellipse,#mermaid-svg-jnPduDVyQtuQt60G .node polygon,#mermaid-svg-jnPduDVyQtuQt60G .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-jnPduDVyQtuQt60G .node .label{text-align:center;fill:#333}#mermaid-svg-jnPduDVyQtuQt60G .node.clickable{cursor:pointer}#mermaid-svg-jnPduDVyQtuQt60G .arrowheadPath{fill:#333}#mermaid-svg-jnPduDVyQtuQt60G .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-jnPduDVyQtuQt60G .flowchart-link{stroke:#333;fill:none}#mermaid-svg-jnPduDVyQtuQt60G .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-jnPduDVyQtuQt60G .edgeLabel rect{opacity:0.9}#mermaid-svg-jnPduDVyQtuQt60G .edgeLabel span{color:#333}#mermaid-svg-jnPduDVyQtuQt60G .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-jnPduDVyQtuQt60G .cluster text{fill:#333}#mermaid-svg-jnPduDVyQtuQt60G div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-jnPduDVyQtuQt60G .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-jnPduDVyQtuQt60G text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-jnPduDVyQtuQt60G .actor-line{stroke:grey}#mermaid-svg-jnPduDVyQtuQt60G .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-jnPduDVyQtuQt60G .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-jnPduDVyQtuQt60G #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-jnPduDVyQtuQt60G .sequenceNumber{fill:#fff}#mermaid-svg-jnPduDVyQtuQt60G #sequencenumber{fill:#333}#mermaid-svg-jnPduDVyQtuQt60G #crosshead path{fill:#333;stroke:#333}#mermaid-svg-jnPduDVyQtuQt60G .messageText{fill:#333;stroke:#333}#mermaid-svg-jnPduDVyQtuQt60G .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-jnPduDVyQtuQt60G .labelText,#mermaid-svg-jnPduDVyQtuQt60G .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-jnPduDVyQtuQt60G .loopText,#mermaid-svg-jnPduDVyQtuQt60G .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-jnPduDVyQtuQt60G .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-jnPduDVyQtuQt60G .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-jnPduDVyQtuQt60G .noteText,#mermaid-svg-jnPduDVyQtuQt60G .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-jnPduDVyQtuQt60G .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-jnPduDVyQtuQt60G .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-jnPduDVyQtuQt60G .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-jnPduDVyQtuQt60G .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jnPduDVyQtuQt60G .section{stroke:none;opacity:0.2}#mermaid-svg-jnPduDVyQtuQt60G .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-jnPduDVyQtuQt60G .section2{fill:#fff400}#mermaid-svg-jnPduDVyQtuQt60G .section1,#mermaid-svg-jnPduDVyQtuQt60G .section3{fill:#fff;opacity:0.2}#mermaid-svg-jnPduDVyQtuQt60G .sectionTitle0{fill:#333}#mermaid-svg-jnPduDVyQtuQt60G .sectionTitle1{fill:#333}#mermaid-svg-jnPduDVyQtuQt60G .sectionTitle2{fill:#333}#mermaid-svg-jnPduDVyQtuQt60G .sectionTitle3{fill:#333}#mermaid-svg-jnPduDVyQtuQt60G .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jnPduDVyQtuQt60G .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-jnPduDVyQtuQt60G .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jnPduDVyQtuQt60G .grid path{stroke-width:0}#mermaid-svg-jnPduDVyQtuQt60G .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-jnPduDVyQtuQt60G .task{stroke-width:2}#mermaid-svg-jnPduDVyQtuQt60G .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jnPduDVyQtuQt60G .taskText:not([font-size]){font-size:11px}#mermaid-svg-jnPduDVyQtuQt60G .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jnPduDVyQtuQt60G .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-jnPduDVyQtuQt60G .task.clickable{cursor:pointer}#mermaid-svg-jnPduDVyQtuQt60G .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-jnPduDVyQtuQt60G .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-jnPduDVyQtuQt60G .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-jnPduDVyQtuQt60G .taskText0,#mermaid-svg-jnPduDVyQtuQt60G .taskText1,#mermaid-svg-jnPduDVyQtuQt60G .taskText2,#mermaid-svg-jnPduDVyQtuQt60G .taskText3{fill:#fff}#mermaid-svg-jnPduDVyQtuQt60G .task0,#mermaid-svg-jnPduDVyQtuQt60G .task1,#mermaid-svg-jnPduDVyQtuQt60G .task2,#mermaid-svg-jnPduDVyQtuQt60G .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-jnPduDVyQtuQt60G .taskTextOutside0,#mermaid-svg-jnPduDVyQtuQt60G .taskTextOutside2{fill:#000}#mermaid-svg-jnPduDVyQtuQt60G .taskTextOutside1,#mermaid-svg-jnPduDVyQtuQt60G .taskTextOutside3{fill:#000}#mermaid-svg-jnPduDVyQtuQt60G .active0,#mermaid-svg-jnPduDVyQtuQt60G .active1,#mermaid-svg-jnPduDVyQtuQt60G .active2,#mermaid-svg-jnPduDVyQtuQt60G .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-jnPduDVyQtuQt60G .activeText0,#mermaid-svg-jnPduDVyQtuQt60G .activeText1,#mermaid-svg-jnPduDVyQtuQt60G .activeText2,#mermaid-svg-jnPduDVyQtuQt60G .activeText3{fill:#000 !important}#mermaid-svg-jnPduDVyQtuQt60G .done0,#mermaid-svg-jnPduDVyQtuQt60G .done1,#mermaid-svg-jnPduDVyQtuQt60G .done2,#mermaid-svg-jnPduDVyQtuQt60G .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-jnPduDVyQtuQt60G .doneText0,#mermaid-svg-jnPduDVyQtuQt60G .doneText1,#mermaid-svg-jnPduDVyQtuQt60G .doneText2,#mermaid-svg-jnPduDVyQtuQt60G .doneText3{fill:#000 !important}#mermaid-svg-jnPduDVyQtuQt60G .crit0,#mermaid-svg-jnPduDVyQtuQt60G .crit1,#mermaid-svg-jnPduDVyQtuQt60G .crit2,#mermaid-svg-jnPduDVyQtuQt60G .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-jnPduDVyQtuQt60G .activeCrit0,#mermaid-svg-jnPduDVyQtuQt60G .activeCrit1,#mermaid-svg-jnPduDVyQtuQt60G .activeCrit2,#mermaid-svg-jnPduDVyQtuQt60G .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-jnPduDVyQtuQt60G .doneCrit0,#mermaid-svg-jnPduDVyQtuQt60G .doneCrit1,#mermaid-svg-jnPduDVyQtuQt60G .doneCrit2,#mermaid-svg-jnPduDVyQtuQt60G .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-jnPduDVyQtuQt60G .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-jnPduDVyQtuQt60G .milestoneText{font-style:italic}#mermaid-svg-jnPduDVyQtuQt60G .doneCritText0,#mermaid-svg-jnPduDVyQtuQt60G .doneCritText1,#mermaid-svg-jnPduDVyQtuQt60G .doneCritText2,#mermaid-svg-jnPduDVyQtuQt60G .doneCritText3{fill:#000 !important}#mermaid-svg-jnPduDVyQtuQt60G .activeCritText0,#mermaid-svg-jnPduDVyQtuQt60G .activeCritText1,#mermaid-svg-jnPduDVyQtuQt60G .activeCritText2,#mermaid-svg-jnPduDVyQtuQt60G .activeCritText3{fill:#000 !important}#mermaid-svg-jnPduDVyQtuQt60G .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jnPduDVyQtuQt60G g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-jnPduDVyQtuQt60G g.classGroup text .title{font-weight:bolder}#mermaid-svg-jnPduDVyQtuQt60G g.clickable{cursor:pointer}#mermaid-svg-jnPduDVyQtuQt60G g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-jnPduDVyQtuQt60G g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-jnPduDVyQtuQt60G .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-jnPduDVyQtuQt60G .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-jnPduDVyQtuQt60G .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-jnPduDVyQtuQt60G .dashed-line{stroke-dasharray:3}#mermaid-svg-jnPduDVyQtuQt60G #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-jnPduDVyQtuQt60G #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-jnPduDVyQtuQt60G #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-jnPduDVyQtuQt60G #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-jnPduDVyQtuQt60G #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-jnPduDVyQtuQt60G #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-jnPduDVyQtuQt60G #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-jnPduDVyQtuQt60G #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-jnPduDVyQtuQt60G .commit-id,#mermaid-svg-jnPduDVyQtuQt60G .commit-msg,#mermaid-svg-jnPduDVyQtuQt60G .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jnPduDVyQtuQt60G .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jnPduDVyQtuQt60G .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jnPduDVyQtuQt60G g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jnPduDVyQtuQt60G g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-jnPduDVyQtuQt60G g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-jnPduDVyQtuQt60G g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-jnPduDVyQtuQt60G g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-jnPduDVyQtuQt60G g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-jnPduDVyQtuQt60G .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-jnPduDVyQtuQt60G .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-jnPduDVyQtuQt60G .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-jnPduDVyQtuQt60G .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-jnPduDVyQtuQt60G .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-jnPduDVyQtuQt60G .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-jnPduDVyQtuQt60G .edgeLabel text{fill:#333}#mermaid-svg-jnPduDVyQtuQt60G .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-jnPduDVyQtuQt60G .node circle.state-start{fill:black;stroke:black}#mermaid-svg-jnPduDVyQtuQt60G .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-jnPduDVyQtuQt60G #statediagram-barbEnd{fill:#9370db}#mermaid-svg-jnPduDVyQtuQt60G .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-jnPduDVyQtuQt60G .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-jnPduDVyQtuQt60G .statediagram-state .divider{stroke:#9370db}#mermaid-svg-jnPduDVyQtuQt60G .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-jnPduDVyQtuQt60G .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-jnPduDVyQtuQt60G .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-jnPduDVyQtuQt60G .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-jnPduDVyQtuQt60G .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-jnPduDVyQtuQt60G .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-jnPduDVyQtuQt60G .note-edge{stroke-dasharray:5}#mermaid-svg-jnPduDVyQtuQt60G .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-jnPduDVyQtuQt60G .error-icon{fill:#522}#mermaid-svg-jnPduDVyQtuQt60G .error-text{fill:#522;stroke:#522}#mermaid-svg-jnPduDVyQtuQt60G .edge-thickness-normal{stroke-width:2px}#mermaid-svg-jnPduDVyQtuQt60G .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-jnPduDVyQtuQt60G .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-jnPduDVyQtuQt60G .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-jnPduDVyQtuQt60G .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-jnPduDVyQtuQt60G .marker{fill:#333}#mermaid-svg-jnPduDVyQtuQt60G .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-jnPduDVyQtuQt60G {color: rgba(0, 0, 0, 0.75);font: ;}

window
Grid
Button
StackPanel
Image
TextBox

应用程序的UI在用户看来是平面结构的,与传统设计结构不同的是,在后台开发者面对的XAML是树形逻辑结构的,不过Button上放置其他控件的方式有很多,但文档框架始终都是树形结构。

XAML 基础语法

XAML中最基本的语法元素与XML类似,下面回顾一下XML中的标签、属性和内容的语法。

标签

标签通常是以<>开始,以</>结束的,一一个标签的声明通常表示一个对象。 如<Window></Window><Grid></Grid>分别定义了一个窗体对象及一个Grid对象,标签定义有以下两种常用写法。
(1)非自闭合标签:如<Window></Window><Grid></Grid>,标签要成对出现。
(2)自闭合标签:如<Window /><Grid/><Button/>
这种自闭合标签用于无内容情况下,可以让代码看上去更简洁,当然,正常情况下WindowGrid都是有内容的。

属性

属性通常以键值对形式出现,形式如下。
Attribute = Value
例如,<Window></Window>标签中的"Title=“MainWindow” Height=“450” Width=“800” ",等号左边表示Window标签的属性,等号右边表示该属性的值。

内容

一组标签对之间夹杂的文本或其他标签都称为这个标签之间的内容。此处Window标签的内容就是一对<Grid></Grid>标签。


XAML 中的属性

继续使用WpfApp2这个解决方案,根据需要还会不断丰富其功能,以便配合学习讲解XAML

XAML 简单属性

XAML是声明性语言,XAML编译器给每个标签创建一个与标签对应的对象,再对其属性初始化。所以,每个标签是要先声明对象,再为对象赋初值。赋值方法有两种:一种是XAML中的字符串简单赋值,另外一种是在后台CS代码中,使用属性元素进行复杂赋值。

1.字符串简单赋值

XAML使用标签定义UI元素,每一个标签对应。NET Framework类库的一个 控件类。通过设置标签的Attribute(属性),实现标签对应的控件对象Property(属性)赋值。
首先在WpfApp2新建一个新的WPF项目:
其中Grid标签之间的代码

    <Grid><!-- 设置名称属性为rectangle 颜色为Blue 边界为左50,上75,右125,下175 --><Rectangle x:Name="rectangle" Fill="Blue" Margin="50,75,125,175"></Rectangle></Grid>

效果图
其中在VS2019切换启动项目在菜单栏下方

2.属性元素复杂赋值

在CS代码中,创建对象,并设置他们的属性,代码如下:

/*using System... 省略*/
namespace Rectangle
{/// <summary>/// MainWindow.xaml 的交互逻辑/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();SolidColorBrush scb = new SolidColorBrush();scb.Color = Colors.Yellow;this.rectangle.Fill = scb;}}
}

效果图
两种赋值方法相对照,这里需解释Fill属性的用法。因为Fill类型是Brush,但是Brush一个抽象类,由于抽象类不能实例化.所以只能用抽象类的子类实例赋值,Brush的派生类简要说明如下。

  • SolidColorBrush:使用纯Color绘制区域;
  • LinearGradientBrush:使用线性渐变绘制区城;
  • RadialGradientBrush:使用径向渐变绘制区域;
  • ImageBrush:使用图像(由ImageSource对象表示)绘制区域:
  • DrawingBrush:使用Drawing绘制区域。绘图可能包含向量和位图对象:
  • VisualBrush:使用Visual对象绘制区域,使用VisualBrush可以将内容从应用程序的一个部分复制到另一个区域,这在创建反射效果和放大局部屏幕时会非常有用。

XAML 复杂属性

在WpfApp2中加入新的设计需求: Grid的背景使用渐变色,渐变方案是:由红色到黄色,再由黄色到绿色。要实现该功能就需要对Grid.Background中的LinearGradientBrush进行设置,代码如下。

<Grid><Grid.Background><LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"><GradientStop Color="Red" Offset="0"/><GradientStop Color="Yellow" Offset="0.6"/><GradientStop Color="Green" Offset="1"/></LinearGradientBrush></Grid.Background><!-- 保留原Button后续代码 -->

效果图
根据如上所示的效果,其中代码中的Grid.Background便是复杂属性。下面介绍程序中用到的属性。
现在我们知道LinearfGradientBrush的功能是线性渐变笔刷,填充线性渐变颜色到当前区域,故可搭配两种或两种以上的颜色。
它的的重要属性有GradientStop(倾斜点)、Color(渐变颜色)、Offset(偏移量)、StartPoint(起点坐标)、EndPoint(终点坐标)。
LinearGndientBrush的渐变色是由多个GradientStop组成的,其中的ColorOffset分别表示渐变色值和颜色起始位置,Offset宽度是整个绘制区域,取值范围为0~1.0。

XAML 附加属性

继续在WpfApp2中加入新的设计需求,在Grid布局中加入一个蓝色矩形与之前的button并列

效果图如下

要实现如上的效果,首先我们需要对Grid布局中新增加一列,对<Grid.ColumnDefinitions>属性设置代码如下:

<!-- 保留之前的代码 --></Grid.Background><Grid.ColumnDefinitions><ColumnDefinition></ColumnDefinition><ColumnDefinition></ColumnDefinition></Grid.ColumnDefinitions>

要将<Rectangle>置于<Grid>的第1列,类似程序语言中的数组,Grid布局的起始行与列都是从0开始,

<!-- 保留之前的代码 --></Button><Rectangle x:Name="Rec" Grid.Column="1" Fill="Blue" Margin="25"></Rectangle></Grid>
</Window>

此例之中用的属性,<Grid.ColumnDefinitions>是复杂属性,Grid.Column="1"位于<Rectangle>内部,这就是附加属性。
这时候出现了一个疑问,以上两个属性均为Grid.的形式,但却是不同的属性,因为Grid.ColumnDefinitions这一属性隶属于Grid,他完全可以视为Grid的子标签,而Grid.Column="1"是在<Rectangle>内部,用来设置Rectangle标签的。他并非真正的属性,被转为调用Get.SetColumn() 方法来实现,之后会发现附件属性全部在控件布局之中。

XAML 处理特殊字符和空白

在XAML中,可以让一些特殊字符作为元素的内容出现,例如,之前Button中的Hathaways Flash要变成<Hathaways Flash>显示,需要修改TextBox标签中的Text="&lt;Hathaways Flash&gt;"

XAML中特殊字符处理方式

特殊字符 处理方式 特殊字符 处理方式
< &lt; & &amp;
> &gt; " &auot;

在XAML中处理特殊字符并不难,但还存在一个关键问题——空白的处理。
在默认情况下,XAML忽略所有的空白,这就意味着空格、Tab键、硬回车、带有多个空格的长字符串被转换为单个空格。有时放在文本中的空格,希望输出,例如,文本框中输出带尖括号及空格的字符,如< Hathaways Flash >,则需要修改代码如下,

<TextBox Text="&lt; Hathaways Flash &gt;" xml:space="preserve" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBox>

在保留空格的元素(TextBox)中使用" xml:spac= “preserve””, Text属性中的空格被保留输出。事实上" xml:spac= “preserve”"特性是XML标准的一部分。


XAML 名称空间

我们来继续学习并介绍XAML文件根标记中的两个默认XAML名称空间映射及其用意,同时还将说明如何生成类似的映射,便于用在代码中或单独的程序集中定义的元素。

XAML 名称空间的作用

开发语言会将常用功能以类的形式封装,开发人员根据业务需求,也会封装符合自身业务需求的类,有序组织这些类。这样,一方面,便于开发人员准确调用;另一方面,编译器可以有效地识别具有相同命名的类,就引入了名称空间。
名称空间是通过类似树形结构来组织各种类,是一种较为有效的类名排列方式。
XAML和.NET其他语言一样,也是通过名称空间有效地组织XAML内部的相关元素类,但是XAML的名称空间与. NET中的名称空间不是一对一的映射关系 ,而是一对多映射。

XAML 默认名称空间

在之前我们建立的WPF项目的XAML文档结构之中,了解到系统默认的名称空间的代码如下,

<Window x:Class="WpfApp2.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfApp2"mc:Ignorable="d"Title="MainWindow" Height="450" Width="1300">

XAML名称空间是XML名称空间概念的扩展。xmlns是XML-Namespace的缩写,看起来类似“网址”,但在浏览器中无法打开,所以它并不是网址。它是遵循XAML解析器标准的命名规则,是声明程序集和.NET名称空间的引用。

  • 其中,“xmlns=“http://schemas.microsoft.com/winfx/2006/xaml/presentation”"与.NET的名称空间中的System.Windows下的类相对应,包含XAML基本的布局和控件。
  • 带x的“xmlns:x=“http://schemas.microsoft.com/winfx/2006/xaml”"对应一些XAML语法和编译相关的CLR名称空间。
  • 带d的“xmlns:d="http://schemas.microsoft.com/expression/blend/2008""是让我们在写xaml文件时看到控件的大小。
  • 带mc的“xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006""关于程序兼容性的控制
  • 带loacl的“xmlns:local=“clr-namespace:WpfApp2””对应本地项目的名称空间
  • mc:Ignorable="d"的意思就是告诉编辑器(VS2019)在项目运行时忽略命名空间d设置的大小

为了避免概念上的混淆,在此,对C#、CLR与.NET简要说明一下。在人们做开发时,常会使用C#语言,它是. NET的核心开发语言; . NET(.NET Framework)是一个运行时平台;CLR(Common Language Runtime)是公共语言运行库,与Java虚拟机(JVM)一样是一个运行时环境,它负责资源管理(内存分配和垃圾收集等),确保应用和底层操作系统之间必要的分离。正是因为有了CLR,所以.NET成为一个跨语言的集成开发平台。

XAML 名称空间的标记扩展

标记扩展是XAML的重要特性,它放在一对花括号{}中,使用类似对象标签的方式来精确解析。
现在增加新的设计需求:设置矩形框的颜色为紫色。简单的方法是Fill= “Violet” ,但是我们现在用标记扩展来实现。先设置窗体资源,代码如下。

<!--保留Window代码--><Window.Resources><SolidColorBrush x:Key="bg" Color="Violet"    /></Window.Resources><Grid>
<!--保留后续代码-->

再修改Rectangle的Fill,代码如下。

<Rectangle x:Name="Rec" Grid.Column="1" Fill ="{StaticResource bg}" Margin="25"></Rectangle>

运行代码后,效果图如下。Fill使用标记扩展来赋值。

XAML 内置 XAML特性名称空间指令及含义

XAML 名称空间指令 含 义 示 例
x:Array 创建CLR数组 < x;ArrayType= “(x:Type Button)”>
< Button/>
< Button/>
</x:Array >
x:Class 定义的类名 < Window
x:Class =”MainWindow">…
</ Window >
x:ClassModifier 定义类型的模式Public、Internal < Window…
x:Class = " MainWindow">…
x:ClassModifier = " Pubie"…
</ Window >
x:Code XAML中内嵌代码 < x:Code >
Public void SomeMethod(){}
</x:Code >
x:Key 包含在字典中的元素键 < Window. Resources >
< SolidColorBrush x: Key = “bg”…/>
</Window. Resources >
x:Name 指定元素的编程名 < Rectangle x:Name= “Rec” …/>
x:Null 创建一个空值 < TextBox Text= "{x:Null} ">
x:Static 静态字段和属性值 < Button background = “{Statie…)”/>
x:Type 提供CLR类型 < ControlTemplate >
TargetType= "{x:Type Button} "
< /ControlTemplate >
x:TypeArguments 为实例化泛型类型指定泛型类型的参数 < object x: Class = " namespace. classname"
x:TypeArguments="{x; Type type1}
[,{x: Type type2},{x:Type type3… }]">< /object>
x:XData XAML指令元素 主要用作 XmlDataProvider 的子对象
或 XmIDataProvider.XmlSerializer属性的子对象

XAML 类型转换器

XAML的属性元素赋值形式为。Attribute = Value此处的Value是一个String类型但在后台CS代码中,对象的属性(Property)类型不一定是String类型。为了解决XAML与CS代码中的数据类型不统一,使用TypeConverter类。这个类的功能是:将值类型转换为其他类型,如可以把字符串转换成对象。

  • 现在在WpfApp2中新增需求,在CS中创建Teacher类,Teacher中有Name和Student两个属性,其中Name类型是String,Student类型是Teacher;XAML中的Button按下后弹出一个消息框,消息框中的显示内容为“I AM THE FLASH”。其中,消息框调用方式为Teacher.Student.Name

首先是在后台CS代码中创建Teacher类,
变更XAML中的代码如下:

<!--保留Window代码--><Window.Resources><local:Teacher x:Key="teacher" Student="I AM THE FLASH"/><SolidColorBrush x:Key="bg" Color="Violet" /></Window.Resources>
<!--保留Window代码--><Button Name="Btn" Width="600" Height="400" Click="Btn_Click">
<!--保留Window代码-->

在给Button加入Click后在MainWindow.xaml.cs之中的Btn_Click方法中编辑事件代码

        private void Btn_Click(object sender, RoutedEventArgs e){Teacher t = (Teacher)this.FindResource("teacher");MessageBox.Show(t.Student.Name);}

这时候运行代码点击按钮报错

错误XDG0028    “Teacher”的 TypeConverter 不支持从字符串进行转换。

而这个问题的解决方案是通过TypeConverter派生用户自定义类,重载该类的ConvertForm方法。该方法中有一个Value,他是在XAML中进行设置的,再把这个Value转成用户期望的数据类型。下面创建一个将String转换成Teacher的用户自定义类,将这个类命名为StringToTeacherTypeConverter

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel; // ADD new NameSpacenamespace WpfApp2
{class StringToTeacherTypeConverter:TypeConverter{public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value){if (value is string){Teacher t = new Teacher();t.Name = value as string;return t;}return base.ConvertFrom(context, culture, value);}}
}

之后修改Teacher.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;namespace WpfApp2
{[TypeConverterAttribute(typeof(StringToTeacherTypeConverter))]public class Teacher{public string Name{ get; set; }public Teacher Student { get; set; }}
}

现在运行代码,单击Button,弹出消息框,效果图如下
此处可以把TypeConverterAttribute中的Attribute省去,因为特征类在使用时可省略Attribute


XAML 导入程序集

在项目开发时,一个项目由多个模块构成,模块之间可以相互调用。在用VisualStudio2019创建的解决方案下,每个项目都可以独立编译,独立编译的结果就得到一个程序集。常见的程序集包括exe(可执行文件)和dII(Dynamic Link Library动态链接库)。这里说的“导入程序集”是指dll类型。程序集要放在合适的名称空间下,名称空间解决不同模块类名相同问题。
在XAML中导人程序集。设用户自定义的程序集名为UserLibrary.dlI,它有CommCont两个名称空间,在XAML中引用这两个名称空间的语法格式如下。

xmlns:映射名= "clr - namespace:名称空间;assembly=程序集名"

接下来根据语法格式,在程序集UserLibrary.dll中的两个名称空间对应的XAML引用为:

xmlns:cont= "clr - namespace :Comm; assembly = UserLibrary"
xmlns:cont= "clr - namespace :Cont; assembly = UserLibrary"

在XAML文档添加引用后,就可以使用名称空间中的类,语法格式如下。

<映射名:类名>...</映射名:类名>
<comm:类名></comm:类名>
<cont:类名></cont:类名>

这个例子只是简单引入,后面会详细说明。


本章小结

本章节从XAML文档框架开始,让我们认识到UI的平面结构对应着XAML文档的树形结构。XAML是可扩展的应用程序声明式语言,它是基于XML的,所以XAML中的标签、属性、内容语法结构与XML有相似之处。我们所写的案例从Button上放置Image、TextBox的例子开始,通过分层叠加式案例,逐步地讲解XAML的复杂属性、附加属性、xmIns指令和名称空间中的标记扩展,并使用TypeConverter类把字符串转换成对象。还讲解了项目开发时,在XAML导入程序集的语法。倘若在学习中,有些内容不懂,可以跳过,当遇到具体应用后,回过头来阅读,会恍然大悟。对XAML语法知识有所了解以后,便可以用它来创建用户界面了。


相关阅读
上一篇:WPF编程基础入门 ——— 第一章 引言.
下一篇:WPF编程基础入门 ——— 第三章 布局(一)布局原则.
WPF编程基础入门 ——— 目录导航.

WPF编程基础入门 ——— 第二章 XAML相关推荐

  1. WPF编程基础入门 ——— 第三章 布局(五)布局面板WrapPanel

    WPF布局--布局面板WrapPanel WPF--WrapPanel布局控件 WrapPanel实例--十个按钮 WPF--WrapPanel布局控件 WrapPanel(自动折行面板),允许任意多 ...

  2. Java基础入门第二章

    大二学的java,一个假期过去,学的差不多都忘光了,在这里再重学一遍,也算不上重学吧,相当于复习吧.第一章讲的是jdk及开发工具的安装,这里就不多赘述了,废话不多说,我们直接从第二章开始. 2.1Ja ...

  3. 并发编程基础篇——第二章(如何创建线程)

    上节讲了基础概念,本章正式进入线程专题,对基础薄弱的同学可以好好看本章!! 1.Thread匿名子类 我们可以通过下面的代码来直接创建一个线程. // 构造方法的参数是给线程指定名字,推荐 Threa ...

  4. Java编程基础篇第二章

    关键字 概述:被Java语言赋予特定含义的单词. 特点:组成关键字的字母全部为小写字母. 标识符 概述:给类,接口,包,方法,常量起名字时的字符序列 组成规则:英文大小写字母,数字,$和- 命名规则. ...

  5. Java基础入门第二章答案

    一.填空题 1. true和false 2. 基本数据类型.引用数据类型 3. & && | || 4. 5 5. 56 二.判断题 1. 错 2.对 3.错 4.对 5.错 ...

  6. 《DirectX 9.0 3D游戏开发编程基础》 第二章 绘制流水线 读书笔记

    模型的表示 场景:物品或模型的集合 任何物品都可以用三角形网络逼近表示.我们经常用以下术语描述三角形网络:多边形(polygons).图元(primitives).网络几何单元(mesh geomet ...

  7. py系统学习笔记:第七阶段:网页编程基础:第二章:CSS3:23.文本、表格属性

    目录 文本属性 设置文本对齐方式 代码:左.右.中 效果: 设置文本的修饰方式 代码:下划线.上划线.删除线 效果: 设置文本大小写 代码:每个单词开头大写,全部大写,全部小写 效果: 设置文本的首行 ...

  8. JavaSE入门0基础笔记 第二章Java基础语法

    JavaSE入门0基础笔记 第二章Java基础语法 1.运算符 1.1算术运算符 1.1.1运算符和表达式 1.1.2 算术运算符 1.1.3字符的"+"操作 1.1.4 字符串中 ...

  9. python快乐编程—基础入门-从萌新到大神必读书籍 《Python快乐编程基础入门》...

    2019年,全球信息化进程持续加快,IT行业繁荣发展.作为新时代IT人,不仅需要强大的理论知识,更需要过硬的技术.Python作为最受欢迎的编程语言之一,作为人工智能时代的首选语言,因其受众多.用途广 ...

最新文章

  1. 面试必备的C++知识(未完待续)
  2. 年度书单盘点 | “裁员潮”持续蔓延?职场没有铁饭碗,只有硬技能
  3. Android内存优化大全(中)
  4. 单元测试框架之unittest(一)
  5. 能简单才不简单,仿Flickr.com:基于Flash+jQuery的一次性划选多文件并上传
  6. 第四范式恭祝大家新春快乐!
  7. Tomcat 配置 Context
  8. [New Portal]Windows Azure Virtual Machine (14) 在本地制作数据文件VHD并上传至Azure(1)
  9. layui数据表格(一:基础篇,数据展示、分页组件、表格内嵌表单和图片)
  10. 浅谈MVP与Model-View-ViewModel(MVVM)设计模式
  11. lnmp修改mysql上传大小限制_安装Linux+Nginx+MySQL+PHP(LNMP)集成环境,解除上传文件大小限制...
  12. Docker-Compose快速搭建Oracle-12C系统
  13. 库克发文纪念苹果成立45周年:伟大使命还有待实现
  14. html5自动生成图片,HTML5拖放API如何实现自动生成相框功能 HTML5拖放API实现自动生成相框功能代码...
  15. startService和onBinderService混合开发音乐播放器
  16. @程序员,你真得了解每天打交道的字节吗?
  17. CentOS7.6新增或修改SSH端口号的步骤
  18. 软件开发项目流程 - 立项
  19. 快速排序C语言代码+辅助图+注释
  20. 计算机网络教程网线制作,网线水晶头制作过程详解(视频+图文教程)

热门文章

  1. CSS动画——行走的小人
  2. 大创项目-薅羊毛-day10
  3. Ktolin-Android studio调用蓝牙模块stepbystep
  4. 【规则引擎】一、规则引擎简介
  5. ANSYS ICEM CFD三维非结构网格生成实例——教室吊顶空调送回风
  6. java计算机毕业设计至臻阁古董拍卖网源码+数据库+系统+lw文档+mybatis+运行部署
  7. 大一新生计算机课程学情分析,大一计算机基础课程论文
  8. Samsung eMCP LPDDR 2系列
  9. MT4-EA自动化交易研究笔记(2022-04-28)
  10. javaweb 签到 功能实现 mysql_java web小项目:记录签到系统