一起谈.NET技术,WPF 基础到企业应用系列5——WPF千年轮回2

一,摘要

  首先很高兴这个系列能得到大家的关注和支持,前端时间身体状况不适,所以暂停了更新,对此表示非常抱歉,以后会逐渐加快进度,不过由于这是一个很长的系列,我也想把它写好,所以以后也会慢慢来,在这个系列的过程中也会穿插发一些其他文章,比如Windows Azure、设计模式、WCF、Silverlight等,同时也会发一些自己的技术随感和心得,反正只要自己写得开心且对大家有帮助就行。由于自己才疏学浅且是对这些技术的使用总结和心得体会,错误之处在所难免,怀着技术交流的心态,在这里发表出来,所以希望大家能够多多指点,这样在使一部分人受益的同时也能纠正我的错误观点,以便和各位共同提高。

  这篇课程主要是对上几次课程的回顾和简单深化,所以没有讲什么比较新的概念,不过掌握好了这篇,对后面的很多文章都有帮助,同时这一篇文章做Demo、构思、研究等也花费了不少时间,所以希望对大家有所帮助。

二,本文提纲

· 1.摘要

· 2.本文提纲

· 3.前篇回顾

· 4.Xaml基础

· 5.脱离VS工具CSC编译WPF

· 6.XamlReader与XamlWriter

· 7.本文总结

. 8.系列进度

三,前篇回顾

  在我们日常的开发中,软件企业的开发人员一般会有两种类型的工作:

    1,一类是用户界面设计人员,他们关心的是软件和用户之间的交互,就是如何让用户体验更好;

    2,另一类是软件开发人员,他们关心的是软件的架构设计、业务逻辑的处理和软件功能的实现;

  在BS中,用户界面设计人员使用HTML及其工具来设计界面,开发人员使用Java,C#,VB或其他语言来实现其中的逻辑,HTML网页可以用到最终的产品中。

  在CS中,过去我们一直没有分开这两种不同性质的工作。用户界面设计人员通常和开发人员使用不同的工具,当界面设计人员设计好用户界面时,他们的工作并没有用到最终的产品中,而只是用来展现某种概念或工作流程。

  XAML实现了互联网应用程序和桌面应用程序的统一,界面设计人员可以使用XAML或基于XAML的工具(如微软的Design和 Blend) 来设计CS或BS应用程序的界面。程序开发人员则可以在此基础上使用C#或VB.NET等来开发相应的功能,这样,界面设计人员的工作便自然过渡到最终产品中。

  在XAML中,用户界面用XML的元素或属性来表示。WPF引擎把XAML描述的UI元素解释为相应的.NET对象,从而在桌面程序或Silverlight网页上创建相应的控件。如下图所示:

2  上面这副就是传统的WinForm开发模式,这两种人没有分离开来,所以在很多企业里就形成了开发人员既要做UI也要做程序的境地。

1  上图就是现在的WPF和Silverlight程序的开发模式,这两类人可以分开来工作,他们都可以对Window1.xaml进行修改和加载,所以这样就使分工更专业了,由于大家专注于某一个方面,分工协作的同时,质量和效率也逐渐提高了。

  前几篇介绍了一些基础知识,那么这篇也简单的回顾一下,下面第一幅图是WPF的执行顺序,第二副图是WPF的一个项目的构成,第三幅图是WPF所对应的IL代码(这些图处理得不好,还望各位见谅)。

3WPF的执行顺序

9

WPF的一个项目的构成

10

WPF所对应的IL代码

四,Xaml基础

  这个部分要讲的东西就太多了,由于这篇文章篇幅有限,同时我觉得用代码诠释能让大家可以更清晰地理解,所以就讲得随意一些,通过一个Demo介绍WPF对资源、类、控件的调用和处理,对Dictionary资源、Application资源、window资源以及控件资源的应用等,如下图所示(本篇所有代码在评论的第一条):

4

  由于这些概念比较简单,所以我就不花费大的篇幅来讲这些它们,感兴趣或者对这些知识还有不清楚的朋友可以下载这个Demo进行查看或调试,我觉得对初学者很有帮助。

五,脱离VS工具CSC编译WPF

  为了更好的认识WPF的编译和执行过程,我们可以暂时弃用我们熟悉的VS工具,选用记事本写如下的代码:

using System;
using System.Windows;
namespace KnightsWarrior.HelloWorld
{
class HelloWorld
{
[STAThread]
public static void Main()
{
Window win
= new Window();
win.Height
= 300;
win.Width
= 400;
win.Title
= "Hello,KnightsWarrior!";
win.Show();

Application app
= new Application();
app.Run();
}
}
}

  然后保存到D:\HelloWorld.cs 这个位置,通过CMD或者VS cmomand Line中输入以下编译命令:

csc.exe /out:D:\HelloWorld.exe D:\HelloWorld.cs /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\presentationframework.dll"  /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\windowsbase.dll"  /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\presentationcore.dll"

  然后就可以手动编译成功了。

6

  那么通过 可以查看到它的IL代码,如果感兴趣的朋友也可以进行详细的分析。

5

  如果对MSIL比较熟悉的朋友,也可以用记事本写同样功能的IL代码,由于没有对WPF窗体的IL做具体研究,所以用Console程序代替,等过一段时间再研究WPF控件的IL代码.

.assembly extern mscorlib { auto }
.assembly HelloApp {}
.module HelloApp.exe

.
namespace HelloApp
{
.
class public Program extends [mscorlib]System.Object
{
.method
static private void Main(string[] args)
{
.entrypoint

ldstr
"Hello, KnightsWarrior!"
call
void [mscorlib]System.Console::WriteLine(string)
ret
}
}
}

  然后打开 Visual Studio Command Prompt,使用 ILASM 开始编译。 11  这样你就更能看清楚编译器背后的秘密,同时也能跟踪每一步执行的操作,同时对一些简单的内存泄露问题也比较容易察觉到。当然现在也有很多工具可以跟踪这些问题,我这里只是写一种思路,大家可以根据自己的爱好取舍。

六,XamlReader与XamlWriter

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

  XamlReader类除了定义Load的实时加载之外,也定义了异步方法,可以异步解析XAML中的内容。我们可以在XamlReader对象的实例里调用它们。如果在读取一个大文件时要保持用户UI的响应性,就可以使用异步读取的方法。和异步读取方法匹配的还有一个CancelAsync方法,用于停止读取操作。XamlReader 还定义了LoadCompleted事件,在读取完成后会触发该事件,那么我们就可以把读完后要做的事情都在这里进行处理。

7

  XamlWriter 供一个静态 Save 方法(多次重载),该方法可用于以受限的 XAML 序列化方式,将所提供的运行时对象序列化为 XAML 标记。这句话似乎有点难懂,其实简单的说就是把它序列化为我们需要的类型。

8

  具体功能代码如下:

  通过XamlReader 动态构建并实例化一个Window。

//XamlReader
StringBuilder strXMAL = new StringBuilder("<Window ");
strXMAL.Append(
"xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" ");
strXMAL.Append("xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" ");
strXMAL.Append("Title=\"Window2\" Height=\"600\" Width=\"600\">");
strXMAL.Append(
"</Window>");
var window
= (Window)XamlReader.Parse(strXMAL.ToString());
window.ShowDialog();

  同时我们还可以从文件流中读取并操作。

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

var button
= (Button)window2.FindName("btnTest");
button.Click
+= (x, y) => MessageBox.Show("Knights Warrior");

window2.ShowDialog();
}

  Window2.xaml 的代码:

<Window x:Class="XamlReaderWriterDemo.Window2"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
Title
="Window2" Height="300" Width="300">
<Grid>
<Button Height="23" Name="btnTest" Margin="98,72,105,0" VerticalAlignment="Top">Button</Button>
</Grid>
</Window>

  这里我们需要特别注意的是 XamlReader 载入的 XAML 代码不能包含任何类型(x:Class)以及事件代码(x:Code),也就是说要XAML自身的代码才受支持(这个也在WPF揭秘这本书讲到过)。那么我们可以用 XamlWriter 将一个编译的 BAML 还原成 XAML了,具体代码如下:

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

  输出的Message如下(为了效果更好看一些,我粘贴到了VS):

<Window2 Title="Window2" Width="300" Height="300" xmlns="clr-namespace:XamlReaderWriterDemo;assembly=XamlReaderWriterDemo" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<av:Grid>
<av:Button Name="btnTest" Height="23" Margin="98,72,105,0" VerticalAlignment="Top">Button</av:Button>
</av:Grid>
</Window2>

  XAML 的动态载入在使用动态换肤以及运行时加载等场景颇为有用,以后也会慢慢接触。

  由于使用XamlReader和XamlWriter有很多限制,比如我想把一批Baml转化为Xaml,再比如我想指定Baml的路径,然后通过Load的方式载入,那么这些场景就无法通过XamlReader和XamlWriter完成了,这个让我也做过不少的Demo,也跟踪了很长时间的IL代码,在百思不得其解之后和周永恒、Virus等讨论了一下,最后终于找到了一个方案,如下代码所示:

public static class BamlWriter
{
public static void Save(object obj, Stream stream)
{
string path = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(path);

try
{
string xamlFile = Path.Combine(path, "input.xaml");
string projFile = Path.Combine(path, "project.proj");

using (FileStream fs = File.Create(xamlFile))
{
XamlWriter.Save(obj, fs);
}

Engine engine
= new Engine();
engine.BinPath
= RuntimeEnvironment.GetRuntimeDirectory();
Project project
= engine.CreateNewProject();
BuildPropertyGroup pgroup
= project.AddNewPropertyGroup(false);
pgroup.AddNewProperty(
"AssemblyName", "temp");
pgroup.AddNewProperty(
"OutputType", "Library");
pgroup.AddNewProperty(
"IntermediateOutputPath", ".");
pgroup.AddNewProperty(
"MarkupCompilePass1DependsOn", "ResolveReferences");

BuildItemGroup igroup
= project.AddNewItemGroup();
igroup.AddNewItem(
"Page", "input.xaml");
igroup.AddNewItem(
"Reference", "WindowsBase");
igroup.AddNewItem(
"Reference", "PresentationCore");
igroup.AddNewItem(
"Reference", "PresentationFramework");

project.AddNewImport(
@"$(MSBuildBinPath)\Microsoft.CSharp.targets", null);
project.AddNewImport(
@"$(MSBuildBinPath)\Microsoft.WinFX.targets", null);
project.FullFileName
= projFile;

if (engine.BuildProject(project, "MarkupCompilePass1"))
{
byte[] buffer = new byte[1024];
using (FileStream fs = File.OpenRead(Path.Combine(path, "input.baml")))
{
int read = 0;
while (0 < (read = fs.Read(buffer, 0, buffer.Length)))
{
stream.Write(buffer,
0, read);
}
}
}
else
{
throw new System.Exception("Baml compilation failed.");
}
}
finally
{
Directory.Delete(path,
true);
}
}
}

public static class BamlReader
{
public static object Load(Stream stream)
{
ParserContext pc
= new ParserContext();
return typeof(XamlReader)
.GetMethod(
"LoadBaml", BindingFlags.NonPublic | BindingFlags.Static)
.Invoke(
null, new object[] { stream, pc, null, false });
}
}

  上面的代码,大家可以试一下运行效果。或者有更好的方式也请告知。

七,本文总结

  本篇主要对前几次的课程进了一些简单的回顾,同时用一个比较全的Demo介绍了Xaml中引用各种控件和类等,另外对脱离VS工具CSC编译WPF以及XamlReader与XamlWriter 做了比较详细的介绍。下篇我们将进入WPF布局的世界进行漫游,争取和布局控件及应用来一个全接触!

  最后圣殿骑士 会尽心尽力写好这个系列,同时由于是自己对这些技术的使用总结和心得体会,错误之处在所难免,怀着技术交流的心态,在博客园和51CTO发表出来,所以希望大家能够多多指点,这样在使一部分人受益的同时也能纠正我的错误观点,以便和各位共同提高,后续文章敬请关注!

八,系列进度(红色标示已发布)

· 1. WPF 基础到企业应用系列1——开篇有益

· 2. WPF 基础到企业应用系列2——WPF前世今生

· 3. WPF 基础到企业应用系列3——WPF开发漫谈

· 4. WPF 基础到企业应用系列4——WPF千年轮回

· 5. WPF 基础到企业应用系列5——WPF千年轮回 续前缘

· 6. 使用面板做布局(几种布局控件的XAML及CS代码,综合布局等)

· 7. 依赖属性、附加属性(基本、继承、元数据)

· 8. 路由事件、附加事件

· 9. 命令

· 9. WPF控件分类介绍与使用技巧(ContentControl、HeaderedContentControl…… Decorator)

· 10. 尺寸缩放、定位与变换元素

· 11. 资源

· 12. 数据绑定(基本、值转换、验证、集合的筛选、排序、分组、主从、数据提供者)

· 13. 样式

· 14. 模板

· 15. 多语言、皮肤和主题

· 16. 2D图形

· 17. 3D图形

· 18. 动画(几种动画的应用)

· 19. 音频、视频、语音

· 20. 文档、打印、报表

· 21. 用户控件和自定义控件

· 22. Win32、Windows Form以及ActiveX之间的互用性

· 23. 构建并部署应用程序(ClickOnce部署、微软setup /InstallShield+自动更新组件)

· 24. WPF的模式讲解及实例(MVC Demo)

· 25. WPF的模式讲解及实例(MVP Demo)

· 26. WPF的模式讲解及实例(MVVM Demo)

· 27. 性能优化(WPF项目的瓶颈)

· 28.一个完整WPF项目(普通架构版)

· 39. 一个完整WPF项目(MVVM架构版)

· 30. WPF 4.0新功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/464677.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

排序算法之希尔排序(Java)

希尔排序 平均时间复杂度&#xff1a;O(nlogn) 不稳定的排序算法 v[0]与v[0n/2]比较&#xff0c;v[1]与v[1n/2]比较&#xff0c;v[2]与v[2n/2]比较&#xff0c;小的放到前面&#xff0c;以此类推.............. 关键部分代码如下&#xff1a; public static void shell_so…

AOP和IOC

AOP切面编程&#xff0c;作用&#xff1a;事务&#xff0c;日志&#xff0c;统一调用&#xff0c;统一实现&#xff0c;拦截,分发&#xff1b; 切点&#xff1a;告诉编译器切面作用于哪个package中的class IOC&#xff1a;控制反转&#xff0c;相对于new 对象来说的&#xff0c…

手把手教你|拦截系统调用

一、什么是系统调用系统调用 是内核提供给应用程序使用的功能函数&#xff0c;由于应用程序一般运行在 用户态&#xff0c;处于用户态的进程有诸多限制&#xff08;如不能进行 I/O 操作&#xff09;&#xff0c;所以有些功能必须由内核代劳完成。而内核就是通过向应用层提供 系…

mysql修改列明sql语句_SqlServer修改表名、修改列名T-SQL语句

前面介绍了SQL基本用法《MSSQL数据库常见操作 SQL语句》,但是没有介绍sql修改表的相关操作,本篇文章将介绍T-SQL修改表的相关操作。1。修改表名:execute sp_rename department.mgrig ,mgrid;详述:EXEC sp_rename 表名.[原列名], 新列名, columnTransact-SQL参考sp_rename----…

求2个数的最大公约数

求2个数的最大公约数 该方法只适用于部分数 int gongyueshu(int m, int n) {if ((0 m) || (0 n)){return 0;}while (n)//考虑到n是负数{int temp n;n m % n;m temp; }return m; }

[转载]C 指针

一、认识存储单元指针是C语言最显著的特色。要理解指针的概念&#xff0c;需要先理解计算机读写内存的的方式以及变量的概念。计算机内存是以字节为单位划分内存单元的&#xff0c;每个内存单元占用一个字节&#xff0c;每个内存单元都有自己的地址编号&#xff0c;操作系统或软…

公司年会

没有抽奖的年会肯定是不完美的。有抽奖没有饭局的年会也是很香的。因为疫情&#xff0c;我们没有年终饭局&#xff0c;我也不知道过去那些年腾讯是怎么开年会的&#xff0c;不过今年&#xff0c;我觉得挺不错。上周我们搞了年终活动&#xff0c;我那时候还在开会&#xff0c;CG…

MySQL函数笔记_MySQL笔记之数学函数详解

绝对值函数ABS(x)和圆周率函数PI()复制代码 代码如下:mysql> SELECT ABS(0.5), ABS(-0.5), PI();-------------------------------| ABS(0.5) | ABS(-0.5) | PI() |-------------------------------| 0.5 | 0.5 | 3.141593 |-------------------------------…

给年薪不到48w的程序员提个醒!!

近日&#xff0c;一程序员在脉脉自曝“年薪37W带12人团队&#xff0c;因学历内推腾讯被拒”&#xff0c;引发争议。末流院校&#xff0c;带12人前端团队&#xff0c;到手37w股票20w&#xff0c;过硬的编程技术让他觉得可以出去“闯闯”&#xff1b;内推到腾讯&#xff0c;电话里…

POLYCOM RMX2000 激活与初始化 信令板卡初始化

POLYCOM RMX2000 激活与初始化 信令板卡初始化 上个星期跟组长去建行升级RMX2000的时候遇到的问题就是系统起来后&#xff0c;在“硬件监视器”下可以找到MPMx板卡&#xff0c;但是系统的“IP 网络服务”里面找不到信令板卡。 刚开始以为是板卡激活出现问题&#xff0c;重复了几…

实验二 网络嗅探与欺骗

实验二 中国人民公安大学 Chinese people’ public security university 网络对抗技术 实验报告 实验二 网络嗅探与欺骗 学生姓名 张昊 年级 2015 区队 三 指导教师 高见 信息技术与网络安全学院 2018年9月25日 实验任务总纲 2018—20179学年 第 一 学期 一、实验目…

年终奖

我一个人走在路上&#xff0c;想说点什么&#xff0c;我觉得很难受&#xff0c;去年这个时候我一个高中同学跟我聊天&#xff0c;他跟我说「我听说你们在深圳做程序员的工资很高&#xff0c;我认识的一个朋友在深圳一个月2万多&#xff0c;年终奖发了十几万」。我想&#xff0c…

python barrier_Python线程障碍对象Barrier原理详解

python线程Barrier俗称障碍对象&#xff0c;也称栅栏&#xff0c;也叫屏障。一.线程障碍对象Barrier简介# 导入线程模块import threading# 障碍对象barrierbarrier threading.Barrier(parties, actionNone, timeoutNone)parties — 线程计数器&#xff0c;记录线程数量&#x…

Spring AOP 五大通知类型

1.前置通知 在目标方法执行之前执行执行的通知。 前置通知方法&#xff0c;可以没有参数&#xff0c;也可以额外接收一个JoinPoint&#xff0c;Spring会自动将该对象传入&#xff0c;代表当前的连接点&#xff0c;通过该对象可以获取目标对象 和 目标方法相关的信息。 注意&…

转载CSDN博文精选:Android系列开发博客资源汇总

CSDN博客本期热文推荐&#xff0c;为您介绍有关Android应用开发的10个博客&#xff0c;分享他们的日积月累的宝贵经验&#xff0c;希望这些文章对Android开发者们能有所启发和帮助。 [1] 张国威&#xff1a;Android从入门到提高系列 前面写了十四篇关于界面的入门文章&#xff…

简单工厂模式+工厂方法模式

在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; …

Windows下搭建ESP-IDF开发环境,适合ESP32/S2/C3/S3系列模组二次开发

前言本教程适用于以下两种用户&#xff1a;①无Linux环境搭建经验或搭建Linux开发环境不成功&#xff1b;②使用安信可windows一体化环境IDE V1.5开发环境搭建不成功&#xff1b;本教程提供了windows下搭建 ESP-IDF 开发环境的方法。适用系统&#xff1a;Windows 10 64 位版本、…

python中 1.34e3_Python快速编程入门——第2章 Python基础语法

第2章 python基础语法一、基本语法二、变量和数据类型三、标识符和关键字四、简单数值类型一、基本语法注释&#xff1a;Python的注释是用# 不像C/C使用的是//或者/*/。多行注释好像挺麻烦。行与缩进&#xff1a;Python中的特色是缩进而C/C语言一般都是使用的括号来表示范围。如…

Lync Server 2010的部署系列_第六章 安装配置拓扑生成器、前端Server、前端池

一、安装 Lync Server 2010 管理工具&#xff08;包括拓扑生成器&#xff09; 1) 登录Front.Gianthard.com&#xff08;192.168.1.21&#xff09;。在“Microsoft Lync Server 2010 - 部署向导”页上&#xff0c;单击“安装拓扑生成器”。 2) 进行SQL方面的客户端。 3) 安装成功…

CF1042F Leaf Sets (贪心+树上构造)

题目大意&#xff1a;给你一棵树&#xff0c;让你对叶节点分组&#xff0c;保证每组中&#xff0c;任意两个叶节点之间的距离不大于K&#xff0c;求最小的组数 手动yy的贪心竟然对的 对于每个节点&#xff0c;维护一个$ma[i]$&#xff0c;表示在$i$节点的子树内 未被分组的叶节…