输一个程序编写。 就是给出几个输入数字出对应文字然后写个编程,按照什么条件最后

K.N.King编写的《C语言程序设计现代方法第;原题如下:;编写一个程序,要求用户输入一个两位数,然后显示该;提示:把数分解为两个数字;注:本题是针对C语言刚起步的读者的编程题目,本人;#includeintmain(void){;inta,b;;printf(\scanf(\;printf(\if(a!=1){;switch(a){;case2:prin
K.N.King 编写的《C语言程序设计现代方法 第2版》第P68第11题 原题如下: 编写一个程序,要求用户输入一个两位数,然后显示该数的英文单词: Enter a two-digit number: 45 You entered the number forty-five. 提示:把数分解为两个数字。用一个switch语句显示第一位数字对应的单词(“twenty”、“thirty”等),用第二个switch语句显示第二位数字对应的单词。不要忘记11~19需要特殊处理。 注:本题是针对C语言刚起步的读者的编程题目,本人也是C语言刚起步半个月的新手,自己尝试解决这道题目,写的程序可能比较混乱、不简洁,望谅解。
int main (void) {
scanf(\ printf(\ if (a!=1)
switch (a){
case 2 : printf(\
case 3 : printf(\
case 4 : printf(\
case 5 : printf(\
case 6 : printf(\
case 7 : printf(\
case 8 : printf(\
case 9 : printf(\ switch (b){
case 1 : printf(\ case 2 : printf(\ case 3 : printf(\ case 4 : printf(\ case 5 : printf(\ case 6 : printf(\ case 7 : printf(\ case 8 : printf(\ case 9 : printf(\ }
switch (b){
case 1: printf(\ case 2: printf(\ case 3: printf(\ case 4: printf(\ case 5: printf(\ case 6: printf(\ case 7: printf(\ case 8: printf(\ case 9: printf(\ }
return 0; }
三亿文库包含各类专业文献、外语学习资料、行业资料、幼儿教育、小学教育、高等教育、应用写作文书、中学教育、36编写一个程序,要求用户输入一个两位数,然后显示该数的英文单词等内容。 
 再调用 two()函数, 然后再在另一行中显示单词&three...编写一个程序,要求用户输入行驶的英里数和消耗汽油的...该程序要求输入一个 float 型数并打印该数的立方值...  编写一个程序,要求用户输入一个两位数,然后逆序打印...键盘输入一个英文字母在英文字母表中的序号, 然后...个数等于其所有 真因子(不含自身)之和,则该数为...  选择结构编程练习 (1)_计算机软件及应用_IT/计算机_专业资料。C++练习选择...编写一个程序,要求用户输入一个两位数,然后显示该数的英文单词: 【样式输入】 ...  该函数要在一行中显示单词&one&, 再调用 two()...编写一个程序,要求输入水的夸 脱数, 然后显示这么...} 8.编写一个程序,该程序要求用户输入一个华氏温度...  合理的输入后,显示信息错误 3、最终程序截图 4、错误调试分析 无 5、运行结果截图 (三) 1、实验题目 编写程序,要求用户输入一个两位数,然后显示该数的英文单词...  编写一个程序,要求用户输入一个十进制正整数,然后...每行中间的各数等于上 一行位于该数左上方和正上方...当输入一个整数以后,可以转换成相应的英文单词输出。...  语言程序,要求对键盘输入的小写字母用大写字母显示...LOOP COMPARE1 STOP: RET 10.设有一段英文,其字符...试编写一程序,查对单词SUN在该 文中的出现次数,并...  4. 从键盘输入任意三个整数,然后输出这三个数并...编写一个程序,要求用户输入一个十进制正整数,然后...当输入一个整数以后,可以转换成相应的英文单词输出。...《C#程序设计教程(第3版)[精品]》_其它编程-织梦者
当前位置:&>&&>& > 《C#程序设计教程(第3版)[精品]》
《C#程序设计教程(第3版)[精品]》
WPF应用程序和Silverlight应用程序是微软公司推出的基于.NET和DirectX的应用程序编程模型。开发在Windows 7操作系统上运行的客户端应用程序时,建议用 WPF 应用程序来实现,这样可以充分发挥GPU硬件加速的性能优势。
.NET框架包括两个主要组件,一个是公共语言运行库(Common Language Runtime,CLR),另一个是类库。
公共语言运行库提供.NET应用程序所需要的核心服务;类库是与公共语言运行库紧密集成的可重用的类的集合,旨在为开发和运行.NET应用程序提供各种支持。 .NET 框架 4.5 版的类库由近 5 000 个类组成,这些类提供了 Internet 和企业级开发所需要的各种功能,为开发各种.NET应用程序提供了很大的方便。 类库中的每个类均按照功能划分到不同的命名空间下。
Blend for Visual Studio 2012是微软公司研制的、针对VS2012的界面和原型设计工具。在设计XAML动画和生成XAML格式的三维模型时,我们需要使用这个工具。
Console.WriteLine(&Hello World&); (2)作为别名指令,用于简化命名空间的表达形式。 除了使用using关键字指定引用的命名空间外,还可以使用using简化命名空间的层次表达形式,例如: using System.Windows.F 可以表示为 using WinForm=System.Windows.F 这样一来,语句 System.Windows.Form.MessageBox.Show(&hello&); 就可以简写为 WinForm.MessageBox.Show(&hello&);
(3)作为语句,用于定义一个范围。 在C#语言中,using关键字还可用来创建using语言,该语句的作用是定义一个用大括号包围的范围,程序执行到此范围的末尾,就会立即释放在 using 的小括号内创建的对
象。例如: static void Main() { using (TextWriter w = File.CreateText(&test.txt&)) { w.WriteLine(&Line one&); w.WriteLine(&Line two&); w.WriteLine(&Line three&); } } 这段代码中的 using 语句表示程序执行到它所包含的语句块的末尾“}”时,会立即释放TextWriter对象占用的内存资源。 如果某个范围内有多个需要立即释放的对象,可以用嵌套的using语句来实现。
Main方法只能声明为public static int或者public static void,这是C#程序的规定。另外,每一个方法都要有一个返回值,对于没有返回值的方法,必须声明返回值类型为void。 Mian方法的返回值只能有两种类型,一种是int,另一种是void。int类型的返回值用于表示应用程序终止时的状态码,其用途是退出应用程序时返回程序运行的状态(0 表示成功返回,非零值一般表示某个错误编号,错误编号所代表的含义也可以由程序员自己规定)。
Main 方法可以放在任何一个类中,但为了让开发人员容易找到入口点,控制台应用程序和Windows窗体应用程序默认将其放在Program.cs文件的Program类中。
XML注释方式 “///”符号是一种XML注释方式,只要在用户自定义的类型(如类、接口、枚举等)或者在其成员上方,或者命名空间的声明上方连续键入3个斜杠字符“/”,系统就会自动生成对应的XML注释标记。添加XML注释的步骤举例如下: (1)首先定义一个类、方法、属性、字段或者其他类型。例如,在Studentinfo.cs中定义一个PrintInfo方法。 (2)在类、方法、属性、字段或者其他类型声明的上面
键入 3 个斜杠符号(“/”),此时开发环境就会自动添加对应的XML注释标记。例如,先编写一个PrintInfo方法,然后在该方法的上面键入3个斜杠符号后,就会得到下面的XML注释代码: /// &summary& /// /// &/summary& public void PrintInfo ( ) { Console.WriteLine(&姓名:{0},年龄:{1}&, studentName, age); } (3)在 XML 注释标记内添加注释内容。例如,在&summary&和&/summary&之间添加方法的功能描述。
以后调用该方法时,就可以在键入方法名和参数的过程中直接看到用 XML 注释的智能提示。
Main方法结束前加上Console.ReadKey();语句,意思是读取键盘输入的任意一个字符,按一下键盘上的空格键、回车键或者其他任何一个字符键,就又返回到开发环境下了。
Write方法与WriteLine方法的区别是后者在输出数据后,还自动输出一个回车换行符,即将光标自动转到下一行。
System命名空间下的Console类提供了一个ReadLine方法,该方法从标准输入流依次读取从键盘输入的字符,并将被按下的字符立即显示在控制台窗口中,而且在用户按下回车键之前会一直等待输入,直到用户按下回车键为止。 下面的代码演示了ReadLine方法的简单用法。 string s = Console.ReadLine(); if (s == &abc&) {
Console.WriteLine(&OK&); } 除了ReadLine方法之外,还可以用ReadKey方法读取用户按下的某一个字符或功能键,并将被按下的键值显示在控制台窗口中。ReadKey方法返回的是一个ConsoleKeyInfo类型的对象,该对象描述用户按下的是哪个键,例如: ConsoleKeyI do { c = Console.ReadKey( ); } while (c.Key != ConsoleKey.Escape); 上面这段代码的功能是一直接受用户按下的键,直到用户按下&Esc&键为止。
编写C#代码时,系统提供了很多可直接插入的代码段,利用这些代码段可加快C#代码输入的速度。例如输入“for”这3个字母后,连续按两次&Tab&键,系统就会自动插入如下的代码段: for (int i = 0; i & i++) { } 此时可继续按&Tab&键跳转到代码段的某个修改位置,按回车键完成修改。 也可以在要插入代码段的位置处,用鼠标右键单击选择“外侧代码”的办法插入代码段。
常用形式为 Console.WriteLine(&格式化表示&, 参数序列);
或者 Console.Write(&格式化表示&, 参数序列); 带下画线的斜体字表示需要用具体内容替换,例如: int x=10, y=20, z=30; Console.WriteLine(&{0}+{1}+{2}={3}&, x, y, z, x+y+z); //输出10+20+30=60 Console.WriteLine(&{3}={1}+{2}+{0}&, x, y, z, x+y+z); //输出60=20+30+10 1.格式化表示的一般形式 使用格式化表示时,用“{”和“}”将格式与其他输出字符区分开。一般形式为:
{N [, M][: 格式码]} 注意 格式中的中括号表示其内容为可选项。 假如参数序列为x、y、z,格式中的含义如下。
o N:指定参数序列中的输出序号。例如{0}表示x,{1}表示y,{2}表示z。 o M:指定参数输出的最小长度,如果参数的长度小于M,就用空格填充;如果大于等于M,则按实际长度输出;如果M为负,则左对齐;如果M为正,则右对齐;如果未指定M,默认为0。例如{1,5}表示将参数y的值转换为字符串后按5位右对齐输出。 o 格式码:为可选的格式化代码字符串。例如{1:00000}的输出结果为00020,含义是将参数y按5位数字输出,不够5位左边补0,超过5位按实际位数输出。
o 如果恰好在格式中也要使用大括号,可以用连续的两个大括号表示一个大括号,例如“{{”、“}}”。
o 如果希望格式中的字符或字符串包含与格式符相同的字符,但是又希望让其原样显示时,可以用单引号将其括起来。
也可以利用string.Format方法将某种类型的数据按照希望的格式转换为对应的字符串,该方法既可以在控制台应用程序中使用,也可以在其他应用程序中使用。例如: int i = 123; string s = string.Format(&{0:d6}&, i); //d6表示不够6位左边补0
如果是一个变量,使用ToString方法更简单。例如: int n1 = 12; string s1 = n1.ToString(&X4&); //X格式表示用十六进制输出。结果为:000C string s2 = n1.ToString(&d5&); //结果:00012
GDI(Graphics Device Interface,图形设备接口)是Windows 2000操作系统内核提供的技术,它提供了二维图形和文本处理功能以及功能有限的图像处理功能,但GDI没有三维图形、音频、视频等多媒体处理功能。随着Windows 2000操作系统逐渐退出历史舞台,使用GDI技术的开发人员也越来越少。
GDI+引入了2D图形的反走样、浮点数坐标、渐变以及单个像素的Alpha支持,同时还支持多种
图像格式。但是,GDI+没有GPU硬件加速功能,所有图形图像处理功能全部都是靠软件来实现。 从应用开发的角度来看,WinForm 已有多年的历史,其技术高度成熟,如果开发的程序不是包含动画、多媒体以及三维图形等对性能要求比较高的程序,使用WinForm编程模型可以获得比较高的开发效率和运行性能
在WinForm编程模型的Main方法中,使用Application类提供的静态方法来启动、退出应用程序。Application类提供的常用方法如下。 o Run方法:用于在当前线程上启动应用程序消息循环,并显示窗体。
o Exit方法:用于停止应用程序消息循环,即退出应用程序。
.创建并显示窗体 要显示一个窗体,必须先创建该窗体类的实例,再调用该实例提供的方法将其显示出来。 例如: MyForm myForm = new MyForm(); myForm.Show(); 或者 MyForm myForm = new MyForm(); myForm.ShowDialog(); Show方法将窗体显示出来后就立即返回,接着程序会
执行Show方法后面的语句代码,而不会等待该窗口关闭,因此,打开的窗口不会阻止用户与应用程序中的其他窗口交互。这种类型的窗口称为“无模式”窗口。 如果使用ShowDialog方法来打开窗口,该方法将窗体显示出来以后,在该窗体关闭之前,应用程序中的所有其他窗口都会被禁用,并且仅在该窗体关闭后,程序才继续执行ShowDialog方法后面的代码。这种类型的窗口称为“模式”窗口。
.隐藏打开的窗体 对于“无模式”窗口,调用Hide方法即可将其隐藏起来。例如,隐藏当前打开的窗体可以用下面的语句: this.Hide(); 隐藏其他窗体可以调用实例名的Hide方法,例如: myForm.Hide(); 窗体隐藏后,其实例仍然存在,因此,可以重新调用Show方法再次将其显示出来。
代码中可以直接调用Close方法关闭窗体。例如,下面的语句将关闭当前打开的窗体: this.Close(); 如果要关闭其他窗体,如关闭用语句Form2 fm = new Form2( );创建的窗体,则使用下面的语句即可。 fm.Close(); 还有一点要注意,不论程序打开了多少个窗体,也不论当前窗体是哪个窗体,只要调用了Application的Exit方法,整个应用程序就会立即退出,用法为: Application.Exit();
4.注册事件 事件是响应用户操作的一种技术。在Windows窗体应用程序中,有3种注册事件的办法。 (1)在窗体的设计界面中双击控件,此时默认会自动注册最常用的事件,例如,按钮的最常用事件是Click事件,所以双击按钮注册的是Click事件。
(2)选择某个控件,然后单击【属性】窗口中的“雷电”符号,就会看到该控件对应的各种事件,双击指定的事件,即可注册对应的事件。 (3)在代码中通过+=注册指定的事件,通过-=注销指定的事件。当熟悉代码后,这种办法是最灵活的,也是方便的。
鼠标右击设计界面,选择【查看代码】 ,添加下面的命名空间引用: using WinFormExamples.F (11)在构造函数的InitializeComponent();语句的下面,添加语句设置主窗体的启动位置。
this.StartPosition = FormStartPosition.CenterS 输入枚举类型的值时有一个小技巧:先输入this.StartPosition =,然后按空格键,它就会自动弹出快捷菜单可选项,选择合适的选项,按回车键即可。
(12)注册Button按钮的Click事件。注册办法为:先输入ButtonHelloWorld.Click +=,然后按两次&Tab&键,就会自动得到下面的代码: public MainForm() { InitializeComponent(); this.StartPosition = FormStartPosition.CenterS ButtonHelloWorld.Click += ButtonHelloWorld_C } private void buttonHelloWorld_Click(object
sender, EventArgs e) {
throw new NotImplementedException(); } ( 13 )鼠标右键单击 buttonHelloWorld_Click ,选择【重构】→【重命名】,将其换名为button_Click。
(14)修改button_Click的事件处理程序,将代码改为下面的内容。 void button_Click(object sender, EventArgs e) { Button btn = sender as B Form fm = switch (btn.Text) { case &显示新窗体&: fm = new HelloWorldForm(); } if (fm != null)
{ fm.Owner = fm.StartPosition = FormStartPosition.CenterP fm.ShowDialog(this); } }
在Windows窗体应用程序中,MessageBox是一个预定义的模式对话框,程序员可以通过调用MessageBox类的静态Show方法来显示消息对话框,并可以通过检查Show方法返回的值来确定用户单击了哪个按钮。注意,这里虽然
使用Show方法显示消息框,但由于它本身是模式窗口,所以在消息框关闭前,不会继续执行该方法后面的代码。
MessageBox的Show方法提供了多种重载形式,常用的重载形式有: public static DialogResult Show(string text) public static DialogResult Show(string text, string caption) public static DialogResult Show( string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon) 方法中各参数的含义如下。
o text:在消息框中显示的文本。 o caption:在消息框的标题栏中显示的文本。 o buttons:MessageBoxButtons枚举值之一,指定在消息框中显示哪些按钮。枚举值有OK、OKCancel、YesNoCancel和YesNo。
o icon:MessageBoxIcon 枚举值之一,指定在消息框中显示哪个图标。枚举值有 None(不显示图标)、Hand(手形)、Question(问号)、Exclamation(感叹号)、Asterisk(星号)、Stop(停止)、Error(错误)、Warning(警告)和Information(信息)。
1.分组(Panel、GroupBox) Panel控件和GroupBox控件均用于对控件进行分组,不同组的控件放置在不同的Panel控件和GroupBox控件内即可。Panel控件与GroupBox控件的不同之处是,Panel控件不能显示标题但可以有滚动条,而GroupBox控件可显示标题但不能显示滚动条。
2.标签(Label)和文本框(TextBox) Label控件用于提供控件或窗体的描述性文字,以便为用户提供相应的信息。Label控件常用的属性是Text属性,该属性表示显示的文本内容。 TextBox 控件的主要作用是允许用户在应用程序中输入或编辑文本,也可以将控件的ReadOnly属性设为true,用来只显示文本,而不允许用户编辑文本框中所显示的内容。 在TextBox中编辑的文本可以是单行的,也可以是多行的,还可以设置为密码字符屏蔽状态作为密码输入框。 TextBox控件的常用属性如下。 o Name:指定控件的名称,以便C#代码可通过它访问控件。
o Text:获取或设置文本框中的内容。 o PasswordChar:指定作为密码输入时文本框中显示的字符,一般用“*”来显示。
3.复选框(CheckBox)和单选按钮(RadioButton) CheckBox用于选择一个或者多个选项,每个选项一般用选中和非选中两种状态表示。 RadioButton 以单项选择的形式出现,即一组RadioButton按钮中只能有一个处于选中状态。一旦某一项被选中,则同组中其他 RadioButton 按钮的选中状态自动清除。
ListBox(列表框)控件和ComboBox(下拉框)控件均用于显示一组条目,以便操作者从中选择一条或者多条信息,并对其进行相应的处理。两个控件的用法基本上完全一样,不同之处仅仅在于控件的外观不一样。
这两个控件的常用属性和方法如下。 o SelectedIndex属性:获取或设置当前选择项的索引序号,-1表示没有选择项。 o SelectedItem属性:获取或设置当前选择项的值。 o Count属性:获取项的个数。 o Items.Add方法:添加项。 o Items.Clear方法:清除所有项。 o Items.RemoveAt方法:删除指定的项。
ErrorProvider 组件一般用于提示用户输入的信息有错误,利用该组件可在指定的控件(如文本框)旁显示一个闪烁的错误图标,当用户将鼠标指针放在闪烁的图标上时,会自动显示错误信息。
WPF是Windows 7、Windows 8操作系统内核默认提供的技术
WPF的界面技术是通过操作系统底层支持的DirectX和GPU硬件加速来实现,而不是通过GDI+来实现。WPF应用程序用于生成能带给用户震撼视觉体验的Windows客户端应用程序。它除了具有传统WinForm应用程序的一般功能外,还具有音频、视频、文档、样式、动画以及二维和三维图形等一体化设计功能。
WPF提供的图形界面呈现技术和布局控件都是矢量形式的,因此可以对窗口进行任意级别的缩放,而且画面的质量不会有任何的损耗。这是基于GDI+的WinForm应用程序无论如何优化都无法做到的。 在Windows 7、Windows 8操作系统上,用WPF应用程序模板来开发客户端应用程序能获得非常高的性能。而在Windows XP操作系统上,虽然也能运行WPF应用程序,但由于它没有操作系统的底层支持,运行性能会大打折扣,显得有些力不能及。 当然,Windows 7、Windows 8操作系统仍然继续支持GDI+,即仍然继续提供Windows窗体应用程序的实现,但
是由于GDI+和DirectX是两套完全不同的实现技术,因此WinForm和WPF本质上也是两种完全不同的应用程序开发技术。
Windows窗体应用程序及WPF应用程序主要用于开发基于C/S的桌面客户端应用程序,而Silverlight是一种插件式的富客户端应用程序,其功能类似于Flash。 Silverlight主要是靠客户端浏览器(IE、Firefox、Chrome)来承载运行,但也可以独立运行。 对于桌面计算机来说,Silverlight应用程序不需要在客户端安装.NET框架,因为它靠安装在客户端的Silverlight插件来运行,就像运行Flash程序时要求必须在客户端安装Flash插件一样。 对于开发人员来说,从API层面上来看,Silverlight应用程序和WPF应用程序出奇地相似,全部都是用XAML来编写页面,后台代码用C#语言来编写。但从内部实现来看,由于Silverlight应用程序需要解决跨浏览器、安装Win
dows Phone操作系统的手机,以及Xbox 360游戏机3种平台的问题,因此它实际上是另一种解决方案和实现技术。 微软公司对Silverlight的定位是主要用来开发基于Windows Phone 7操作系统(简称WP7)或者Windows Phone 8操作系统(简称WP8)的程序,WP 8可安装在平板电脑、移动手机、游戏机、电视机和车载娱乐系统上。 在桌面计算机上,如果客户端使用Windows 7、Windows 8操作系统,而且希望通过IE(建议使用IE 10.0)或者Firefox 浏览器来访问基于Web
的企业级应用程序,用Silverlight 来实现开发效率也非常高,但由于 Silverlight 应用程序受浏览器的沙盒限制(即使提升权限也仍然有一定限制),所以它提供的功能没有基于C/S的WPF应用程序强大。
Silverlight和WPF的语法极其相似,实际上,读者只要学会WPF应用程序和XAML语法,再学习如何用 Silverlight 来编写富客户端浏览器应用程序,可以说是轻而易举的,甚至连实现的XAML和C#代码大部分也都是完全相同的。另外,在浏览器中运行时,由于HTML5支持能在各种操作系统上运行的各种浏览器,比Silverlight更通用
VS2012 还提供了很多其他类型的应用程序编程模型,比如,WCF应用程序、ASP.NET Web应用程序、ASP.NET MVC应用程序,以及只能在Windows 8操作系统上运行的Metro样式的应用程序等。
C#语言的类型系统除了通过.NET框架提供了一些内置的数据类型外,还允许开发人员用类型声明(type declara
tion)来创建自定义的类型,包括类类型(简称类)、结构类型(简称结构)、接口类型(简称接口)、枚举类型(简称枚举)、数组类型(简称数组)和委托类型(简称委托)等。
一种是值类型,另一种是引用类型
匿名类型的局部变量 如果是局部变量,在C#中还可以用var来声明其类型,当开发人员记不清楚它到底是哪种数据类型时,使用 var 声明非常方便。实际上采用这种方式声明的仍然是一种强类型的数据,只是具体的类型由编译器负责推断而已。例如: var key = Console.ReadKey(); 这条语句和下面的语句是等价的: ConsoleKeyInfo key = Console.ReadKey(); 显然,用var声明要方便得多。
给变量赋值时,可采用十进制或十六进制的常数。如果是十六进制常数,在程序中必须加前缀“0x”。例如: long x = 0x12 //声明一个长整型变量x,并为其赋值为十六进制的数据12AB
C#语言中还可以使用十六进制的转义符前缀(“\x”)或 Unicode 表示法前缀(“\u”)表示字符型常量,例如: char c2 = '\x0041'; //字母“A”的十六进制表示 char c3 = '\u0041'; //字母“A”的Unicode编码表示 对于一些特殊字符,包括控制字符和图形符号,一样可以用转义符来表示
public enum MyColor{ Red, Green, Blue} 这行代码的含义是:定义一个类型名为MyColor、基础
类型是int的枚举类型。它包含3个常量名:Red、Green、Blue。3个常量都是int类型,常量值分别为:0、1、2。 上面这行代码也可以写为 public enum MyColor{ Red=0, Green=1, Blue=2}
定义枚举类型时,枚举中的所有常量值必须是同一种基础类型。基础类型只能是8种整型类型之一,如果不指定基础类型,默认为int类型。 如果希望基础类型不是int类型,定义时必须用冒号指定是哪种基础类型。例如: public enum Number:byte{x1=3, x2=5}; 该枚举类型定义了两个常量x1、x2,两
使用枚举的好处是可以利用.NET框架提供的Enum类的一些静态方法对枚举类型进行各种操作。例如,当我们希望将枚举定义中的所有成员的名称全部显示出来,供用户选择时,可以用Enum类提供的静态GetNames方法来实现。
添加 XML 注释时,一定要先定义,然后再在定义的上面按 3 个斜杠(///)添加注释,而不应先键入XML注释后再定义。 另外,如果键入源代码时格式比较混乱,希望快速调整
源程序的格式,可将源程序文件中的最后一个右大括号删除,然后再键入刚删除的右大括号,此时该文件内整个源程序就会按格式自动重新排列。
创建字符串的方法有多种,最常用的一种是直接将字符串常量赋给字符串变量,例如: string s1 = &this is a string.&; 另一种常用的操作是通过构造函数创建字符串类型的对象。下面的语句通过将字符‘a’重复4次来创建一个新字符串: string s2 = new string('a',4); //结果为aaaa 也可以直接利用格式化输出得到希望的字符串格式。例如: string s = string.Format(&{0, 30}&, ' ');  //s为30个空格的字符串 string
s1 = string.Format(&{0, -20}&, &abc&); //s1为左对齐长度为20的字符串
string filePath = &C:\\CSharp\\MyFile.cs&; 为了使表达更清晰,C#规定:如果在字符串常量的前面加上@符号,则字符串内的所有内容均不再进行转义,例如: string filePath = @&C:\CSharp\MyFile.cs&; 这种表示方法和带有转义的表示方法效果相同。
1.字符串比较 如果仅仅比较两个字符串是否相等,直接使用两个等号来比较即可。例如: Console.WriteLine(s1 == s2);    //结果为True Console.WriteLine(s1.Equals(s2));   //结果为True 注意 对于引用类型的对象来说,“==”是指比较两个变量是否引用同一个对象,要比较两个对象的值是否完全相同,应该使用 Equals 方法。但是对于字符串来说,“==”和Equals都是指比较两个对象的值是否完全相同。之所以这样规定,主要是因为字符串的使用场合比较多,用“==”书写起来比较方便。
Contains方法用于查找一个字符串中是否包含指定的子字符串,语法为 public bool Contains( string value ) 例如: if(s1.Contains(&abc&)) Console.WriteLine(&s1中包含abc&);
StartsWith方法和EndsWith方法用于从字符串的首或尾开始查找指定的子字符串,并返回布尔值(true或false)
IndexOf 方法用于求某个字符或者子串在字符串中出现的位置
如果希望得到一个字符串中从某个位置开始的子字符串,可以用Substring方法
o 从startIndex开始插入子字符串value。 public string Insert( int startIndex, string value) o 删除从startIndex到字符串结尾的子字符串。 public string Remove(int startIndex) o 删除从startIndex开始的count个字符。 public string Remove(int startIndex, int count)
o 将oldChar 的所有匹配项均替换为newChar。 public string Replace(char oldChar, char newChar) o 将oldValue 的所有匹配项均替换为newValue。 public string Replace(string oldValue, string newValue)
利用 TrimStart 方法可以移除字符串首部的一个或多个字符,从而得到一个新字符串;利用TrimEnd方法可以移除字符串尾部的一个或多个字符;利用Trim方法可以同时移除字符串首部和尾部的一个或多个字符。
将字符串的所有英文字母转换为大写可以用ToUpper方法,将字符串的所有英文字母转换为小写可以用ToLower方法
String类表示的是一系列不可变的字符。例如,在myString的后面连接上另一个字符串: string myString = &abcd&; myString += & and 1234 &; //结果为&abcd and 1234& 对于用“+”号连接的字符串来说,其实际操作并不是在原来的 myString 后面直接附加上第二个字符串,而是返回一个新String实例,即重新为新字符串分配内存空间。显然,如果这种操作非常多,对内存的消耗是非常大的。因此,字符串连接要考虑如下两种情况:如果字符串连接次数不多(如
10 次以内),使用“+”号直接连接比较方便;如果有大量的字符串连接操作,应该使用System.Text命名空间下的StringBuilder类,这样可以大大提高系统的性能
StringBuilder sb = new StringBuilder( ); sb.Append(&string1&); sb.AppendLine(&string2&); sb.Append(&string3&); string s = sb.ToString( ); Console.WriteLine(s); 这段代码的输出结果如下: string1string2 string3
数组长度是指数组中所有元素的个数。例如: int[] a = new int[10]; //定义一个有10个元素的数组,数组元素分别为a[0]、a[1]……a[9] int[,] b = new int[3, 5]; //数组长度为3*5=15,其中第0维长度为3,第1维长度为5
在C#中,数组的最大容量默认为20GB。换言之,只要内存足够大,绝大部分情况都可以利用数组在内存中对数据直接进行处理。
还可以一次性加载大于20GB 的数组。例如在WPF应用程序中,通过在App.xaml中配置&gcAllowVeryLargeObjects&元素即可达到这个目的。
交错数组相当于一维数组的每一个元素又是一个数组,也可以把交错数组称为“数组的数组”。下面是交错数组的一种定义形式: int[][] n1 = new int[2][] { new int[] {2,4,6}, new int[] {1,3,5,7,9}
}; 注意 初始化交错数组时,每个元素的new运算符都不能省略。 上面定义的数组也可以写为: int[][] n1 = new int[][] { new int[] {2,4,6}, new int[] {1,3,5,7,9} }; 或者写为: int[][] n1 = { new int[] {2,4,6}, new int[] {1,3,5,7,9} }; 还有一点要说明,交错数组的每一个元素既可以是一维数组,也可以是多维数组。例如,下面的语句中每个元素又是一个二维数组: int[][,] n4 = new
int[3][,] { new int[,] { {1,3}, {5,7} }, new int[,] { {0,2}, {4,6}, {8,10} },
new int[,] { {11,22}, {99,88}, {0,9} } };
在实际应用中,我们可能需要计算数组中所有元素的平均值、求和、求最大数以及求最小数等,这些可以利用数组的Average方法、Sum方法、Max方法和Min方法来实现。
对于字符串数组,可以直接利用string的静态Join方法和静态Split方法实现字符串和字符串数组之间的转换。 Join方法用于在数组的每个元素之间串联指定的分隔符,从而产生单个串联的字符串。它相当于将多个字符串插入分隔符后合并在一起。语法为:
public static string Join( string separator, string[] value ) Split方法用于将字符串按照指定的一个或多个字符进行分离,从而得到一个字符串数组。常用语法为: public string[] Split( params char[] separator )
Array是所有数组类型的抽象基类。对数组进行处理时,可以使用Array类提供的静态方法,如对元素进行排序、反转、查找等。常用有以下方法。 o Copy方法:将一个数组中的全部或部分元素复制到另一个数组中。 o Sort方法:使用快速排序算法,将一维数组中的元素按照升序排列。
o Reverse 方法:反转一维数组中的元素。 另外,还可以使用该类提供的Contains方法和IndexOf方法查找指定的元素。
句逐个提取集合中的元素,并对集合中每个元素执行语句序列中的操作。一般形式为: foreach ( 类型 标识符 in 表达式) { 语句序列 } “类型”和“标识符”用于声明循环变量,“表达式”为操作对象的集合。注意在循环体内不能改变循环变量的值。另外,类型也可以使用var来表示,此时其实际类型由编译器自行推断。
goto语句的功能是将控制转到由标识符指定的语句。 格式: goto 标识符; 例如: static void Main(string[] args) {
int i = 0; loop: Console.WriteLine(args[i++]); check: if (i & args.Length) } 需要注意的是,虽然goto语句使用比较方便,但是容易引起逻辑上的混乱,因此除了以下两种情况外,其他情况下不要使用goto语句。 o 在switch语句中从一个case 标记跳转到另一个case 标记时。 o 从多重循环体的内部直接跳转到最外层的循环体外时。
在catch块内,还可以使用throw语句将异常抛给调用它的程序。 1.try-catch语句 C#语言提供了利用 try-catch 捕捉异常的方法。在 try 块中的任何语句产生异常,都会执行catch块中的语句来处理异常。常用形式为: try
{ 语句序列 } catch { 异常处理语句序列 } 或者 try { } 语句序列 catch(异常类型 标识符) {
异常处理语句序列 } 在程序运行正常的时候,执行 try 块内的程序。如果 try 块中出现了异常,程序就立即转到catch块中执行。 在 catch 块中可以通过指定异常类型和标识符来捕获特定类型的异常。也可以不指定异常类型和标识符,此时将捕获所有异常。 一个try语句中也可以包含多个catch块。如果有多个catch块,则每个catch块处理一个特定类型的异常。但是要注意,由于Exception是所有异常的基类,因此如果一个try语句中包含多个catch块,应该把处理其他异常的catch块放在上面,最后才是处理Exception异常的catch块,否则的话,处理其他异常的catch块就根本无法有执行的机会。
y-catch-finally语句 如果try后有finally块,不论是否出现异常,也不论是否有catch块,finally块总是会执行的,即使在try内使用
跳转语句或return语句也不能避免finally块的执行。 一般在finally块中做释放资源的操作,如关闭打开的文件、关闭与数据库的连接等。
有时候在方法中出现了异常,不一定要立即把它显示出来,而是想把这个异常抛出并让调用这个方法的程序进行捕捉和处理,这时可以使用throw语句。它的格式为: throw [表达式]; 可以使用 throw 语句抛出表达式的值。注意:表达式类型必须是 System.Exception 类型或从System.Exception继承的类型。 throw也可以不带表达式,不带表达式的throw语句只能用在catch块中,在这种情况下,它重新抛出当前正在由catch块处理的异常。 除了这些常用的基本语句外,C#还提供了其他一些语句,如
yield 语句、fixed 语句、unsafe语句、lock语句,以及checked和unchecked语句等。
类是封装数据的基本单位,用来定义对象具有的特征(字段、属性等)和可执行的操作(方法、事件等)。自定义类的常用形式为: [访问修饰符] [static] class 类名 [: 基类 [,接口序列]] { [类成员] } 其中带中括号的表示可省略,带下画线的表示需要用实际内容替换。 一个类可以继承多个接口,当接口序列多于一项时,各项之间用逗号分隔。如果既有基类又有接口,则需要把基类放在冒号后面的第一项,基类和接口之间也是用逗号分隔。 类成员包括字段、属性、构造函数、方法、事件、运算符、索引器、析构函数等。 如果省略类的访问修饰符,默认为Internal;如果省略类成员的访问修饰符,默认为private
访问修饰符 类和类的成员都可以使用下面的访问修饰符。 o public:类的内部和外部代码都可以访问。 o private:类的内部可访问,类的外部无法访问。如果省略类成员的访问修饰符,默认为private。 o internal:同一个程序集中的代码都可以访问,程序集外的其他代码无法访问。如果省略类的访问修饰符,默认为internal。
o protected:类的内部或者从该类继承的子类可以访问。 o protected internal:从该类继承的子类或者从另一个程序集中继承的类都可以访问。 类的访问修饰符用于控制类的访问权限,成员的访问修饰符用于控制类中成员的访问权限。类的成员可以是常量、字段、属性、索引、方法、事件、运算符、构造函数、析构函数、嵌套类。 除了上面的访问修饰符以外,还可以使用partial修饰符,包含partial修饰符的类称为分部类。
在C#语言中,通过指定类名来调用静态成员,通过指定实例名来调用实例成员。 如果有些成员是所有对象共用的,此时可将成员定义为静态(static)的,当该类被装入内存时,系统就会在内存中专门开辟一部分区域保存这些静态成员。 static关键字表示类或成员加载到内存中只有一份,而不是有多个实例。当垃圾回收器检测到不再使用该静态成员时,会自动释放其占用的内存。
静态字段有两个常见的用法:一是记录已实例化对象的个数;二是存储必须在所有实例之间共享的值。 静态方法可以被重载但不能被重写,因为它们属于类,而不是属于类的实例。
构造函数一般使用public修饰符,但也可以使用private创建私有构造函数。私有构造函数是一种特殊的构造函数,通常用在只包含静态成员的类中,用来阻止该类被实例化。 如果不指定构造函数的访问修饰符,默认是private。但是,一般都显式地使用private修饰符来清楚地表明该类不能被实例化。
readonly关键字用于声明在程序运行期间只能初始化“一次”的字段。初始化的方法有两种,一种是在声明语句中初始化该字段,另一种是在构造函数中初始化该字段。初始化以后,该字段的值就不能再更改
则其作用就和用 const声明定义一个常量相似,区别是readonly常量在运行的时候才初始化,而const 常量在编译的时候就将其替换为实际的值。另外,const 常量只能在声明中赋值,readonly常量既可以在声明中赋值,也可以在构造函数中赋值。
自定义结构的常用形式为: [访问修饰符] [static] struct 结构名 [: 接口序列] { [结构成员] }
结构和结构成员的访问修饰符只能是以下之一:public、private、internal。由于自定义的结构不能从其他结构继承,所以不能使用protected和protected internal。 如果省略结构的访问修饰符,默认为 internal;如果省略结构成员的访问修饰符,默认为private。
使用自动实现的属性可使属性声明变得更简单,因为这种方式不再需要声明对应的私有字段。例如: class Student
{ public int Age{ } public string Name { } } 上面这段代码中,Age是只读属性,而Name则是读写属性。
更多的用法(如扩展方法、分部方法、匿名方法、迭代器、动态查询、具名参数和可选参数等)
C#程序中定义的方法都必须放在某个类中。定义方法的一般形式为: [访问修饰符] 返回值类型 方法名([参数序列]) { [语句序列] } 如果方法没有返回值,可将返回值类型声明为void。
方法声明中的参数用于向方法传递值或变量引用。方法的参数从调用该方法时指定的实参获取实际值。有四类参数:值参数、引用参数、输出参数和参数数组。
引用参数(reference parameter)用于传递输入和输出参数。为引用参数传递的实参必须是变量,并且在方法执行期间,引用参数与实参变量表示同一存储位置。
引用参数使用ref修饰符声明。 与值参数不同,引用参数并没有再分配内存空间,实际上传递的是指向原变量的引用,即引用参数和原变量保存的是同一个地址。运行程序时,在方法中修改引用参数的值实际上也就是修改被引用的变量的值。 当将值类型作为引用参数传递时,必须使用ref关键字。对于引用类型来说,可省略ref关键字。
抽象类使用 abstract 修饰符来描述,用于表示该类中的成员(如方法)不一定实现,即可以只有声明部分而没有实现部分。 抽象类只能用做其他类的基类,而且无法直接实例化抽象类。 带有abstract修饰符的成员称为抽象成员。 当从抽象类派生非抽象类时,非抽象类必须实现抽象类的所有抽象成员,否则会引起编译错误。 在非抽象类中实现抽象类时,必须实现抽象类中的每一个抽象方法,而且每个实现的方法必须和抽象类中指定的方
法一样,即接收相同数目和类型的参数,具有同样的返回类型。
还可以将类声明为密封类,以禁止其他类从该类继承。 密封类是指不能被其他类继承的类。在C#语言中,用sealed修饰符声明密封类。由于密封类不能被其他类继承,因此,系统就可以在运行时对密封类中的内容进行优化,从而提高系统的性能。 同样道理,sealed关键字也可用于防止基类中的方法被扩充类重写,带有sealed修饰符的方法称为密封方法。密封方法同样不能被扩充类中的方法继承,也不能被隐藏。
继承用于简化类的设计工作量,同时还能避免设计的不一致性。一般将公共的、相同的部分放在被继承的类中,非公共的、不相同的部分放在继承的类中。 1.类继承的一般形式 在C#中,用冒号(“:”)表示继承。被继承的类叫基类
或者父类,从基类继承的类叫扩充类,又叫派生类或者子类
继承意味着一个类隐式地将它的基类的所有成员当作自已的成员,而且派生类还能够在继承基类的基础上继续添加新的成员。但是,基类的实例构造函数、静态构造函数和析构函数除外。
C#在内部按照下列顺序处理构造函数:从扩充类依次向上寻找其基类,直到找到最初的基类,然后开始执行最初的基类的构造函数,再依次向下执行扩充类的构造函数,直至执行完最终的扩充类的构造函数为止。
有以下几种实现多态性的方式。 第一种方式是通过继承实现多态性。多个类可以继承自同一个类,每个扩充类又可根据需要重写基类成员以提供不同的功能。 第二种方式是通过抽象类实现多态性。抽象类本身不能被实例化,只能在扩充类中通过继承使用。抽象类的部分或全部成员不一定都要实现,但是要在继承类中全部实现。抽象类中已实现的成员仍可以被重写,并且继承类仍可以实现其他功能。
解决这个问题的办法其实很简单,只需要将 public B(int age) 改为 public B(int age):base(age) 其含义为:将 B 类的构造函数的参数 age 传递给 A 类的构造函数。程序执行时,将首先调用System.Object的构造
函数,然后调用A类中带参数的构造函数,由于B的构造函数中已经将age传递给A,所以A的构造函数就可以利用这个传递的参数进行初始化。
多态(new、virtual、override)
在C#中,多态性的定义是:同一操作可分别作用于不同的类的实例,此时不同的类将进行不同的解释,最后产生不同的执行结果。
简单地说,当建立一个类型名为A的父类的对象时,它的内容可以是A这个父类的,也可以是它的子类B的,如果子类B和父类A都定义有同样的方法,当使用B对象调用这个方法的时候,定义这个对象的类,也就是父类A中的同名方法将被调用。如果在父类A中的这个方法前加virtual关键字,并且子类B中的同名方法前面有override关键字,那么子类B中的同名方法将被调用。
第三种方式是通过接口实现多态性。多个类可实现相同的“接口”,而单个类可以实现一个或多个接口。接口本质上是类需要如何响应的定义。接口仅声明类需要实现的方法、属性和事件,以及每个成员需要接收和返回的参数类型,而这些成员的特定实现留给实现类去完成。
在基类中,用修饰符virtual表示某个属性或者方法可以被扩充类中同名的属性或方法重写。例如: public virtual string MyProperty{} //扩充类可以重写此属性 public virtual void myMethod( ) //扩充类可以重写此方法 { //实现代码 } 这样一来,在扩充类中就可以使用修饰符override重写基类的属性和方法了。
如果重写基类的虚拟方法,必须在扩充类中用override关键字声明。
在类Triangle中使用base.ShowShape( )是指调用在类Shape中声明的ShowShape方法。对基类的访问禁用了虚拟调用机制,它只是简单地将那个重写了的基类的方法视为非虚拟方法。
只有在扩充类中使用override修饰符时,才能重写基类声明为virtual的方法;否则,在继承的类中声明一个与基类方法同名的方法会隐藏基类的方法。
如果类B继承自类A,类C继承自类B,A中用virtual声明了一个方法M1,而B中用override声明的方法M1再次被其扩充类C重写,则B中重写的方法M1仍然使用override修饰符(而不是virtual),C中的方法M1仍然用override重写B中的M1方法。
隐藏(new) 编写方法时,如果希望扩充类重写基类的方法,需要在扩充类中用override声明;如果希望隐藏基类的方法,在扩充类中需要用new声明,这就是C#语言进行版本控制的依据。 除了重写基类的方法外,还可以在扩充类中使用new修饰符来隐藏基类中同名的方法。 与方法重写不同的是,使用new关键字时并不要求基类中的方法声明为virtual,只要在扩充类的方法前声明为new,就可以隐藏基类的方法。什么情况下需要这样做呢?例如,要求开发人员需要重新设计基类中的某个方法,该基类是一年前由另一组开发人员设计的,并且已经交给用户使用,可是原来的开发人员在该方法前并没有加virtual关键字,但又不无法修改原来的程序。这种情况下显然不能使用override重写基类的方法,这时就需要隐藏基类的方法。
也可以在扩充类中通过base关键字直接调用基类的方法
Math类 Math类定义了各种常用的数学运算,该类位于System命名空间下,其作用有两个,一个是为三角函数、对数函数和其他通用数学函数提供常数,如PI值等;二是通过静态方法提供各种数学运算功能。
Round方法的转换原则,即该方法转换为整数时采用“四舍六入五成双”的原则,就是说,以.5结尾的数字转换为整数时将舍入为最近的“偶数”位。例如,2.5舍入为2,3.5舍入为4。在大型数据事务处理中,此转换原则有助于避免趋向较高值的系统偏差。如果转换为非整数,则采用“四舍五入”的原则。
ateTime表示范围在日午夜12:00:00到日晚上11:59:59之间的日期和时间,最小时间单位等于100ns。 TimeSpan表示一个时间间隔,其范围在Int63.MinVal
ue到Int63.MaxValue之间。
对于中文操作系统来说,默认情况下星期几和月份均显示类似“星期三”、“三月”的中文字符串形式。如果希望在中文操作系统下显示英文形式的月份和星期,还需要使用System.Globalization命名空间下的DateTimeFormatInfo类,例如: DateTime dt = new DateTime(, 12, 30, 40); System.Globalization.DateTimeFormatInfo dtInfo = new System.Globalization.CultureInfo(&en-US&,
false).DateTimeF string s = string.Format(dtInfo, &{0:yyyy-MM-dd HH:mm:ss ddd(dddd),MMM(MMMM)}&, dt); Console.WriteLine(s);
也可以使用ToString方法指定输出格式。例如: DateTime date1 = new DateTime(); Console.WriteLine(date1.ToString(&yyyy-MM-dd ddd MMMM&, new System.Globalization.CultureInfo(&en-US&))); Console.WriteLine(date1.ToString(&yyyy-MM-dd ddd MMMM&, new System.Globalization.CultureInfo(&zh-CN&)));
秒表、计时和随机数(Stopwatch、Timer、Random)
秒表(System.Diagnostics.Stopwatch类)提供了一组方法和属性,利用Stopwatch类的实例可以测量一段时间间隔的运行时间,也可以测量多段时间间隔的总运行时间。 Stopwatch的常用属性和方法如下。 o Start方法:开始或继续运行。 o Stop方法:停止运行。 o Elapsed属性、ElapsedMilliseconds属性、ElapsedTicks属性:检查运行时间。 默认情况下,Stopwatch实例的运行时间值相当于所有测量的时间间隔的总和。每次调用Start时开始累计运行时间计数,每次调用Stop时结束当前时间间隔测量,并冻结累计运行时间值。使用Reset方法可以清除现有Stopwatch实例中的累计运行时间。
System.Windows.Forms命名空间下的Timer类是一个基于Windows窗体的计时组件,利用它可在WinForm中按固定的间隔周期性地引发Tick事件,然后通过处理这个事件
来提供定时处理,如每隔30ms更新一次窗体内容等。该类常用属性、方法和事件如下。 o Interval属性:获取或设置时间间隔。 o Tick事件:每当到达指定的时间间隔后引发的事件。 o Start方法:启动计时器。它和将Enabled属性设置为true的功能相同。 o Stop方法:停止定时器。它和将Enabled属性设置为false的功能相同。
在 WPF 应用程序中,不能使用 WinForm 的 System.Windows.Forms.Timer 类,此时应该用System.Windows.Threading.DispatcherTimer类来实现定时
System.Random 类用于生成随机数。
Random 类的无参数构造函数使用系统时钟生成其种子值,但由于时钟的分辨率有限,频繁地创建不同的Random对象有可能创建出相同的随机数序列。为了避免这个问题,一般创建单个Random对象,然后利用对象提供的方法来生成随机数。
在C#中,有一个特殊的关键字称为“using”。该关键字有3种用途: (1)作为引用指令,用于为命名空间导入其他命名空间中定义的类型。 为了快速引用需要的功能,一般在程序的开头引用命名空间来简化代码表示形式。如果在程序的开头加上: using S 则: System.Console.WriteLine(&Hello World&); 就可以直接写为
接口可以包含方法、属性、事件和索引器。接口只包含成员的声明部分,而没有实现部分,即接口本身并不提供成员的实现,而是在继承接口的类中去实现接口的成员。 在C#语言中,使用interface关键字声明一个接口。语法为: [访问修饰符] interface 接口名称 {
接口中只能包含方法、属性、索引器和事件的声明,不能包含构造函数(因为无法构建不能实例化的对象),也不能包含字段(因为字段隐含了某些内部的执行方式)。另外,定义在接口中的属性、方法等接口体要求必须都是 public的,因此不能再用 public修饰符声明。 接口是用类或结构来实现的,实现接口的类或结构必须严格按照接口的声明来实现接口提供的功能。有了接口,就可以在不影响现有接口声明的情况下,修改接口的内部实现,从而使兼容性问题最小化。 若要实现接口成员,类中的对应成员必须是公共的、非
静态的,并且必须与接口成员具有相同的名称和签名。类的属性和索引器可以为接口中定义的属性或索引器定义额外的访问器。例如,接口可以声明一个带有 get 访问器的属性,而实现该接口的类可以声明同时带有get和set访问器的同一属性。但是,如果显式实现该属性,则其访问器必须和接口中的声明完全匹配。
C#语言提供了两种实现继承的方式:类继承和接口继承。类继承只允许单一继承,如果必须使用多重继承,可以通过接口继承来实现。
委托类型(delegate type)用于定义一个从System.Delegate类派生的类型,其功能与C++语言中指向函数的指针功能类似,不同的是C++语言的函数指针只能够指向静态的方法,而委托除了可以指向静态的方法之外,还可以指向实例的方法。另外,委托是完全面向对象的技术,不会
像C++程序一样,一不小心就会出现内存泄露的情况。 委托的最大特点是,任何类或对象中的方法都可以通过委托来调用,唯一的要求是方法的参数类型和返回类型必须与委托的参数类型和返回类型完全匹配。
定义委托的一般语法为: [访问修饰符] delegate 返回类型 委托名([参数序列]); 例如: public delegate double MyFunction(double x); 这行代码定义了一个名为MyFunction 的委托。编译器编译这行代码时,会自动为其生成一个继承自System.Delegate的类型,类型的名称为MyFunction。
由于事件是利用委托来实现的,因此声明事件前,需要先定义一个委托。例如: public delegate void MyEventHandler() 定义了委托以后,就可以用event关键字声明事件,例如: public event MyEventHandler H 若要引发该事件,可以定义引发该事件时要调用的方法,如下例所示: public void OnHandler()
{ Handler(); } 在程序中,可以通过“+ =”和“- =”运算符向事件添加委托,来注册或取消对应的事件。例如: myEvent.Handler += new MyEventHandler(myEvent.MyMethod); myEvent.Handler -= new MyEventHandler(myEvent.MyMethod);
在实际的应用开发中,绝大部分情况下,实际上使用的都是具有标准签名的事件。在具有标准签名的事件中,事件处理程序包含两个参数,第1个参数是Object类型,表示引发事件的对象;第2个参数是从EventArgs类型派生的类型,用于保存事件数据。 为了简化具有标准签名的事件的用法,.NET框架为开发人员提供了以下委托: public delegate void EventHandler(object sender, EventArgs e)
public delegate void EventHandler&TEventArgs&(Object sender, TEventArgs e) EventHandler委托用于不包含事件数据的事件,EventHandler&TEventArgs&委托用于包含事件数据的事件。如果没有事件数据,可将第2个参数设置为EventArgs.Empty;否则,第2个参数是从EventArgs派生的类型,在该类型中,提供事件处理程序需要的数据。
匿名类型提供了一种方便的方法,利用它可将一组只读属性封装到单个对象中,而无需显式定义一个类型。例如: var v = new { ID = &0001 &, Age = 18 }; Console.WriteLine(&ID:{0},年龄:{1}&, v.ID, v.Age);
在XAML中映射自定义命名空间 除了默认的命名空间之外,在实际开发中,我们还会经常使用自定义的对象(扩展名为.cs的文件或者扩展名为.dll的文件)。如果在XAML中引用这些对象,就必须在XAML中映射自定义命名空间。 如果在项目中添加一个类, 比如在ch07解决方案的cs文件夹下添加一个文件名为MyClass.cs的类,该文件中定义一个MyProperty属性: public class MyClass { public string MyProperty { } public MyClass()
{ MyProperty = &Hello&; } } 要在TestWindow.xaml文件中引用MyClass中的属
性,须满足两个条件:一是MyClass类的访问修饰符必须是public;二是必须在根元素中为其指定一个XAML命名空间。例如: &Window x:Class=&ch07.cs.TestWindow& …… xmlns:c=&clr-namespace:ch07.cs& ……& 在这段代码中,xmlns:c中的c是自定义前缀,也可以将其换成其他字符串,比如: xmlns:myCustom=&clr-namespace:ch07.cs&
XAML的语法与开发Web应用程序时使用的 HTML(超文本标记语言)的语法非常相似,即都是利用元素、特性(Attribute)和属性(Property)来描述元素对象(类的实例)的各种要素。
以下标记创建一个具有红色文本和蓝色背景的按钮,Content 特性用于指定在按钮上显示的文本: &Button Background=&Blue& Foreground=&Red& Content=&按钮1&/&
在XAML中,特性语法是设置对象属性的最简单有效的形式。使用时应该尽量使用特性语法来描述,只有无法用特性语法描述时才使用属性语法。
如果某个属性采用集合类型,可以使用集合语法,此时在XAML标记中,声明该属性的值的所有子元素项都将自动成为集合的一部分。下面的XAML代码用集合语法为GradientStops属性设置线性渐变的值: &Window.Background& &LinearGradientBrush& &LinearGradientBrush.GradientStops& &GradientStop Offset=&0.0& Color=&Red& /& &GradientStop Offset=&1.0& Color=&Blue&
/& &/LinearGradientBrush.GradientStops& &/LinearGradientBrush& &/Window.Background&
根据 XAML 规则的规定,XAML 内容属性的值必须完全在该对象元素的其他任何属性之前或之后指定
XAML中的空白字符包括空格、换行符和制表符。默认情况下,XAML处理器会将所有空白字符(空格、换行符和制表符)自动转换为空格。另外,处理XAML时连续的空格将被替换为一个空格。如果希望保留文本字符串中的空格,可以在该元素的开始标记内添加xml:space=&preserve&特性。但是,要避免在根级别指定该特性,否则会影响XAML处理的性能。
在WPF应用程序中,有两种类型的窗口,一种是WPF窗口(简称窗口),用于直接显示WPF元素;另一种是
WPF导航窗口,用于显示WPF页。
按照窗口的形式来划分,可将WPF窗口分为标准窗口、无边框窗口、浮动窗口和工具窗口。标准窗口是指包含工作区和非工作区的窗口,这是 WPF 默认的窗口;无边框窗口只有工作区部分,没有非工作区部分;浮动窗口和标准窗口类似,但非工作区的右上角只有关闭按钮,不包括最小
化、最大化和还原按钮;工具窗口和浮动窗口相似,但它比浮动窗口多了一个“铆钉”按钮。
为了达到窗口关联这个目的,可以通过设置附属窗口的Owner属性让一个窗口拥有另一个窗口。例如: Window ownedWindow = new Window(); ownedWindow.Owner =
ownedWindow.Show(); 通过这种方式建立关联之后,附属窗口就可以通过Owner属性的值来引用它的所有者窗口,所有者窗口也可以通过OwnedWindows属性的值来发现它拥有的全部窗口。
在 WPF 应用程序中,我们可能希望在主窗口显示前先显示另一个窗口,比如登录窗口或者欢迎窗口,当用户关闭登录窗口或者欢迎窗口后再显示主窗口,要达到这个目的,可以通过主窗口的SourceInitialized事件来实现。 由于引发主窗口的SourceInitialized事件时,窗口还没有显示出来(内部正在进行初始化),所以开发人员可以在该事件处理程序中同时做一些其他的工作。
{ Button btn = sender as B switch (btn.Content.ToString()) { case &确定&: this.UserName = userNameTextBox.T this.Close(); case &取消&: App.Current.Shutdown(); }
App.Current.Shutdown();
.消息框 WPF应用程序的消息框和WinForm的消息框用法类似,区别是其返回值是MessageBoxResult枚举类型,通过枚举可检查用户单击了哪个按钮。 下面的代码演示了MessageBox的典型用法。 常用形式1: MessageBox.Show(&输入的内容不正确&); 常用形式2: MessageBox.Show(&输入的内容不正确&, &警告&); 常用形式3: MessageBoxResult result= MessageBox.Show(&是否退出应用程序?&, &提示&,
MessageBoxButton.YesNo, MessageBoxImage.Question); if (result == MessageBoxResult.Yes) { App.Current.ShutDown( ); }
2.通用对话框 WPF公开的通用对话框有3个:OpenFileDialog、SaveFileDialog和PrintDialog。由于这些对话框是操作系统级别的实现,所以在各种应用程序中都可以使用。
WPF页和页面导航 在WPF应用程序中,既可以用WPF窗口设计界面,也可以用WPF页(Page)设计界面,并通过Window、Frame或者NavigationWindow来承载WPF页。 如果通过Frame或者NavigationWindow来承载WPF
页,还可以实现导航功能。另外,在具有导航功能的窗口中,还可以在 TextBlock 中使用超链接(HyperLink)标记链接到另一个WPF页。
1.在NavigationWindow中承载Page 利用C#代码将NavigationWindow窗口的Content属性设置为页的实例来承载WPF页,即将NavigationWindow作为页的宿主窗口。例如: Window w = new System.Windows.Navigation.NavigationWindow(); w.Content = new PageExamples.Page1(); w.Show(); 采用这种方式时,可以在页中设置导航窗口(NavigationWindow)的标题以及窗口大小。也可以在C#代码中使用NavigationService类提供的静态方法实现导航功能。
Page的常用属性如下。 o WindowTitle:设置导航窗口的标题。
o WindowWidth和WindowHeight:设置导航窗口的宽度和高度。 o ShowsNavigationUI:false表示不显示导航条,true表示显示导航条。 o NavigationService属性:获取该页的宿主窗口中管理导航服务的对象,利用该对象可实现前进、后退、清除导航记录等操作。
2.在Frame中承载Page 第二种方式是在Frame元素中将Source属性设置为要导航到的页,这是使用最方便的页导航方式,也是项目中最常用的导航方式。 在这种方式下,既可以用XAML加载页并实现导航,也可以用C#代码来实现。其宿主窗口既可以是Window,也可以是NavigationWindow。或者说,在WPF窗口中以及WPF页中,都可以使用Frame元素。例如: XAML: &Frame Name=&frame1& NavigationUIVisibility=&Visi
ble& Source=&Page1.xaml& Background=&#FFF9F4D4& /& C#: frame1.Source = new Uri(&Page1.xaml&, UriKind.Relative);
在System.Windows.dll中的System.Windows.Media命名空间下的Brushes类和Colors类都利用静态属性提供了预定义的颜色,这些颜色在各种应用程序中都可以使用。比如设置控件的前景色、背景色、边框色等。
Brushes类的C#语法为 public sealed class Brushes Colors类的C#语法为 public sealed class Colors 可以看出,这两个类都是隐藏类,即只能通过它们提供的静态属性获取或设置颜色。 下面的XAML用Background设置按钮的背景色: &Button Name=&btn& Background=&AliceBlue& Width=&60& Height=&30& Content=&取消&/& 下面的C#代码用Brushes类提供的静态属性实现相同的功能:
btn.Background = Brushes.AliceB 也可以用下面的C#代码实现相同的功能: SolidColorBrush sb = new SolidColorBrush(Colors.AliceBlue);
btn.Background =
Color结构 在System.Windows.dll中的System.Windows.Media命名空间下,WPF还提供了一个Color结构,该结构通过A(透明度)、R(红色通道)、G(绿色通道)和B(蓝色通道)的组合来创建各种自定义的颜色。 用XAML表示颜色时,可直接用字符串表示。一般形式为“#rrggbb”或者“#aarrggbb”,其中#表示十六进制,aa表示透明度,rr表示红色通道,gg表示绿色通道,bb表示蓝色通道。也可以使用“#rgb”或者“#argb”的简写形式,例如“#00F”或者“#F00F”。
下面的XAML设置按钮的前景色、背景色、边框颜色及宽度: &Button Name=&btn1& Content=&确定& Background=&#FFC6ECA7& Foreground=&#FFE00B0B& BorderBrush=&#FFFFC154& BorderThickness=&5& Height=&90& /&
在C#代码中,可分别使用Color结构的A、R、G、B属性获取或设置颜色的某个成分,还可以使用FromArgb方法来创建自定义颜色。例如: Button myButton = new Button(); myButton.Content = &A Button&; SolidColorBrush mySolidColorBrush = new SolidColorBrush(); mySolidColorBrush.Color = Color.FromArgb(255,255,0,0); myButton.Background
= mySolidColorB
形状(Shape)是具有界面交互功能的几何图形的封装形式。System.Windows.Shapes 命名空间定义了呈现2D几何图形对象的类,这些类都继承自同一个Shape类。这些类可作为普通控件使用,就像使用【工具箱】的其他控件一样,既可以用XAML来描述,也可以用C#访问其对应的属性、方法和事件。
从Shape类继承的类也称为形状控件,包括Rectangle(矩形)、Ellipse(椭圆)、Line(直线)、Polyline(折线)、Polygon(封闭的多边形)和Path(路径)。由于Rectangle和Ellipse这两个控件比较常用,所以VS2012将其放在了工具箱中,其他的形状控件没有放在工具箱内。
在XAML中,可直接用特性语法声明这些属性。 1.矩形 Rectangle类用于绘制矩形。例如:
&Canvas& &Rectangle Width=&100& Height=&100& Fill=&Blue& Stroke=&Red& Canvas.Top=&20& Canvas.Left=&20& StrokeThickness=&3& /& &/Canvas&
在WPF应用程序中,画笔(Brush,也叫画刷)是所有控件都具有的基本功能。最常见的是利用画笔设置控件的前景色、背景色,填充渐变色、图像和图案。
SolidColorBrush类提供了Color属性来创建一个纯色画笔。 在C#代码中,创建SolidColorBrush实例后,可通过Color类提供的方法设置Color属性。例如: SolidColorBrush scb = new SolidColorBrush(); scb.Color = Color.FromArgb(0xFF, 0xFF, 0x0, 0x0); button1.Background =
渐变画笔使用沿一条轴彼此混合的多种颜色绘制区域。可以使用渐变画笔来形成各种光和影的效果。还可以使用渐变画笔来模拟玻璃、镶边、水和其他光滑表面。 LinearGradientBrush 使用沿一条直线(即渐变轴)定义的渐变来绘制区域。可以使用GradientStop 对象指定渐变的颜色及其在渐变轴上的位置,还可以修改渐变轴创建水平和垂直渐变并反转渐变方向。 如果不指定渐变方向,LinearGradientBrush默认创建对角线渐变。下面的XAML代码使用4种颜色创建线性渐
变。 &StackPanel& &!--对角线渐变--& &Rectangle Width=&200& Height=&100&& &Rectangle.Fill& &LinearGradientBrush StartPoint=&0,0& EndPoint=&1,1&& &GradientStop Color=&Yellow& Offset=&0.0& /& &GradientStop Color=&Red& Offset=&0.25& /& &GradientStop Color=&Blue& Offset=&0.75&
/& &GradientStop Color=&LimeGreen& Offset=&1.0& /& &/LinearGradientBrush& &/Rectangle.Fill& &/Rectangle& &/StackPanel& 这段代码使用默认坐标系来设置起点和终点。 如果不在LinearGradientBrush中指定MappingMode
属性,则渐变使用默认坐标系。默认坐标系规定控件边界框的左上角为(0,0),右下角为(1,1)。此时StartPoint和EndPoint都使用相对于边界框左上角的百分比来表示(用0~1之间的值来表示)。其中0表示0%,1表示100%。如果将 MappingMode 属性设置为“Absolute”,即采用绝对坐标系,则渐变值将不再与控件的边界框相关,而是由控件的宽度和高度决定。
一般使用默认坐标系实现渐变效果。 线性渐变画笔的渐变停止点位于一条直线上,即渐变轴上。可以使用画笔的StartPoint和EndPoint属性更改直线的方向和大小,例如创建水平和垂直渐变、反转渐变方向以及压缩渐变的范围等。 渐变停止点(GradientStop)的Color属性指定渐变轴上Offset处的颜色。Offset属性指定渐变停止点的颜色在渐变轴上的偏移量位置,这是一个范围从0~1的Double值。渐变停止点的偏移量值越接近0,颜色越接近渐变起点;值越接近1,颜色越接近渐变终点。 渐变停止点之间每个点的颜色按两个边界渐变停止点指定的颜色组合执行线性内插。
线性渐变(LinearGradientBrush)和径向渐变(RadialGradientBrush)都可以用两种或多种颜色渐变填充一个区域。两者的区别在于,LinearGradientBrush 总是沿一条直线定义渐变色填充区域,当然也可以通过图形变换或设定直线方向的起止点被旋转到任何位置;而RadialGradientBrush以一个椭圆为边界,从中心点开始由内向外逐渐填充渐变的颜色。 径向渐变也叫仿射渐变,意思是画笔由原点(GradientOrigin)和辐射到的范围(Center、RadiusX、RadiusY)来
定义。渐变从原点(GradientOrigin)开始由强到弱逐渐向外围辐射,中心点和半径(Center、RadiusX、RadiusY)指定辐射到的椭圆范围,Center 属性指定椭圆的圆心。渐变轴上的渐变停止点指定辐射的颜色和偏移量。 下面的 XAML 代码表示用仿射渐变画笔绘制矩形的内部。 &StackPanel& &Rectangle Width=&200& Height=&100&& &Rectangle.Fill& &RadialGradientBrush GradientOrigin=&0.5,0.5&
Center=&0.5,0.5 & RadiusX=&0.5& RadiusY=&0.5&& &GradientStop Color=&Yellow& Offset=&0& /& &GradientStop Color=&Red& Offset=&0.25& /& &GradientStop Color=&Blue& Offset=&0.75& /& &GradientStop Color=&LimeGreen& Offset=&1& /& &/RadialGradientBrush& &/Rectangle.Fill
& &/Rectangle&
&/StackPanel&
利用WPF设计器实现画笔变换 在WPF设计器中,可直接用鼠标对各种控件进行平移(Translate)、旋转(Rotate)、缩放(Scale)、扭曲(Skew)、反转(Flip)等变换。 将鼠标放在控件的四个角的外侧可看到旋转符号,放在四条边的中间外侧可看到扭曲符号。拖放中心点可修改以哪一个点为旋转中心(即绕哪个点旋转,中心点默认在控件的左上角)。如果希望反转控件(水平翻转、垂直翻转),可通过【属性】窗口来设置。
在C#中,属性(Property)是类对外公开的字段,用get和set访问器实现,这些属性实际上是公共语言运行时属性,简称CLR属性。 除了CLR属性之外,我们还要掌握依赖项属性和附加属性的概念。 1.依赖项属性 在WPF中,为了用XAML描述动态变化的属性值以及用XAML实现数据绑定,除了CLR属性之外,每个控件又用 DependencyProperty 类对 CLR 属性做了进一步的封装和扩展,这些与CLR属性对应的封装和扩展后的属性称为依赖项属性。 依赖项属性的用途是提供一种手段,让系统在XAML或者C#代码中用其他来源的值自动计算依赖项属性的值。有了这种技术,开发人员就可以在样式、主题、数据绑定、动
画、元数据重写、属性值继承以及WPF设计器集成等情况下,对每个界面元素都定义一个与其CLR属性对应的依赖项属性,然后用多种方式使用这个依赖项属性,从而达到灵活控制界面元素的目的。 例如有一个Name属性为button1的按钮,在XAML中或者【属性】窗口中都可以直接设置Width依赖项属性的值: &Button Name=&button1& Width=&100&/& 而在 C#代码中,一般情况下通过 CLR 属性获取或设置该依赖项属性的值即可(button1.Width),此时系统会自动根据上下文处理与其对应的依赖项属性。但在动画等功能中,由于要确保它的基值(用CLR属性保存)不变,动画改变的只是与该CLR属性对应的依赖项属性,此时就必须通过SetProperty方法改变它的依赖项属性的值。动画结束后,再利用CLR属性还原基值(原始值)。
之亦然。 o 在XAML以及【属性】窗口中,都是用依赖项属性来描述控件的某个属性的,此时WPF会自动维护与该依赖项属性对应的CLR属性。 o 在C#代码中,开发人员绝大部分情况下都是使用CLR属性获取或修改控件的某个属性值,此时系统会自动处理与该CLR属性对应的依赖项属性。只有在实现动画等特殊功能时,才需要设置系统无法判断该如何处理的依赖项属性的相关信息。 正是因为这些原因,用 WPF 设计界面时,除了动画等特殊功能以外,我们一般没有必要时刻去关注它到底是依赖项属性还是CLR属性,只需要统统将其作为属性来处理即可。比如设置界面中某个控件的宽度时,在XAML中是利用Width属性来设置,在C#代码中仍然是利用Width属性来设置。
.附加属性 除了依赖项属性之外,在XAML中还有一个功能,该功能可以让开发人员在某个子元素上指定其父元素的属性,以
这种方式声明的属性称为附加属性。 定义附加属性的一般形式为: 父元素类型名.属性名 例如: &DockPanel& &CheckBox DockPanel.Dock=&Top&&Hello&/CheckBox& &/DockPanel& 这段代码中的DockPanel.Dock就是一个附加属性,这是因为CheckBox元素本身并没有Dock这个属性,它实际上是其父元素DockPanel的属性。但是在CheckBox元素内声明了这个附加属性后,WPF分析器就可以确定该CheckBox相对于DockPanel的停靠方式。
附加属性和依赖项属性的最大不同是,依赖项属性声明的是元素自身的属性;而附加属性声明的是其父元素的属性,只是它将父元素的属性“附加”到这个元素上而已。
事件 目前市场上流行的输入设备有4种,分别是键盘、鼠标、触笔和触控。针对这4种输入设备, WPF分别提供了Keyboard类、Mouse类、Stylus类和Touch类,WPF内部自动将这些类以附加事件的形式提供并在WPF元素树上传播,同时在属性窗口中公开类中对应的事件。
1.在XAML中注册事件 在XAML中,声明事件的一般形式为: 事件名=&事件处理程序名& 或者: 子元素类型名.事件名=&事件处理程序名& 有两种声明事件的方法,开发人员可根据对事件的熟悉情况选择其中的一种。 方法1:通过事件列表附加事件。
例如,选中某个 Button 元素,然后通过【属性】窗口找到 MouseDoubleClick 事件,双击其右边的输入框,它就会自动生成对应的附加事件,XAML代码示意如下: &Button Name=&btn1& Content=&B1& MouseDoubleClick=&btn1_MouseDoubleClick&/& 方法2:在XAML中直接键入事件名称。 此时智能提示会帮助完成事件选择,并会自动添加事件处理程序的代码段。
.在C#代码中注册事件 在 C#代码中注册事件的办法和 C#程序设计基础中介绍的办法相同。例如,在构造函数中键入“Button1.MouseDoubleClick +=”以后,再按&Tab&键,系统就会自动添加事件处理程序的代码段。
.事件处理程序中的参数 所有WPF事件处理程序默认都提供两个参数。例如: private void OkButton_Click(object sender, RoutedEventArgs e)
这里的参数sender报告附加该事件的对象,参数e是数据源的相关数据。 在WinForm应用程序中,由于事件不存在路由,所以都是用sender来判断是哪个控件引发事件,而在 WPF 应用程序中,绝大部分情况下都是用 e.Source 来判断事件源是谁。另外,如果是判断图形图像中重叠的部分,则应该用e.OriginalSource,靠命中测试来判断(只命中不是null的对象)。
4.事件路由策略 路由是指在嵌套的元素树中,从某个元素开始,按照某种顺序依次查找其他元素的过程。路由事件是指通过路由将事件转发到其他元素的过程。 WPF 中的事件路由使用以下三种策略之一:直接、冒泡和隧道。这种路由方式和 Web 标准中使用的路由策略相同。因此,理解了WPF的事件路由策略,同时也就明白了在Web应用程序中如何使用事件。 (1)直接 直接(Direct)是指该事件只针对元素自身,而不会再
去路由到其他元素。这种用法和WinForm应用程序中事件的用法相同。
(2)冒泡 冒泡(Bubble)是指从事件源依次向父元素方向查找(即“向上”查找)。就像下面的水泡向上冒一样,直到查找到根元素为止。冒泡查找的目的是搜索父元素中是否包含针对该元素的附加事件声明。利用内部“冒泡”处理这个原理,我们就可以在某个父元素上一次性地为多个子元素注册同一个事件。例如: XAML: &Window ……& &Border BorderBrush=&Gray& BorderThickness=&1& Margin=&154,233,201,109&& &StackPanel Background=&LightGray&
Orientation=&Horizontal& Button.Click=&Button_Click& Margin=&3,33,-3,65&& &Button Name=&YesButton& Content=&是&
Width=&54& /& &Button Name=&NoButton& Content=&否& Width=&65&/& &Button Name=&CancelButton& Content=&取消& Width=&64&/& &/StackPanel& &/Border& &/Window& C#: private void Button_Click(object sender, RoutedEventArgs e) { FrameworkElement source = e.Source as FrameworkE
switch (source.Name) { case &YesButton&:
…… case &NoButton&: …… case &CancelButton&: …… } } 在这个元素树中,StackPanel元素中的Button.Click指明了Click事件的事件源是其子元素的某个Button,因此YesButton、NoButton和CancelButton都会引发Click事件,至于哪个引发,要看用户单击的是哪个按钮。
这段代码中冒泡的含义是:当用户单击按钮时,它先看这个按钮有没有附加事件,如果有,则直接执行对应事件的处理程序,然后再向上查找其父元素(即冒泡),每当在父元素中找到一个针对按钮的附加事件声明,它就去执行与该附加事件对应的事件处理程序,找到多少个就执行多少次。
在【属性】窗口中,凡是没有包含“Preview”前缀的事件都是冒泡路由事件,即都可以在父元素中用附加事件的办法来声明。
在父元素内用“子元素名.事件名”的形式声明事件时有一个技巧,就是先在子元素内添加一个事件(如 Click=&Button_Click&),然后将其剪切到父元素中,最后再添加子元素类型前缀(如改为 Button.Click=&Button_Click&)。之所以这样做,是因为父元素自身可能没有子元素对应的事件。
鼠标事件 常用的鼠标事件有鼠标单击、双击,鼠标进入控件区域、悬停于控件区域、离开控件区域等
6.键盘事件 WPF 提供了基础的键盘类(System.Windows.Input.Keyboard 类),该类提供有关键盘状态的信息。Keyboard的事件也是通过UIElement等XAML基元素类的事件向外提供。
WPF控件有两个共同的基本模型,分别称为控件模型和内容模型。
WPF控件模型 WPF应用程序的控件模型在System.Windows.Control类中实现,所有WPF控件默认都继承自Control类。从使用
的角度来看,WPF控件的基本模型和Web标准的CSS盒模型非常相似,样式控制的设计思路也和CSS样式控制的实现办法相似。
从示意图中可以看出,每个控件都由4个区域组成,这4个区域从里向外分别如下。 o 内容:指显示控件内容的区域,可以是文本、图像或
其他控件元素。 o Padding:内边距。即边框和内容之间的矩形环区域。 o 边框:即内边距和外边距之间的黑色矩形环区域。 o Margin:外边距。指边框和图中虚线包围的矩形环区域,表示该控件和其他控件之间的距离。 在WPF控件中,这4个区域分别用对应的属性来表示,但只有部分控件公开了Padding属性和边框属性。
1.外边距(Margin) Margin属性和Padding属性是使用最多的两个属性,深刻理解这两个属性的含义,对界面设计和布局非常重要。 Margin 用于描述某元素所占用的矩形区域与其容器元素的矩形区域之间的距离,也叫外边距。利用该属性可以精确地控制元素在其容器中的相对位置。
在XAML中,一般用特性语法来描述Margin属性。常用有两种形式,一种是用一个值来描述,例如下面的代码表示按钮周边4个方向的外边距都是10。 XAML: &Button Name=&Button1& Margin=&10&&按钮1&/Button& C#: Button1.Margin = new Thickness(10); Button1.Content = &按钮1&; 另一种是按照“左、上、右、下”的顺序,用4个值分别描述4个方向的外边距。例如下面的代码表示Button2按钮的左、上、右、下的外边距分别是0、10、0、10:
XAML: &Button Name=&Button2& Margin=&0,10,0,10&&按钮2&/Button&
数字的线表示(终端只延伸到网格线),则调整窗口(或页面)大小时,该控件相对于所在单元格左上角的位置保持不变。
C#: Button2.Margin = new Thickness(0, 10, 0, 10); 也可以先在XAML中选择某个元素,然后在【属性】窗口中分别设置这4个值。 另外,在 WPF 设计器中,用鼠标选择某个控件后,它就会自动在控件边缘与其近邻边缘之间用带数字的线(表示保持不变的外边距)和虚线(表示可变的外边距)来指示左、上、右、下4个边的外边距,如图8-2所示。 图8-2 外边距(Margin)的含义 在图8-2(a)中,Button1控件的上边距和左边距用带数字的线表示(终端延伸到窗口),则它相对于窗口(或页面)左上角是固定不变的,即调整窗口大小时,该控件相对于窗口左上角的位置保持不变。
在图8-2(b)中,Button2控件的上边距和左边距用带
2.内边距(Padding) Padding属性用于控制元素内部与其子元素或文本之间的间距,其用法和Margin属性的用法相似。例如: XAML: &Border Background=&LightBlue& BorderBrush=&Black& BorderThickness=&2& CornerRadius=&45& Padding=&25&& &/Border& C#: myBorder = new Border(); myBorder.Background = Brushes.LightB
myBorder.BorderBrush = Brushes.B
myBorder.BorderThickness = new Thickness(2); myBorder.CornerRadius = new CornerRadius(45); myBorder.Padding = new Thickness(25); 这段代码中的最后一行表示Border的四个方向的内边距都是25。 当然也可以像Margin属性那样,按照“左、上、右、下”的顺序,用4个值分别描述4个方向的内边距。
3.水平对齐(HorizontalAlignment) 除了Margin属性和Padding属性外,要灵活地控制元素的位置,我们还需要掌握另外两个常用的属性:HorizontalAlignment属性和VerticalAlignment属性。 HorizontalAlignment 属性声明元素相对于其父元素的水平对齐方式
4.垂直对齐(VerticalAlignment) VerticalAlignment属性描述元素相对于其父元素的垂直对齐方式。可能的取值分别为Top(顶端对齐)、Center
(中心对齐)、Bottom(底端对齐)和Stretch(默认,垂直拉伸)。
用XAML描述控件元素时,一般语法形式为 &控件元素名& 内容模型 &/控件元素名& 从语法上可以看出,WPF内容模型是构成控件内容的基础。
1.Text Text内容模型表示一段字符串文本。TextBox、PasswordBox都属于Text内容模型。 下面是TextBox的XAML语法,它表示其内容模型是Text: &TextBox& Text
&/TextBox&
2.Content Content内容模型表示该内容只有“一个”对象,该对象可以是文本、图像以及其他元素。
在C#中使用对象的Content属性获取或设置内容。由于Content是Object类型,因此控件的内容可以是任何对象。像 Button、RepeatButton、CheckBox、RadioButton、Image 等都属于这种模型。 下面是Button的XAML语法,它表示其内容模型是Content。 &Button& Content &/Button& 下面的代码表示如何用XAML声明Button对象。 &Button Name=&button1& Content=&这是一个按钮&/& 下面的代码表示如何用C#设置Button对象的Content。
button1.Content=&这是一个按钮&;
HeaderedContent表示其内容模型为一个标题和一个内容项,二者都是任意对象。 在C#中,使用对象的HeaderedContent属性获取或设置标题和内容项。 这里有一点需要提醒,TabItem 是一个特殊类型的内容控件,利用它可设置内容和标题。该控件与其他内容控件一样,也可以设置其Content属性。此外,还可以为具有Header属性的内容设置标题。Header属性属于Object类型,因此与Content属性一样,对标题可以包含的内容也没有限制。 TabControl、TreeView等控件均包含TabItem。
4.Items Items 表示一个项集合。可以通过设置控件的 Items 属性来直接填充该控件的每一项。Items属性的类型为ItemCollection,该集合是泛型PresentationFrameworkCollection&T&。 在C#代码中,也可以使用Add方法向现有集合中添加
项,但不能向使用ItemsSource属性创建的集合中添加项。 在XAML中,利用ItemsControl的ItemsSource属性,可以将实现IEnumerable的任何类型用作ItemsControl的内容。通常使用ItemsSource来显示数据集合或将ItemsControl绑定到集合对象。设置ItemsSource属性时,会自动为集合中的每一项创建容器。
5.HeaderedItems 该内容模型表示一个标题和一个项集合。 6.Children 该内容模型表示一个或多个子元素。Children属性的类型为UIElementCollection。 UIElementCollection只能包含UIElement对象,布局控件一般采用这种内容模型。
WPF的布局分类 WPF的布局类型分为两大类:绝对定位布局和动态定位布局。 1.绝对定位布局 绝对定位布局是指子元素使用相对于布局元素左上角(0,0)的坐标(x、y)来描述。在这种布局模式下,当调整布局元素的大小(Width、Height)时,子元素的坐标位置不会发生变化,所以称为绝对定位布局。 传统的WinForm应用程序使用的就是绝对布局。而在WPF应用程序中,使用绝对定位布局的控件只有Canvas控件。 2.动态定位布局 动态定位布局是指布局元素内的子元素位置以及排列顺序随着页面或窗口的大小变化动态调整。在WPF中,除了Canvas布局元素内的子元素采用绝对布局外,其他布局元
素内的元素都是采用动态布局。 WinForm应用程序由于默认采用的是绝对布局,导致其实现各种变换(如旋转、缩放、动画及三维实现等)的布局非常

我要回帖

更多关于 输入法按字母出数字 的文章

 

随机推荐