XAML – 快速指南
XAML – 快速指南
XAML – 概述
XAML 代表可扩展应用程序标记语言。它是一种基于 XML 的简单的声明性语言。
-
在 XAML 中,创建、初始化和设置具有层次关系的对象的属性非常容易。
-
它主要用于设计GUI。
-
它也可以用于其他目的,例如,在 Workflow Foundation 中声明工作流。
XAML 可用于 WPF(Windows Presentation Foundation)、Silverlight、Mobile Development 和 Windows Store App 等不同平台。它可以跨不同的 .Net 框架和 CLR(公共语言运行时)版本使用。
XAML 的工作原理
XAML 是一种声明性语言,它定义了您想要做什么和如何做。XAML 处理器负责找出HOW部分。让我们看看下面的架构。它总结了事物的 XAML 方面 –
该图说明了以下操作 –
-
XAML 文件由特定于平台的 XAML 处理器解释。
-
XAML 处理器将 XAML 转换为描述 UI 元素的内部代码。
-
内部代码和 C# 代码通过部分类定义链接在一起,然后 .NET 编译器构建应用程序。
XAML 的优点
我们所有人在 GUI 设计中面临的长期问题之一可以通过使用 XAML 来解决。它可用于设计 Windows 窗体应用程序中的 UI 元素。
在早期的 GUI 框架中,应用程序的外观和行为方式之间没有真正的分离。GUI 及其行为都是用相同的语言创建的,例如 C# 或 VB.net,这需要开发人员付出更多努力来实现 UI 及其相关行为。
使用 XAML,很容易将行为与设计器代码分开。因此,XAML 程序员和设计人员可以并行工作。XAML 代码非常易于阅读和理解。
XAML – 环境设置
微软为 XAML 提供了两个重要的工具 –
- 视觉工作室
- 表情混合
目前,这两种工具都可以创建 XAML,但事实是开发人员更多地使用 Visual Studio,而设计人员仍然更频繁地使用 Expression Blend。
Microsoft 提供了免费版本的 Visual Studio,可以从https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx下载
注意– 对于本教程,我们将主要使用 WPF 项目和 Windows Store 应用程序。但是免费版的 Visual Studio 不支持 Windows Store App。因此,为此,您将需要 Visual Studio 的许可版本。
安装
按照下面给出的步骤在您的系统上安装 Visual Studio –
-
下载文件后,运行安装程序。将显示以下对话框。
-
单击安装按钮,它将开始安装过程。
-
安装过程成功完成后,您将看到以下屏幕。
-
如果需要,关闭此对话框并重新启动计算机。
-
现在从开始菜单打开 Visual Studio,它将显示以下对话框。第一次需要一些时间,只为准备。
完成所有操作后,您将看到 Visual Studio 的主窗口。
实施的第一步
让我们从一个简单的实现开始。按照下面给出的步骤 –
-
单击文件 → 新建 → 项目菜单选项。
-
将显示以下对话框 –
-
在模板下,选择 Visual C# 并选择 WPF 应用程序。为项目命名,然后单击“确定”按钮。
-
在 mainwindow.xaml 文件中,默认写入以下 XAML 标记。在本教程后面,您将了解所有这些标签。
<Window x:Class = "FirstStepDemo.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:FirstStepDemo" mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604"> <Grid> </Grid> </Window>
默认情况下,网格被设置为页面后的第一个元素。
让我们在 Grid 元素下添加一个按钮和一个文本块。这称为对象元素语法,左尖括号后跟我们要实例化的名称,例如按钮,然后定义内容属性。分配给内容的字符串将显示在按钮上。现在将按钮的高度和宽度分别设置为 30 和 50。同样初始化 Text 块的属性。
现在看看设计窗口。你会看到一个按钮。现在按 F5 执行此 XAML 代码。
<Window x:Class = "FirstStepDemo.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:FirstStepDemo" mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604"> <Grid> <Button Content = "First Button" Height = "30" Width = "80"/> <TextBlock Text = "Congratulations you have successfully build your first app" Height = "30" Margin = "162,180,122,109"/> </Grid> </Window>
当您编译并执行上述代码时,您将看到以下窗口。
恭喜!您已经设计了您的第一个按钮。
在 MAC OS 上编写 XAML 应用程序
XAML 应用程序也可以在 Mac 上开发。在 Mac 上,XAML 可用作 iOS 和 Android 应用程序。要在 Mac 上设置环境,请访问www.xamarin.com。单击产品并选择 Xamarin 平台。下载 Xamarin Studio 并安装它。它将允许您为各种平台开发应用程序。
XAML – C# 语法
在本章中,您将学习编写 XAML 应用程序的基本 XAML 语法/规则。让我们看一个简单的 XAML 文件。
<Window x:Class = "Resources.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "525"> <Grid> </Grid> </Window>
正如您在上面的 XAML 文件中看到的,有不同种类的标记和元素。下表简要描述了所有元素。
Sr.No | 元素和描述 |
---|---|
1 |
<Window 它是根的开放对象元素或容器。 |
2 |
x:Class=”Resources.MainWindow” 分部类声明将标记连接到其中定义的分部类代码。 |
3 |
xmlns 映射 WPF 客户端/框架的默认 XAML 命名空间 |
4 |
xmlns:x XAML 语言的 XAML 命名空间,将其映射到 x: 前缀 |
5 |
> 根对象元素的结尾。 |
6 |
<Grid> </Grid> 空网格对象的开始和结束标记。 |
7 |
</Window> 关闭对象元素 |
对象元素的语法规则
XAML 的语法规则几乎类似于 XML。如果您查看 XAML 文档,您会注意到它实际上是一个有效的 XML 文件。但是,XML 文件不能是有效的 XAML 文件。这是因为在 XML 中,属性的值必须是字符串,而在 XAML 中,它可以是不同的对象,称为属性元素语法。
-
Object 元素的语法以左尖括号 (<) 开头,后跟对象的名称,例如 Button。
-
定义该对象元素的一些属性和属性。
-
Object 元素必须以正斜线 (/) 结束,后跟右尖括号 (>)。
没有子元素的简单对象示例 –
<Button/>
具有某些属性的对象元素示例 –
<Button Content = "Click Me" Height = "30" Width = "60"/>
定义属性的替代语法示例(属性元素语法) –
<Button> <Button.Content>Click Me</Button.Content> <Button.Height>30</Button.Height> <Button.Width>60</Button.Width> </Button>
带有子元素的对象示例 – StackPanel 包含 Textblock 作为子元素
<StackPanel Orientation = "Horizontal"> <TextBlock Text = "Hello"/> </StackPanel>
XAML 与 C# 代码
您可以使用 XAML 来创建、初始化和设置对象的属性。也可以使用编程代码执行相同的活动。
XAML 只是设计 UI 元素的另一种简单易行的方法。使用 XAML,由您决定是要在 XAML 中声明对象还是使用代码声明它们。
让我们举一个简单的例子来演示如何用 XAML 编写 –
<Window x:Class = "XAMLVsCode.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "525"> <StackPanel> <TextBlock Text = "Welcome to XAML Tutorial" Height = "20" Width = "200" Margin = "5"/> <Button Content = "Ok" Height = "20" Width = "60" Margin = "5"/> </StackPanel> </Window>
在这个例子中,我们创建了一个带有一个按钮和一个文本块的堆栈面板,并定义了按钮和文本块的一些属性,如高度、宽度和边距。当上面的代码被编译和执行时,它会产生以下输出 –
现在看一下用 C# 编写的相同代码。
using System; using System.Text; using System.Windows; using System.Windows.Controls; namespace XAMLVsCode { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); // Create the StackPanel StackPanel stackPanel = new StackPanel(); this.Content = stackPanel; // Create the TextBlock TextBlock textBlock = new TextBlock(); textBlock.Text = "Welcome to XAML Tutorial"; textBlock.Height = 20; textBlock.Width = 200; textBlock.Margin = new Thickness(5); stackPanel.Children.Add(textBlock); // Create the Button Button button = new Button(); button.Content = "OK"; button.Height = 20; button.Width = 50; button.Margin = new Thickness(20); stackPanel.Children.Add(button); } } }
上述代码编译执行后,会产生如下输出。请注意,它与 XAML 代码的输出完全相同。
现在您可以看到使用和理解 XAML 是多么简单。
XAML 对比 网络
在本章中,我们将在 VB.Net 中编写相同的示例,以便熟悉 VB.Net 的人也可以了解 XAML 的优点。
让我们再看看用 XAML 编写的同一个例子 –
<Window x:Class = "XAMLVsCode.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <StackPanel> <TextBlock Text = "Welcome to XAML Tutorial with VB.net" Height = "20" Width = "220" Margin = "5"/> <Button Content = "Ok" Height = "20" Width = "60" Margin = "5"/> </StackPanel> </Window>
在本例中,我们创建了一个带有按钮和文本块的堆栈面板,并定义了按钮和文本块的一些属性,例如高度、宽度和边距。当上面的代码被编译和执行时,它会产生以下输出 –
现在看看用 VB.Net 编写的相同代码 –
Public Class MainWindow Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) Dim panel As New StackPanel() panel.Orientation = Orientation.Vertical Me.Content = panel Dim txtInput As New TextBlock txtInput.Text = "Welcome to XAML Tutorial with VB.net" txtInput.Width = 220 txtInput.Height = 20 txtInput.Margin = New Thickness(5) panel.Children.Add(txtInput) Dim btn As New Button() btn.Content = "Ok" btn.Width = 60 btn.Height = 20 btn.Margin = New Thickness(5) panel.Children.Add(btn) End Sub End Class
编译并执行上述代码时,输出与 XAML 代码的输出完全相同。
您现在可以想象与 VB.Net 相比,使用 XAML 是多么简单。
在上面的例子中,我们已经看到我们在 XAML 中可以做的事情也可以在其他过程语言中完成,比如 C# 和 VB.Net。
让我们看一下另一个示例,在该示例中我们将同时使用 XAML 和 VB.Net。我们将在 XAML 中设计一个 GUI,行为将在 VB.Net 中实现。
在这个例子中,一个按钮被添加到主窗口。当用户单击此按钮时,它会在消息框上显示一条消息。这是 XAML 中的代码,其中使用一些属性声明了 Button 对象。
<Window x:Class="MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <Grid> <Button Name = "btn" HorizontalAlignment = "Center" Width = "60" Height = "30" Content = "Click Me" /> </Grid> </Window>
在VB.Net中,实现了按钮点击事件(行为)。此事件在消息框上显示消息。
Public Class MainWindow Private Sub btn_Click(sender As Object, e As RoutedEventArgs) Handles btn.Click MessageBox.Show("Button is Clicked") End Sub End Class
编译并执行上述代码后,将显示以下屏幕 –
现在点击上面写着“点击我”的按钮。它将显示以下消息 –
XAML – 构建块
本章将介绍 XAML 应用程序的一些基本和重要的构建块。它将解释如何
- 创建和初始化一个对象,
- 可以使用资源、样式和模板轻松修改对象,
- 通过使用变换和动画使对象具有交互性。
对象
XAML 是一种典型的声明性语言,可以创建和实例化对象。它是另一种基于 XML 描述对象的方式,即需要创建哪些对象以及在执行程序之前应该如何初始化它们。对象可以是
- 容器(堆栈面板、停靠面板)
- UI 元素/控件(按钮、文本框等)
- 资源词典
资源
资源通常是与某个对象相关联的定义,这些对象只是您预计会经常使用不止一次。它能够在本地为控件或当前窗口或为整个应用程序全局存储数据。
样式
XAML 框架提供了多种策略来个性化和自定义应用程序的外观。样式使我们能够灵活地设置对象的某些属性,并在多个对象中重用这些特定设置以获得一致的外观。
- 在样式中,您只能设置对象的现有属性,例如高度、宽度、字体大小等。
- 只能指定控件的默认行为。
- 可以将多个属性添加到样式中。
在第一个图中,您可以看到三个按钮分别设置了相同的高度和宽度属性;但是在第二个图中,您可以看到所有按钮的高度和宽度都相同,它们被添加到一个样式中,然后该样式与所有按钮相关联。
模板
模板描述了控件的整体外观和视觉外观。对于每个控件,都有一个与之关联的默认模板,用于为该控件提供外观。在 XAML 中,当您想要自定义控件的视觉行为和视觉外观时,您可以轻松创建自己的模板。
在下面的屏幕截图中,有两个按钮,一个是模板,另一个是默认按钮。
现在,当您将鼠标悬停在按钮上时,它也会更改颜色,如下所示。
使用模板,您可以访问控件的更多部分而不是样式。您可以指定控件的现有行为和新行为。
动画和转换
Windows 运行时中的动画和转换可以通过构建交互性和移动来改进您的 XAML 应用程序。通过使用 Windows 运行时动画库中的动画,您可以轻松地在 XAML 应用程序中集成交互式外观。使用动画
- 增强用户界面或使其更具吸引力。
- 以吸引用户注意变化。
在以下屏幕截图中,您可以看到一个正方形 –
当您将鼠标悬停在此方块上时,它将向各个方向展开,如下所示。
XAML – 控件
XAML 用户界面框架提供了一个广泛的控件库,支持 Windows 的 UI 开发。其中一些具有可视化表示,例如 Button、Textbox、TextBlock 等;而其他控件用作其他控件或内容(例如图像)的容器。所有 XAML 控件都继承自System.Windows.Controls.Control。
控件的完整继承层次如下 –
这是我们将在本章中一一讨论的控件列表。
Sr.No. | 控制和描述 |
---|---|
1 | Button
响应用户输入的控件。 |
2 | Calendar
表示一个控件,该控件使用户能够使用可视日历显示来选择日期。 |
3 | CheckBox
用户可以选择或清除的控件。 |
4 | ComboBox
用户可以从中选择的项目的下拉列表。 |
5 | ContextMenu
获取或设置上下文菜单元素,每当通过用户界面 (UI) 从此元素内请求上下文菜单时,该元素应出现。 |
6 | DataGrid
表示在可自定义的网格中显示数据的控件。 |
7 | DatePicker
允许用户选择日期的控件。 |
8 | Dialogs
应用程序还可以向用户显示附加窗口以收集或显示重要信息。 |
9 | GridView
在可以水平滚动的行和列中显示项目集合的控件。 |
10 | Image
显示图像的控件。 |
11 | ListBox
显示用户可以从中选择的内联项目列表的控件。 |
12 | Menus
表示一个 Windows 菜单控件,它使您能够分层组织与命令和事件处理程序关联的元素。 |
13 | PasswordBox
用于输入密码的控件。 |
14 | Popup
在现有内容之上,在应用程序窗口的边界内显示内容。 |
15 | ProgressBar
通过显示条形指示进度的控件。 |
16 | ProgressRing
通过显示环来指示不确定进度的控件。 |
17 | RadioButton
允许用户从一组选项中选择一个选项的控件。 |
18 | RichEditBox
允许用户编辑包含格式化文本、超链接和图像等内容的富文本文档的控件。 |
19 | ScrollViewer
允许用户平移和缩放其内容的容器控件。 |
20 | SearchBox
允许用户输入搜索查询的控件。 |
21 | Slider
允许用户通过沿轨道移动 Thumb 控件从一系列值中进行选择的控件。 |
22 | TextBlock
显示文本的控件。 |
23 | TimePicker
允许用户设置时间值的控件。 |
24 | ToggleButton
可以在两种状态之间切换的按钮。 |
25 | ToolTip
显示元素信息的弹出窗口。 |
26 | Window
提供最小化/最大化选项、标题栏、边框和关闭按钮的根窗口。 |
在本章中,我们将讨论所有这些控制和实现。
XAML – 布局
控件的布局对于应用程序的可用性非常重要和关键。需要在您的应用程序中排列一组 GUI 元素。选择布局面板时需要考虑一些重点;
- 子元素的位置。
- 子元素的大小。
- 重叠的子元素相互叠加。
当应用程序在不同的屏幕分辨率上使用时,控件的固定像素排列不起作用。XAML 提供了一组丰富的内置布局面板,以适当的方式排列 GUI 元素。一些最常用和流行的布局面板如下 –
Sr.No | 面板和说明 |
---|---|
1 | StackPanel
Stack panel 是一个简单而有用的 XAML 布局面板。在堆栈面板中,子元素可以根据方向属性水平或垂直排列在一行中。 |
2 | WrapPanel
在 WrapPanel 中,子元素根据orientation 属性按从左到右或从上到下的顺序排列。 |
3 | DockPanel
DockPanel 定义了一个区域来相对于彼此排列子元素,无论是水平还是垂直。使用 DockPanel,您可以使用 Dock 属性轻松地将子元素停靠到顶部、底部、右侧、左侧和中心。 |
4 | CanvasPanel
Canvas 面板是基本的布局面板,其中可以使用相对于 Canvas 任何一侧(例如左侧、右侧、顶部和底部)的坐标来明确定位子元素。 |
5 | GridPanel
网格面板提供了一个由行和列组成的灵活区域。在 Grid 中,子元素可以以表格形式排列。 |
XAML – 事件处理
XAML 中事件的一般概念类似于其他流行的编程语言(如 .NET 和 C++)中的事件。在 XAML 中,所有控件都公开一些事件,以便可以为特定目的订阅它们。
每当发生事件时,应用程序都会收到通知,程序可以对其做出反应,例如,关闭按钮用于关闭对话框。
可以根据应用程序的要求为应用程序的不同行为订阅多种类型的事件,但最常用的事件是与鼠标和键盘相关的事件,例如,
- 点击
- 鼠标按下
- 鼠标输入
- 鼠标离开
- 鼠标向上
- 按键按下
- 键升
在本章中,我们将使用一些基本和最常用的事件来了解如何将特定控件的事件链接到背后的代码,根据用户在特定事件发生时想要做什么来实现行为。发生。
让我们看一个按钮单击事件的简单示例。下面给出了 Button 控件的 XAML 实现,它是用一些属性和一个 Click 事件(Click=”OnClick”)创建和初始化的。
<Window x:Class = "XAMLEventHandling.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <Grid> <Button x:Name = "button1" Content = "Click" Click = "OnClick" Width = "150" Height = "30" HorizontalAlignment = "Center" /> </Grid> </Window>
每当单击此按钮时,它都会触发OnClick事件,您可以添加任何类型的行为作为对 Click 的响应。让我们看一下 OnClick 事件实现,它会在单击此按钮时显示一条消息。
using System; using System.Windows; using System.Windows.Controls; namespace XAMLEventHandling { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void OnClick(object sender, RoutedEventArgs e) { MessageBox.Show("Button is clicked!"); } } }
当您编译并执行上述代码时,它将产生以下输出 –
当您单击按钮时,将触发单击 (OnClick) 事件并显示以下消息。
现在让我们看一个处理多个事件的复杂示例。
例子
以下示例包含一个带有 ContextMenu 的文本框,该文本框操作文本框中的文本。
以下 XAML 代码创建了一个 TextBox、一个 ContextMenu 和 MenuItems,以及一些属性和事件,例如 Checked、Unchecked 和 Click。
<Window x:Class = "XAMLContextMenu.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <Grid> <TextBox Name = "textBox1" TextWrapping = "Wrap" Margin = "10" Grid.Row = "7"> Hi, this is XAML tutorial. <TextBox.ContextMenu> <ContextMenu> <MenuItem Header = "_Bold" IsCheckable = "True" Checked = "Bold_Checked" Unchecked = "Bold_Unchecked" /> <MenuItem Header = "_Italic" IsCheckable = "True" Checked = "Italic_Checked" Unchecked = "Italic_Unchecked" /> <Separator /> <MenuItem Header = "Increase Font Size" Click = "IncreaseFont_Click" /> <MenuItem Header = "_Decrease Font Size" Click = "DecreaseFont_Click" /> </ContextMenu> </TextBox.ContextMenu> </TextBox> </Grid> </Window>
下面是 C# 中不同事件的实现,只要选中、取消选中或单击菜单项,就会触发这些事件。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; namespace XAMLContextMenu { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Bold_Checked(object sender, RoutedEventArgs e) { textBox1.FontWeight = FontWeights.Bold; } private void Bold_Unchecked(object sender, RoutedEventArgs e) { textBox1.FontWeight = FontWeights.Normal; } private void Italic_Checked(object sender, RoutedEventArgs e) { textBox1.FontStyle = FontStyles.Italic; } private void Italic_Unchecked(object sender, RoutedEventArgs e) { textBox1.FontStyle = FontStyles.Normal; } private void IncreaseFont_Click(object sender, RoutedEventArgs e) { if (textBox1.FontSize < 18) { textBox1.FontSize += 2; } } private void DecreaseFont_Click(object sender, RoutedEventArgs e) { if (textBox1.FontSize > 10) { textBox1.FontSize -= 2; } } } }
当您编译并执行上述代码时,它将产生以下输出 –
我们建议您执行上面的示例代码并尝试其他一些事件。
活动
Sr.No. | 控制和描述 |
---|---|
1 |
Checked 检查触刀顿堡时触发。(继承自 ToggleButton) |
2 |
Click 单击按钮控件时发生。(继承自 ButtonBase) |
3 |
ContextMenuClosing 在元素上的任何上下文菜单关闭之前发生。(继承自 FrameworkElement。) |
4 |
ContextMenuOpening 在打开元素上的任何上下文菜单时发生。(继承自 FrameworkElement。) |
5 |
DataContextChanged 当 FrameworkElement.DataContext 属性的值更改时发生。(继承自 FrameworkElement) |
6 |
DragEnter 当输入系统报告以此元素为目标的底层拖动事件时发生。(继承自 UIElement)。 |
7 |
DragLeave 当输入系统报告以此元素为原点的底层拖动事件时发生。(继承自 UIElement) |
8 |
DragOver 当输入系统报告使用此元素作为潜在放置目标的基础拖动事件时发生。(继承自 UIElement) |
9 |
DragStarting 在启动拖动操作时发生。(继承自 UIElement) |
10 |
DropCompleted 在拖放操作结束时发生。(继承自 UIElement) |
11 |
DropDownClosed 当 ComboBox 的下拉部分关闭时发生。 |
12 |
DropDownOpened 当 ComboBox 的下拉部分打开时发生。 |
13 |
GotFocus 当 UIElement 获得焦点时发生。(继承自 UIElement) |
14 |
Holding 在此元素的命中测试区域上发生其他未处理的 Hold 交互时发生。(继承自 UIElement) |
15 |
Intermediate 当 ToggleButton 的状态切换到不确定状态时触发。(继承自 ToggleButton) |
16 |
IsEnabledChanged 当 IsEnabled 属性更改时发生。(继承自 Control) |
17 |
KeyDown 在 UIElement 具有焦点时按下键盘键时发生。(继承自 UIElement) |
18 |
KeyUp 在 UIElement 具有焦点时释放键盘键时发生。(继承自 UIElement) |
19 |
LostFocus 当 UIElement 失去焦点时发生。(继承自 UIElement) |
20 |
ManipulationCompleted 在 UIElement 上的操作完成时发生。(继承自 UIElement) |
21 |
ManipulationDelta 当输入设备在操作过程中改变位置时发生。(继承自 UIElement) |
22 |
ManipulationInertiaStarting 当输入设备在操作和惯性开始期间失去与 UIElement 对象的联系时发生。(继承自 UIElement) |
23 |
ManipulationStarted 当输入设备开始对 UIElement 进行操作时发生。(继承自 UIElement) |
24 |
ManipulationStarting 在首次创建操作处理器时发生。(继承自 UIElement) |
25 |
SelectionChanged 当文本选择已更改时发生。 |
26 |
SizeChanged 当 ActualHeight 或 ActualWidth 属性更改 FrameworkElement 上的值时发生。(继承自 FrameworkElement) |
27 |
Unchecked 在未选中 ToggleButton 时发生。(继承自 ToggleButton) |
28 |
ValueChanged 当范围值改变时发生。(继承自 RangeBase) |
XAML – 数据绑定
数据绑定是 XAML 应用程序中的一种机制,它为 Windows 运行时应用程序使用分部类显示数据并与数据交互提供了一种简单易行的方法。在这种机制中,数据的管理与数据的显示方式完全分离。
数据绑定允许数据在用户界面上的 UI 元素和数据对象之间流动。当建立绑定并且数据或您的业务模型发生变化时,它将自动将更新反映到 UI 元素,反之亦然。也可以不绑定到标准数据源,而是绑定到页面上的另一个元素。数据绑定可以有两种类型 –
- 单向数据绑定
- 双向数据绑定
单向数据绑定
在单向绑定中,数据从其源(即保存数据的对象)绑定到其目标(即显示数据的对象)。
让我们看一个单向数据绑定的简单示例。以下 XAML 代码创建四个具有某些属性的文本块。
<Window x:Class = "DataBindingOneWay.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <Grid> <StackPanel Name = "Display"> <StackPanel Orientation = "Horizontal" Margin = "50, 50, 0, 0"> <TextBlock Text = "Name: " Margin = "10" Width = "100" /> <TextBlock Margin = "10" Width = "100" Text = "{Binding Name}" /> </StackPanel> <StackPanel Orientation = "Horizontal" Margin = "50,0,50,0"> <TextBlock Text = "Title: " Margin = "10" Width = "100" /> <TextBlock Margin = "10" Width = "100" Text = "{Binding Title}" /> </StackPanel> </StackPanel> </Grid> </Window>
两个文本块的文本属性静态设置为“Name”和“Title”,而另外两个文本块文本属性绑定到“Name”和“Title”,它们是Employee类的类变量,如下所示。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DataBindingOneWay { public class Employee { public string Name { get; set; } public string Title { get; set; } public static Employee GetEmployee() { var emp = new Employee() { Name = "Ali Ahmed", Title = "Developer" }; return emp; } } }
在这个类中,我们只有两个变量,Name和Title,以及一个静态方法,其中 Employee 对象被初始化,它将返回该员工对象。因此,我们绑定到一个属性 Name 和 Title,但我们还没有选择该属性属于哪个对象。最简单的方法是将一个对象分配给我们在以下 C# 代码中绑定其属性的 DataContext –
using System; using System.Windows; using System.Windows.Controls; namespace DataBindingOneWay { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = Employee.GetEmployee(); } } }
让我们运行这个应用程序,您可以立即在 MainWindow 中看到我们已成功绑定到该 Employee 对象的 Name 和 Title。
双向数据绑定
在双向绑定中,用户可以通过用户界面修改数据并在源中更新该数据。如果在用户查看视图时源发生更改,您可能需要更新视图。
例子
让我们看一下下面的示例,其中创建了一个带有三个组合框项目的组合框和一个带有一些属性的文本框。在这个例子中,我们没有任何标准的数据源,但是 UI 元素绑定到其他 UI 元素。
<Window x:Class = "XAMLTestBinding.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <StackPanel> <ComboBox Name = "comboBox" Margin = "50" Width = "100"> <ComboBoxItem Content = "Green" /> <ComboBoxItem Content = "Yellow" IsSelected = "True" /> <ComboBoxItem Content = "Orange" /> </ComboBox> <TextBox Name = "textBox" Margin = "50" Width = "100" Height = "23" VerticalAlignment = "Top" Text = "{Binding ElementName = comboBox, Path = SelectedItem.Content, Mode = TwoWay, UpdateSourceTrigger = PropertyChanged}" Background = "{Binding ElementName = comboBox, Path = SelectedItem.Content}"> </TextBox> </StackPanel> </Window>
当您编译并执行上述代码时,它将产生以下输出。当用户从组合框中选择一个项目时,文本框文本和背景颜色将相应更新。
同样,当用户在文本框中键入有效的颜色名称时,组合框和文本框背景颜色也将更新。
XAML – 标记扩展
在 XAML 应用程序中,标记扩展是一种获取既不是特定 XAML 对象也不是原始类型的值的方法/技术。标记扩展可以通过打开和关闭大括号来定义,在大括号内,定义了标记扩展的范围。
数据绑定和静态资源是标记扩展。System.xaml 中有一些预定义的 XAML 标记扩展可以使用。
让我们看一个简单的例子,其中使用了StaticResources标记扩展,这是一个预定义的 XAML 标记扩展。
以下 XAML 代码创建两个具有某些属性的文本块,它们的前景在Window.Resources 中定义。
<Window x:Class = "XAMLStaticResourcesMarkupExtension.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "525"> <Window.Resources> <SolidColorBrush Color = "Blue" x:Key = "myBrush"></SolidColorBrush> </Window.Resources> <Grid> <StackPanel Orientation = "Vertical"> <TextBlock Foreground = "{StaticResource myBrush}" Text = "First Name" Width = "100" Margin = "10" /> <TextBlock Foreground = "{StaticResource myBrush}" Text = "Last Name" Width = "100" Margin = "10" /> </StackPanel> </Grid> </Window>
在Window.Resources 中,您可以看到x:Key用于唯一标识在 XAML 定义的字典中创建和引用的元素,以标识资源字典中的资源。
当你编译并执行上面的代码时,它会产生下面的 MainWindow。您可以看到前景色为蓝色的两个文本块。
在 XAML 中,自定义标记扩展也可以通过继承 MarkupExtension 类并覆盖作为 MarkupExtension 类中的抽象方法的 ProvideValue 方法来定义。
让我们看一个简单的自定义标记扩展示例。
<Window x:Class = "XAMLMarkupExtension.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:my = "clr-namespace:XAMLMarkupExtension" Title = "MainWindow" Height = "350" Width = "525"> <Grid> <Button Content = "{my:MyMarkupExtension FirstStr = Markup, SecondStr = Extension}" Width = "200" Height = "20" /> </Grid> </Window>
在上面的 XAML 代码中,使用一些属性创建了一个按钮,并且对于内容值,使用了自定义标记扩展(my:MyMarkupExtension)和两个值“Markup”和“Extension”,它们分别分配给 FirstStr 和 SecondStr。
实际上,MyMarkupExtension
是一个派生自MarkupExtension
C# 实现中的类,如下所示。此类包含两个字符串变量 FirstStr 和 SecondStr,它们被连接起来并将该字符串从 ProvideValue 方法返回到按钮的 Content。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Markup; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace XAMLMarkupExtension { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } public class MyMarkupExtension : MarkupExtension { public MyMarkupExtension() { } public String FirstStr { get; set; } public String SecondStr { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { return FirstStr + " " + SecondStr; } } }
让我们运行这个应用程序,您可以立即在我们的 MainWindow 中看到“标记扩展”已成功用作按钮的内容。
XAML – 依赖属性
依赖属性是一种特定类型的属性,其值后跟一个敏锐的属性系统,该系统也是 Windows 运行时应用程序的一部分。定义依赖属性的类必须从 DependencyObject 类继承。
XAML 中使用的许多 UI 控件类都派生自 DependencyObject 类并支持依赖项属性。以下 XAML 代码创建一个具有某些属性的按钮。
<Window x:Class = "XAMLDependencyProperty.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local = "clr-namespace:XAMLDependencyProperty" Title = "MainWindow" Height = "350" Width = "604"> <Grid> <Button Height = "40" Width = "175" Margin = "10" Content = "Dependency Property"> <Button.Style> <Style TargetType = "{x:Type Button}"> <Style.Triggers> <Trigger Property = "IsMouseOver" Value = "True"> <Setter Property = "Foreground" Value = "Red" /> </Trigger> </Style.Triggers> </Style> </Button.Style> </Button> </Grid> </Window>
XAML 中的 x:Type 标记扩展具有与 C# 中的 typeof() 类似的功能。它在指定采用对象类型的属性时使用,例如 <Style TargetType = “{x:Type Button}”>
当你编译并执行上面的代码时,它会产生下面的 MainWindow。当鼠标悬停在按钮上时,它将改变按钮的前景色。当鼠标离开按钮时,它会变回原来的颜色。
依赖属性和其他 CLR 属性之间的主要区别是 –
-
CLR 属性可以通过使用getter和setter直接从类的私有成员读取/写入。在依赖属性的情况下,它不存储在本地对象中。
-
依赖属性存储在由 DependencyObject 类提供的键/值对字典中。
-
它还节省了大量内存,因为它在更改时存储属性。
-
它也可以在 XAML 中绑定。
在 .NET 框架中,还可以定义自定义依赖属性。以下是在 C# 中定义自定义依赖项属性的步骤。
-
使用系统调用寄存器声明并注册您的依赖属性。
-
提供属性的 setter 和 getter。
-
定义一个静态处理程序来处理全局发生的任何更改。
-
定义一个实例处理程序来处理该特定实例发生的任何更改。
下面给出了 C# 中依赖属性的代码,该代码定义为设置用户控件的 SetText 属性。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApplication3 { /// <summary> /// Interaction logic for UserControl1.xaml /// </summary> public partial class UserControl1 : UserControl { public UserControl1() { InitializeComponent(); } public static readonly DependencyProperty SetTextProperty = DependencyProperty.Register("SetText", typeof(string), typeof(UserControl1), new PropertyMetadata("", new PropertyChangedCallback(OnSetTextChanged))); public string SetText { get {return(string) GetValue(SetTextProperty); } set {SetValue(SetTextProperty, value);} } private static void OnSetTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UserControl1 UserControl1Control = d as UserControl1; UserControl1Control.OnSetTextChanged(e); } private void OnSetTextChanged(DependencyPropertyChangedEventArgs e) { tbTest.Text = e.NewValue.ToString(); } } }
这是 XAML 文件,其中 TextBlock 被定义为用户控件,并且 Text 属性将由 SetText 依赖属性分配给它。
以下 XAML 代码创建一个用户控件,并初始化其 SetText 依赖项属性和一些其他属性。
<Window x:Class = "WpfApplication3.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:views = "clr-namespace:WpfApplication3" Title = "MainWindow" Height = "350" Width = "604"> <Grid> <views:UserControl1 SetText = "Hellow World" /> </Grid> </Window>
让我们运行这个应用程序,您可以立即在我们的 MainWindow 中看到用户控件的依赖属性已成功用作文本。
XAML – 资源
资源通常是与某个对象相关联的定义,这些对象只是您预计会经常使用不止一次。它能够为控件或当前窗口或全局为整个应用程序在本地存储数据。
将对象定义为资源允许我们从另一个地方访问它。因此,它允许可重用性。资源在资源字典中定义,任何对象都可以定义为资源,有效地使其成为可共享的资产。为 XAML 资源指定了唯一键,并且可以使用该键通过使用 StaticResource 标记扩展来引用它。
让我们再看一个简单的例子,其中创建了两个带有一些属性的文本块,它们的前景色在Window.Resources 中定义。
<Window x:Class = "XAMLResources.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <Window.Resources> <SolidColorBrush Color = "Blue" x:Key = "myBrush"></SolidColorBrush> </Window.Resources> <StackPanel Orientation = "Vertical"> <TextBlock Foreground = "{StaticResource myBrush}" Text = "First Name" Width = "100" Margin = "10" /> <TextBlock Foreground = "{StaticResource myBrush}" Text = "Last Name" Width = "100" Margin = "10" /> </StackPanel> </Window>
上述代码编译执行后,会产生如下MainWindow。您可以看到两个前景色为蓝色的文本块。资源的优点是,如果有多个文本块,并且你想改变它们的背景颜色,那么你只需要在资源字典中改变它。
资源范围
资源在资源字典中定义,但是有很多地方可以定义资源字典。在上面的例子中,资源字典是在窗口/页面级别定义的。在哪个字典中定义资源会立即限制该资源的范围。因此范围,即您可以在何处使用资源,取决于您定义它的位置。
-
在网格的资源字典中定义资源,并且只能由该网格及其子元素访问。
-
在窗口/页面上定义它,并且该窗口/页面上的所有元素都可以访问它。
-
App 根可以在 App.xaml 资源字典中找到。它是我们应用程序的根,因此这里定义的资源的范围是整个应用程序。
就资源的范围而言,最常见的是应用程序级别、页面级别和特定元素级别,如 Grid、StackPanel 等。
资源词典
XAML 应用程序中的资源字典意味着单独文件中的资源字典。几乎所有 XAML 应用程序都遵循它。在单独的文件中定义资源具有以下优点 –
-
资源字典中定义资源与UI相关代码的分离。
-
在单独的文件(例如 App.xaml)中定义所有资源将使它们在整个应用程序中可用。
那么,我们如何在一个单独的文件中的资源字典中定义我们的资源?嗯,这很容易,只需通过以下步骤通过 Visual Studio 添加一个新的资源字典 –
-
在您的解决方案中,添加一个新文件夹并将其命名为ResourceDictionaries。
-
右键单击此文件夹并从添加子菜单项中选择资源字典并将其命名为DictionaryWithBrush.xaml
让我们来看看同一个应用程序;现在只是在应用程序级别定义了资源字典。
这是 MainWindow.xaml 的 XAML 代码。
<Window x:Class = "XAMLResources.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <StackPanel Orientation = "Vertical"> <TextBlock Foreground = "{StaticResource myBrush}" Text = "First Name" Width = "100" Margin = "10" /> <TextBlock Foreground = "{StaticResource myBrush}" Text = "Last Name" Width = "100" Margin = "10"/> </StackPanel> </Window>
这是 DictionaryWithBrush.xaml 中的实现 –
<ResourceDictionary xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"> <SolidColorBrush Color = "Blue" x:Key = "myBrush"></SolidColorBrush> </ResourceDictionary>
这是 app.xaml 中的实现 –
<Application x:Class = "XAMLResources.App" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" StartupUri = "MainWindow.xaml"> <Application.Resources> <ResourceDictionary Source = " XAMLResources\ResourceDictionaries\DictionaryWithBrush.xaml" /> </Application.Resources> </Application>
当上面的代码被编译和执行时,它会产生以下输出 –
我们建议您执行上述代码并尝试更多资源,例如背景颜色等。
XAML – 模板
模板描述了控件的整体外观和视觉外观。对于每个控件,都有一个与之关联的默认模板,用于为该控件提供外观。
在 XAML 中,当您想要自定义控件的视觉行为和视觉外观时,您可以轻松创建自己的模板。逻辑和模板之间的连接可以通过数据绑定来实现。
样式和模板之间的主要区别是 –
-
样式只能使用该控件的默认属性更改控件的外观。
-
使用模板,您可以访问控件的更多部分而不是样式。您还可以指定控件的现有行为和新行为。
有两种最常用的模板。
- 控制模板
- 数据模板
控制模板
控件模板定义或指定控件的视觉外观和结构。所有的 UI 元素都具有某种外观和行为,例如,按钮具有外观和行为。单击事件或鼠标悬停事件是响应单击和悬停而触发的行为,并且还有一个按钮的默认外观,可以通过 Control 模板进行更改。
让我们再看一个简单的例子,其中创建了两个带有一些属性的按钮。一个是模板,另一个是默认按钮。
<Window x:Class = "TemplateDemo.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <Window.Resources> <ControlTemplate x:Key = "ButtonTemplate" TargetType = "Button"> <Grid> <Ellipse x:Name = "ButtonEllipse" Height = "100" Width = "150" > <Ellipse.Fill> <LinearGradientBrush StartPoint = "0,0.2" EndPoint = "0.2,1.4"> <GradientStop Offset = "0" Color = "Red"/> <GradientStop Offset = "1" Color = "Orange"/> </LinearGradientBrush> </Ellipse.Fill> </Ellipse> <ContentPresenter Content = "{TemplateBinding Content}" HorizontalAlignment = "Center" VerticalAlignment = "Center" /> </Grid> <ControlTemplate.Triggers> <Trigger Property = "IsMouseOver" Value = "True"> <Setter TargetName = "ButtonEllipse" Property = "Fill" > <Setter.Value> <LinearGradientBrush StartPoint = "0,0.2" EndPoint="0.2,1.4"> <GradientStop Offset = "0" Color = "YellowGreen"/> <GradientStop Offset = "1" Color = "Gold"/> </LinearGradientBrush> </Setter.Value> </Setter> </Trigger> <Trigger Property = "IsPressed" Value = "True"> <Setter Property = "RenderTransform"> <Setter.Value> <ScaleTransform ScaleX = "0.8" ScaleY = "0.8" CenterX = "0" CenterY = "0" /> </Setter.Value> </Setter> <Setter Property = "RenderTransformOrigin" Value = "0.5,0.5" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Window.Resources> <StackPanel> <Button Content = "Round Button!" Template = "{StaticResource ButtonTemplate}" Width = "150" Margin = "50" /> <Button Content = "Default Button!" Height = "40" Width = "150" Margin = "5" /> </StackPanel> </Window>
当上面的代码被编译和执行时,它会产生以下 MainWindow –
当您将鼠标悬停在带有自定义模板的按钮上时,它也会更改颜色,如下所示 –
数据模板
数据模板定义并指定数据集合的外观和结构。它提供了在任何 UI 元素上格式化和定义数据表示的灵活性。多用于数据相关的Item控件,如ComboBox、ListBox等。
让我们看一个简单的数据模板示例。以下 XAML 代码创建一个包含数据模板和文本块的组合框。
<Window x:Class = "XAMLDataTemplate.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <Grid VerticalAlignment = "Top"> <ComboBox Name = "Presidents" ItemsSource = "{Binding}" Height = "30" Width = "400"> <ComboBox.ItemTemplate> <DataTemplate> <StackPanel Orientation = "Horizontal" Margin = "2"> <TextBlock Text = "Name: " Width = "95" Background = "Aqua" Margin = "2" /> <TextBlock Text = "{Binding Name}" Width = "95" Background = "AliceBlue" Margin = "2" /> <TextBlock Text = "Title: " Width = "95" Background = "Aqua" Margin = "10,2,0,2" /> <TextBlock Text = "{Binding Title}" Width = "95" Background = "AliceBlue" Margin = "2" /> </StackPanel> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> </Grid> </Window>
这是 C# 中的实现,其中员工对象被分配给 DataContext –
using System; using System.Windows; using System.Windows.Controls; namespace XAMLDataTemplate { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = Employee.GetEmployees(); } } }
这是 Employee 类的 C# 实现 –
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; namespace XAMLDataTemplate { public class Employee : INotifyPropertyChanged { private string name; public string Name { get { return name; } set { name = value; RaiseProperChanged(); } } private string title; public string Title { get { return title; } set { title = value; RaiseProperChanged(); } } public static Employee GetEmployee() { var emp = new Employee() { Name = "Waqas", Title = "Software Engineer" }; return emp; } public event PropertyChangedEventHandler PropertyChanged; private void RaiseProperChanged( [CallerMemberName] string caller = ""){ if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(caller)); } } public static ObservableCollection<Employee> GetEmployees() { var employees = new ObservableCollection<Employee>(); employees.Add(new Employee() { Name = "Ali", Title = "Developer" }); employees.Add(new Employee() { Name = "Ahmed", Title = "Programmer" }); employees.Add(new Employee() { Name = "Amjad", Title = "Desiner" }); employees.Add(new Employee() { Name = "Waqas", Title = "Programmer" }); employees.Add(new Employee() { Name = "Bilal", Title = "Engineer" }); employees.Add(new Employee() { Name = "Waqar", Title = "Manager" }); return employees; } } }
上述代码编译执行后,会产生如下输出。它包含一个组合框,当您单击组合框时,您会看到在 Employee 类中创建的数据集合被列为组合框项。
我们建议您执行上述代码并进行试验。
XAML – 样式
XAML 框架提供了多种策略来个性化和自定义应用程序的外观。样式使我们能够灵活地设置对象的某些属性,并在多个对象中重用这些特定设置以获得一致的外观。
-
在样式中,您只能设置对象的现有属性,例如高度、宽度和字体大小。
-
只能指定控件的默认行为。
-
可以将多个属性添加到单个样式中。
样式用于为一组控件提供统一的外观。隐式样式用于将外观应用于给定类型的所有控件并简化应用程序。
想象一下,我们有三个按钮,而且它们都必须看起来相同——相同的宽度和高度、相同的字体大小和相同的前景色。我们可以在按钮元素本身上设置所有这些属性,这对于所有按钮来说仍然很好,如下图所示。
但是在现实生活中的应用程序中,您通常会拥有更多需要看起来完全相同的内容。当然不仅是按钮,您通常还希望您的文本块、文本框和组合框等在您的应用程序中看起来相同。当然必须有更好的方法来实现这一点 – 它被称为造型。您可以将样式视为将一组属性值应用于多个元素的便捷方式,如下图所示。
让我们看一下包含三个按钮的示例,这些按钮是在 XAML 中创建的,具有一些属性。
<Window x:Class = "XAMLStyle.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:XAMLStyle" mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604"> <StackPanel> <Button Content = "Button1" Height = "30" Width = "80" Foreground = "Blue" FontSize = "12" Margin = "10"/> <Button Content = "Button2" Height = "30" Width = "80" Foreground = "Blue" FontSize = "12" Margin = "10"/> <Button Content = "Button3" Height = "30" Width = "80" Foreground = "Blue" FontSize = "12" Margin = "10"/> </StackPanel> </Window>
当您查看上面的代码时,您会看到所有按钮的高度、宽度、前景色、字体大小和边距属性都保持不变。编译并执行上述代码后,将显示以下输出 –
现在让我们看一下同一个例子,但这次,我们将使用style。
<Window x:Class = "XAMLStyle.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:XAMLStyle" mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604"> <Window.Resources> <Style x:Key = "myButtonStyle" TargetType = "Button"> <Setter Property = "Height" Value = "30"/> <Setter Property = "Width" Value = "80"/> <Setter Property = "Foreground" Value = "Blue"/> <Setter Property = "FontSize" Value = "12"/> <Setter Property = "Margin" Value = "10"/> </Style> </Window.Resources> <StackPanel> <Button Content = "Button1" Style = "{StaticResource myButtonStyle}"/> <Button Content = "Button2" Style = "{StaticResource myButtonStyle}"/> <Button Content = "Button3" Style = "{StaticResource myButtonStyle}"/> </StackPanel> </Window>
样式在资源字典中定义,每个样式都有唯一的键标识符和目标类型。在 <style> 中,您可以看到为将包含在样式中的每个属性定义了多个 setter 标记。
在上面的例子中,每个按钮的所有公共属性现在都在 style 中定义,然后通过 StaticResource 标记扩展设置 style 属性,将样式分配给具有唯一键的每个按钮。
当上面的代码被编译和执行时,它会产生以下窗口,它是相同的输出。
这样做的好处是显而易见的。我们可以在其范围内的任何地方重用该样式,如果我们需要更改它,我们只需在样式定义中更改一次,而不是在每个元素上更改它。
在什么级别上定义样式会立即限制该样式的范围。因此范围,即您可以在何处使用样式,取决于您定义它的位置。可以在以下级别定义样式 –
Sr.No | 级别和描述 |
---|---|
1 | Control Level
在控件级别定义样式只能应用于该特定控件。 |
2 | Layout Level
在任何布局级别定义样式只能由该布局及其子元素访问。 |
3 | Window Level
在窗口级别定义样式可由该窗口上的所有元素访问。 |
4 | Application Level
在 App 级别定义样式使其可在整个应用程序中访问。 |
XAML – 触发器
基本上,触发器使您能够更改属性值或根据属性值执行操作。因此,它基本上允许您动态更改控件的外观和/或行为,而无需创建新控件。
当满足某些条件时,触发器用于更改任何给定属性的值。触发器通常在应用于该特定控件的样式或文档根中定义。有三种类型的触发器 –
- 属性触发器
- 数据触发器
- 事件触发器
属性触发器
在属性触发器中,当一个属性发生更改时,它会立即或动画更改另一个属性。例如,如果要在鼠标悬停在按钮上时更改按钮外观,可以使用属性触发器。
例子
以下示例演示如何在鼠标进入按钮区域时更改按钮的前景色。
<Window x:Class = "XAMLPropertyTriggers.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <Window.Resources> <Style x:Key = "TriggerStyle" TargetType = "Button"> <Setter Property = "Foreground" Value = "Blue" /> <Style.Triggers> <Trigger Property = "IsMouseOver" Value = "True"> <Setter Property = "Foreground" Value = "Green" /> </Trigger> </Style.Triggers> </Style> </Window.Resources> <Grid> <Button Width = "100" Height = "70" Style = "{StaticResource TriggerStyle}" Content = "Trigger"/> </Grid> </Window>
当您编译并执行上述代码时,它将产生以下输出 –
当鼠标进入按钮区域时,前景色会变成绿色。
数据触发器
当绑定数据满足某些条件时,数据触发器会执行某些操作。让我们看一下以下 XAML 代码,其中使用一些属性创建了一个复选框和一个文本块。当复选框被选中时,它会将前景色更改为红色。
<Window x:Class = "XAMLDataTrigger.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "Data Trigger" Height = "350" Width = "604"> <StackPanel HorizontalAlignment = "Center"> <CheckBox x:Name = "redColorCheckBox" Content = "Set red as foreground color" Margin = "20"/> <TextBlock Name = "txtblock" VerticalAlignment = "Center" Text = "Event Trigger" FontSize = "24" Margin = "20"> <TextBlock.Style> <Style> <Style.Triggers> <DataTrigger Binding = "{Binding ElementName = redColorCheckBox, Path = IsChecked}" Value = "true"> <Setter Property = "TextBlock.Foreground" Value = "Red"/> <Setter Property = "TextBlock.Cursor" Value = "Hand" /> </DataTrigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock> </StackPanel> </Window>
当您编译并执行上述代码时,它将产生以下输出 –
当复选框被选中时,文本块的前景色将变为红色。
事件触发器
事件触发器在触发特定事件时执行某些操作。它通常用于完成一些动画,如 DoubleAnimation、ColorAnimation 等。下面的代码块创建了一个简单的按钮。当点击事件被触发时,它将扩展按钮的宽度和高度。
<Window x:Class = "XAMLEventTrigger.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <Grid> <Button Content = "Click Me" Width = "60" Height = "30"> <Button.Triggers> <EventTrigger RoutedEvent = "Button.Click"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty = "Width" Duration = "0:0:4"> <LinearDoubleKeyFrame Value = "60" KeyTime = "0:0:0"/> <LinearDoubleKeyFrame Value = "120" KeyTime = "0:0:1"/> <LinearDoubleKeyFrame Value = "200" KeyTime = "0:0:2"/> <LinearDoubleKeyFrame Value = "300" KeyTime = "0:0:3"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty = "Height" Duration = "0:0:4"> <LinearDoubleKeyFrame Value = "30" KeyTime = "0:0:0"/> <LinearDoubleKeyFrame Value = "40" KeyTime = "0:0:1"/> <LinearDoubleKeyFrame Value = "80" KeyTime = "0:0:2"/> <LinearDoubleKeyFrame Value = "150" KeyTime = "0:0:3"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Button.Triggers> </Button> </Grid> </Window>
当您编译并执行上述代码时,它将产生以下输出 –
现在,单击按钮,您将观察到它将开始在两个维度上扩展。
XAML – 调试
如果您熟悉任何过程语言(例如 C#、C/C++ 等)中的调试,并且您知道break的用法并期望在 XAML 中进行相同类型的调试,那么您会惊讶地发现它不是还可以像调试任何其他过程语言代码一样调试 XAML 代码。调试 XAML 应用程序意味着尝试查找错误;
-
在数据绑定中,您的数据不会显示在屏幕上,您也不知道为什么
-
或者问题与复杂的布局有关。
-
或者对齐问题或边距颜色、覆盖等问题,使用一些广泛的模板,如列表框和组合框。
在 XAML 中进行调试通常是为了检查绑定是否有效,如果无效,则检查哪里出了问题。不幸的是,除了 Silverlight 之外,无法在 XAML 绑定中设置断点,但我们可以使用“输出”窗口来检查数据绑定错误。让我们看一下以下 XAML 代码以查找数据绑定中的错误。
<Window x:Class = "DataBindingOneWay.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <Grid> <StackPanel Name = "Display"> <StackPanel Orientation = "Horizontal" Margin = "50, 50, 0, 0"> <TextBlock Text = "Name: " Margin = "10" Width = "100"/> <TextBlock Margin = "10" Width = "100" Text = "{Binding FirstName}"/> </StackPanel> <StackPanel Orientation = "Horizontal" Margin = "50,0,50,0"> <TextBlock Text = "Title: " Margin = "10" Width = "100"/> <TextBlock Margin = "10" Width="100" Text = "{Binding Title}" /> </StackPanel> </StackPanel> </Grid> </Window>
两个文本块的文本属性静态设置为“名称”和“标题”,而另外两个文本块的文本属性则绑定到“名字”和“标题”。但是类变量被故意作为 Employee 类中的 Name 和 Title ,它们是不正确的变量名称。现在让我们尝试了解当未显示所需的输出时,我们可以在哪里找到此类错误。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DataBindingOneWay { public class Employee { public string Name { get; set; } public string Title { get; set; } public static Employee GetEmployee() { var emp = new Employee() { Name = "Ali Ahmed", Title = "Developer" }; return emp; } } }
这是 C# 代码中 MainWindow 类的实现 –
using System; using System.Windows; using System.Windows.Controls; namespace DataBindingOneWay { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = Employee.GetEmployee(); } } }
让我们运行这个应用程序,您可以立即在我们的 MainWindow 中看到我们已成功绑定到该 Employee 对象的 Title 但名称未绑定。
要检查名称发生了什么,让我们看看生成大量日志的输出窗口。
查找错误的最简单方法是仅搜索错误,您会发现下面提到的错误,内容为“BindingExpression path error: ‘FirstName’ property not found on ‘object”’Employe”
System.Windows.Data Error: 40 : BindingExpression path error: 'FirstName' property not found on 'object' ''Employee' (HashCode = 11611730)'. BindingExpression:Path = FirstName; DataItem = 'Employee' (HashCode = 11611730); target element is 'TextBlock' (Name = ''); target property is 'Text' (type 'String')
这清楚地表明 FirstName 不是 Employee 类的成员,因此它有助于解决应用程序中的此类问题。
当您再次将FirstName更改为Name时,您将看到所需的输出。
XAML 的 UI 调试工具
XAML 的 UI 调试工具随 Visual Studio 2015 一起引入,用于在运行时检查 XAML 代码。在这些工具的帮助下,XAML 代码以您正在运行的 WPF 应用程序的可视化树以及树中不同 UI 元素属性的形式呈现。要启用此工具,请按照以下步骤操作。
-
步骤 1 – 转到“工具”菜单,然后从“工具”菜单中选择“选项”。
-
步骤 2 – 您将看到以下对话框。
-
步骤 3 – 转到左侧调试项目下的常规选项。
-
第 4 步– 检查突出显示的选项,即“为 XAML 启用 UI 调试工具”
-
步骤 5 – 按 OK 按钮。
现在运行任何 XAML 应用程序或使用以下 XAML 代码 –
<Window x:Class = "XAMLTestBinding.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "350" Width = "604"> <StackPanel> <ComboBox Name = "comboBox" Margin = "50" Width = "100"> <ComboBoxItem Content = "Green"/> <ComboBoxItem Content = "Yellow" IsSelected = "True"/> <ComboBoxItem Content = "Orange" /> </ComboBox> <TextBox Name = "textBox" Margin = "50" Width = "100" Height = "23" VerticalAlignment = "Top" Text = "{ Binding ElementName = comboBox, Path = SelectedItem.Content, Mode = TwoWay, UpdateSourceTrigger = PropertyChanged}" Background = "{Binding ElementName = comboBox, Path = SelectedItem.Content}"> </TextBox> </StackPanel> </Window>
当应用程序执行时,它将显示实时可视树,其中所有元素都显示在树中。
此实时可视化树显示了完整的布局结构,以了解 UI 元素的放置位置。但是这个选项只在Visual Studio 2015中可用。如果你使用的是旧版本的Visual Studio,那么你就不能使用这个工具;但是,还有另一种工具可以与 Visual Studio 集成,例如用于 Visual Studio 的 XAML Spy。您可以从http://xamlspy.com/download下载它。如果您使用的是旧版本的 Visual Studio,我们建议您下载此工具。
XAML – 自定义控件
XAML 具有最强大的功能之一,可用于创建自定义控件,这使得创建功能丰富且可自定义的控件变得非常容易。当 Microsoft 提供的所有内置控件都不符合您的标准或您不想为 3 付费时使用自定义控件rd 党控制。
在本章中,您将学习如何创建自定义控件。在我们开始查看自定义控件之前,让我们先快速浏览一下用户控件。
用户控制
用户控件提供了一种技术来收集和组合不同的内置控件并将它们打包成可重用的 XAML。用户控件用于以下场景 –
-
如果控件由现有控件组成,即您可以创建多个现有控件的单个控件。
-
如果控件不需要主题支持。用户控件不支持复杂的自定义、控件模板,也很难设置样式。
-
如果开发人员更喜欢使用代码隐藏模型编写控件,在该模型中为事件处理程序编写视图和直接代码。
-
您不会在应用程序之间共享您的控制权。
让我们以用户控制为例,并按照下面给出的步骤 –
-
步骤 1 – 创建一个新的 WPF 项目,然后右键单击您的解决方案并选择添加 > 新项目…
-
第 2 步– 将打开以下对话框,现在选择User Control (WPF)并将其命名为MyUserControl。
-
第 3 步– 单击“添加”按钮,您将看到将在您的解决方案中添加两个新文件(MyUserControl.xaml 和 MyUserControl.cs)。
下面给出的是 XAML 代码,其中使用 MyUserControl.xaml 文件中的某些属性创建了一个按钮和一个文本框。
<UserControl x:Class = "XAMLUserControl.MyUserControl" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "300"> <Grid> <TextBox Height = "23" HorizontalAlignment = "Left" Margin = "80,49,0,0" Name = "txtBox" VerticalAlignment = "Top" Width = "200" /> <Button Content = "Click Me" Height = "23" HorizontalAlignment = "Left" Margin = "96,88,0,0" Name = "button" VerticalAlignment = "Top" Width = "75" Click = "button_Click" /> </Grid> </UserControl>
下面给出的是更新文本框的 MyUserControl.cs 文件中按钮单击事件的 C# 代码。
using System; using System.Windows; using System.Windows.Controls; namespace XAMLUserControl { /// <summary> /// Interaction logic for MyUserControl.xaml /// </summary> public partial class MyUserControl : UserControl { public MyUserControl() { InitializeComponent(); } private void button_Click(object sender, RoutedEventArgs e) { txtBox.Text = "You have just clicked the button"; } } }
这是在 MainWindow.xaml 中添加用户控件的实现。
<Window x:Class = "XAMLUserControl.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:control = "clr-namespace:XAMLUserControl" Title = "MainWindow" Height = "350" Width = "525"> <Grid> <control:MyUserControl/> </Grid> </Window>
当您编译并执行上述代码时,它将产生以下输出 –
现在单击“单击我”按钮,您将看到文本框文本已更新。
自定义控件
自定义控件是一个类,它提供自己的样式和模板,这些样式和模板通常在generic.xaml 中定义。自定义控件用于以下场景,
-
如果控件不存在并且您必须从头开始创建它。
-
如果您想通过添加额外的属性或额外的功能来扩展或添加现有控件的功能以适合您的特定场景。
-
如果您的控件需要支持主题和样式。
-
如果您想跨应用程序共享您的控制权。
让我们以自定义控件为例,并按照下面给出的步骤进行操作。
-
步骤 1 – 创建一个新的 WPF 项目,然后右键单击您的解决方案并选择添加 > 新项目…
-
步骤 2 – 将打开以下对话框。现在选择自定义控件 (WPF)并将其命名为MyCustomControl。
-
第 3 步– 单击“添加”按钮,您将看到两个新文件(Themes/Generic.xaml 和 MyCustomControl.cs)将添加到您的解决方案中。
下面给出了 XAML 代码,其中为 Generic.xaml 文件中的自定义控件设置了样式。
<ResourceDictionary xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local = "clr-namespace:XAMLCustomControls"> <Style TargetType = "{x:Type local:MyCustomControl}" BasedOn = "{StaticResource {x:Type Button}}"> <Setter Property = "Background" Value = "LightSalmon"/> <Setter Property = "Foreground" Value = "Blue"/> </Style> </ResourceDictionary>
下面给出的是 MyCustomControl 类的 C# 代码,它是从按钮类继承的,在构造函数中,它覆盖了元数据。
using System; using System.Windows; using System.Windows.Controls; namespace XAMLCustomControls { public class MyCustomControl : Button { static MyCustomControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl))); } } }
下面给出的是 C# 中的自定义控件单击事件实现,它更新文本块的文本。
using System; using System.Windows; using System.Windows.Controls; namespace XAMLCustomControls { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void customControl_Click(object sender, RoutedEventArgs e) { txtBlock.Text = "You have just click your custom control"; } } }
这是 MainWindow.xaml 中添加自定义控件和 TextBlock 的实现。
<Window x:Class = "XAMLCustomControls.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:control = "clr-namespace:XAMLCustomControls" Title = "MainWindow" Height = "350" Width = "604"> <StackPanel> <control:MyCustomControl x:Name = "customControl" Content = "Click Me" Width = "70" Margin = "10" Click = "customControl_Click"/> <TextBlock Name = "txtBlock" Width = "250" Height = "30"/> </StackPanel> </Window>
当您编译并执行上述代码时,它将产生以下输出。观察输出包含一个自定义控件,它是一个自定义按钮。
现在单击自定义按钮。您将看到文本块文本已更新。