建立Silverlight2.0控件(Usercontrol)

Silverlight 2.0有一个非常重要的部分,就是控件技术的出现,透过可自行定义开发的控件建立机制,Silverlight ASP.NET一样,可以自行定义可重用的 UserControl,这对于开发人员有着相当重要的意义,这表示对象化的设计、ReUse与大量的开发开始变的可能。

< xml:namespace prefix = o ns = “urn:schemas-microsoft-com:office:office” />

有这些作为基础,我们才有可能真正透过Sivlerlight 2.0建立中大型的应用程序或是RIA,也才有可能确保投资可以延续并且在团队开发当中累积资源。

这么重要的机制,当然要给他试用一下,上图是我尝试建立的traffic light控件,模拟一个红绿灯,一样具有属性、事件、方法……可以跟外部的程序互动,画面中的ButtonTextBox则是Silverlight 2.0当中本来就有的控件,通过.NET Code的开发方式,你可以用C#或是VB,确实比过去1.0时代用JavaScriptAJAX方便很多。

在该控件在被使用者点选之后,会触发一个Click事件,这个事件是我们自己建立出来的,我们可以在这个事件当中改变TextBox内的值(你试用看看就知道)。当然,我们也可以在其他控件(例如按钮)当中来改变灯号(通过traffic light控件的属性),总而言之,这就是一个标准的控件啦。

您可以点选[这里]测试一下这个控件,关于程序代码的说明我会在七月的Run!PC当中介绍,如果您需要Source Code,请私下偷偷Mail给我。

TestDriven.NET(2.7Beta)支持Silverlight/CoreCLR

Silverlight 1.1,在这个微软已经提供下载alpha版本中,包含了一个缩减版的CLR,还有最新发布的Dynamic Language Runtime (DLR)。Silverlight将被插入Internet Explorer、Mozilla和Safari浏览器中,这意味着缩减版的CLR也能够运行在这些平台上。

微软将这个缩减的CLR称为“Core CLR”(核心CLR)(这个核心CLR的代码代号是Tolesto,微软表示这恰巧是一个环绕土星的卫星的名字。)Core CLR将包含garbage collection(碎片帐集)、字体系统、类和很多其他的桌面的CLR的核心功能。它没有包含COM 跨平台支持和其他的一些“你在浏览器中不需要用到的功能”,微软的执行官们表示。

微软并没有公开Core CLR的源代码。它在微软CodePlex源代码仓库中,以Shared Source Permissive许可证的方式开放了DLR的代码。

内容参见
http://weblogs.asp.net/nunitaddin/archive/2007/05/16/test-with-silverlight-coreclr.aspx

Silverlight的InLineXaml功能-让您可轻易地动态产生Xaml代码

  过去我们一直都是通过.xaml文件中的内容来设计Silverlight中的每一个元素的外观长相,有没有想过,如果需要动态的产生xaml代码,而不想通过.xaml文件来完成的时候该怎么办 

  有这种需要吗 有的,而且对于ASP.NET开发人员来说,这类的需求俯拾皆是。

  能够先把.xaml文件设计好,是我们假设早已经知道整个Silverlight功能要显示的内容、图形、或是动画等资源的个数与位置,如果这些信息事先都不知道,得要在执行阶段以ASP.NET的代码来动态决定的时候,显然就无法通过预先写好的.xaml文件来完成。

  最典型的例子是“电子相册”功能的Silverlight程序,当我们要写一套程序来处理“网站上所有用户”的电子相册功能,每一个用户的每一本相册当然都会有不同的图片(相片),不可能都是固定的那几张,所以图片的位置、个数,我们事先都不知道,在执行阶段才有可能知道这些信息,因此我们几乎不可能事先写好.xaml文件,而是要在执行阶段动态的产生.xaml代码的内容。

  又或者,我们要用Silverlight建立一个动态菜单,但是如果.xaml代码是固定的,那菜单内的选项、层级、点选后的HyperLink位置显然都无法任意调整,每次调整都要修改.xaml文件,如此一来相当不方便。

  如果我们可以动态产生.xaml文件,就有着无限的可能性,像刚才提到的菜单、电子相册…等功能,我们都可以在ASP.NET程序的执行阶段,动态决定其内容,甚至可以把Silverlight功能包装在UserControl或是WebControl里,如此一来,使用Silverlight就跟使用控件一样简单。

  由於上述种种原因,Silverlight的.xaml文件必须动态产生的需求相当明显。

  在Silverlight 1.0正式版当中,动态产生xaml代码的功能有着相当不错的简单做法,我们称之为“InLine Xaml”。

  过去我们都是利用Blend 2或是Visual Studio 2005先写好.xaml文件,若是通过InLineXaml的方式,我们就不需要受这个限制了,请看底下的.aspx页面:


  通过这样的方式,我们可以把Xaml代码写在.aspx当中,就不需要再额外建立.xaml文件了。

  您可能会说,那这样只是少写一个.xaml文件而已,跟“动态产生”Xaml代码有什么关系 别忘了,我们还有ASP.NET的“RegisterClientScriptBlock()”指令可用。

  我们可通过ASP.NET代码,配上InLine Xaml的功能,即可动态的产生.xaml代码“喂”给xaml控件,以动态显示需要的.xaml内容。例如,请看底下的.aspx页面:


  我们只有在页面当中布置一个Xaml控件(和一个Button,我们希望按下Button之后,可以动态产生出Xaml文件,这个.aspx页面的HTML代码如下:

  接着,我们在按钮上Double-Click,撰写底下代码:

  如此一来,我们连.xaml文件都不需要撰写,就可以在网页上建立出Silverlight的内容:

  这样的好处是,不只少写了一个Xaml文件,更重要的是,我们可以通过ASP.NET的代码,随意的动态建立出程序当中所需要的Xaml内容。

  例如,我们将ASP.NET代码修改如下:

  很轻松的,我们就可以通过ASP.NET代码在Silverlight当中建立出多个Rectangle,甚至用代码调整其位置:

  再修改一下,我们连颜色也可以动态产生:

  执行结果如下:


  

资料来源: Silverlight权威讲座–ASP.NET整合秘技与独家案例剖析(董大伟 – 旗标)

Silverlight的开发工具

实在是太多人问到Sivlerlight的开发工具了,如果您现在要开发 Silverlight应用程序也好、RIA也好、想要在ASP.NET当中整合Silverlight也好,请安装底下这些开发工具,注意,请依序安装。底下说明每一个工具的用途以及为何需要安装…

笔者建议您“务必依序”安装底下套件:
◎ Visual Studio 2005 → 这个做什么的不用说吧,请最好不要用Express版本

Silverlight 1.0 Run-time(Windows版本) → 用来将你的浏览器外挂Silverlight显示功能

Visual Studio 2005 Services Pack 1 → 要先装这个之后,后面Silvrlight 1.0 SDK才装得起来)

Silvrlight 1.0 SDK → 装这个之后,VS2005中就会有 Silverlight 样板Project(位于C#)

ASP.NET AJAX 1.0 → 要先装这个之后,后面的 Futures Release才装得起来,而且,安装之后,Silverlight 才能够透过AJAX技术读取后端资料库

ASP.NET Futures Release → 让ASP.NET可以轻松整合Silverlight

.NET Framework 3.0(中文版) → 要先装这个之后,后面的 Blend 2 才装得起来

Expression Blend 2(英文版) → 该死的VS2005没有所视即所得,所以需要用Blend 2帮开发人员用拖曳的方式设计Silverlight的UI(请参考此篇文章),除非你的Xaml指令码像奚同学一样滚瓜烂熟。此软件也三五不时有新版,请自己找一下…

完成之后即可开发各式各样的Silverlight应用程序。

Silverlight新书上市-Silverlight权威讲座-现正热卖中

<iframe align=”top” marginwidth=”0″ marginheight=”0″ src=”http://www.zealware.com/csdnblog01.html” frameborder=”0″ width=”728″ scrolling=”no” height=”90″></iframe>

  [博客来网路书店] [天珑书店][本书目录]

  这本书,着实花了笔者不少时间。
  从今年七月开始,笔者在台北、台中、高雄分别主讲了十多数场微软Silverlight相关的研讨会与Hands On Lab,连TechED 2007也是以Silverlight为主题。
  微软更是花大钱摆大阵仗来推广这个新技术。当然罗,您可以慢慢嗅出接下来的Web技术主流在哪里了…
  躬逢其盛,当然也不能缺席,没有抢先在第一时间出版Silverlight的书籍(再一次向读者说声抱歉),实在是因为要整理太多的内容,一个新的技术,怎么和过去我们所熟悉的ASP.NET来整合,是笔者比较关心的主题。也因此,您会看到在这本书当中,把最主要的内容锁定在这个部份,在 ASP.NET和Silverlight的整合议题当中,实在有太多太重要的内容需要向读者介绍。(当然,我们也没有忘记为读者介绍Xaml与SOM)
  如果没有ASP.NET的配合,Silverlight充其量也只会是Flash的另一个竞争对手(不过说实在的,这部份几乎都是交由Designer 来做,而非Developer来做,和开发人员相关性较低),但是加上了JavaScript、ASP.NET、ASP.NET AJAX技术之后,Silverlight摇身一变成为ASP.NET开发人员提升你的Web应用程序功能面和操作界面的一大利器。(对,其实还有功能面的提升,别以为Silverlight只能做UI…)
  同时,为了降低开发人员的进入门槛,我们特别为读者打造了 DynamicXaml 控件,免除 ASP.NET 程序员耗费时间学习 XAML 与 JavaScript,更进一步与 ASP.NET Ajax 技术整合,处理前端事件,让 Silverlight 不只是绚丽的外表,还能真正应用到实务的程序中。通过 DynamicXaml 控件,ASP.NET的开发人员即使不熟JavaScript、不会ASP.NET AJAX,都可以轻松的完成高阶的Silverlight RIA应用程序(Rich Internet/Interactive Application)。
  说真的,就算 ASP.NET开发人员只是为了一个动态图表产生的机制,都值得您通过本书当中所介绍的 DynamicXaml 控件来完成,Silverlight技术其实相当好用。对于ASP.NET开发人员来说,您会发现其实Silverlight有着更深一层的意义… (相关信息请参考截录自书中的试读章节。)

Silverlight权威讲座 – 新书序

Trackback: http://tb.blog.csdn.net/TrackBack.aspx PostId=1861803

silverlight

Microsoft Silverlight是微软所发展的 Web 前端应用程序开发解决方案,是微软丰富型互联网应用程序(Rich Internet Application)策略的主要应用程序开发平台之一,以浏览器的外挂组件方式,提供 Web 应用程序中多媒体(含影音流与音效流)与高度交互性前端应用程序的解决方案,同时它也是微软 UX(用户经验)策略中的一环,也是微软试图将美术设计和程序开发人员的工作明确切分与协同合作发展应用程序的尝试之一。

  silverlight

微软Silverlight是一个跨浏览器、跨客户平台的技术,能够设计、开发和发布有多媒体体验与富交互(RIA,Rich Interface Application)的网络交互程序。   因为Silverlight提供了一个强大的平台,能够开发出具有专业图形、音频和视频的Web应用程序,增强了用户体验,所以SilverLight吸引了设计人员和开发人员的眼球。同时,Silverlight还提供了强大的工具来提高他们的工作效率。

特点

  Silverlight能创建一种具有很高艺术性的应用程序,具有以下的特点:  微软台湾对Silverlight的形象化:蓝泽光

[1]◆一种跨浏览器、跨平台的技术。可以在所有流行的浏览器中运行,包括Microsoft Internet Explorer、Mozilla Firefox, Apple Safari, 和Opera,同样可以运行于Microsoft Windows和Apple Mac OS X。   ◆无论在哪运行,都能提供一致的用户体验。   ◆需要下载很小的文件来安装以支持,只需几秒。   ◆它的视频和音频流,视频质量无论从移动设备还是桌面浏览器都是720p HDTV video模式。   ◆用户可在浏览器中直接对其进行控制,可以拖动、翻转、放大的图片。   ◆它读取数据并且更新外观,但不会通过刷新整体页面来打断用户操作。

特性

  Silverlight将多种技术结合到一个开发平台,可以在其中选择符合需求的合适的工具和编程语言。SilverLight提供了如下的特性:   ◆WPF和XAML。Silverlight包含了Windows Presentation Foundation(WPF)技术,这个技术在创建用户界面时极大的扩展了浏览器元素。WPF可以创建融合图形、动画、媒体和其他的富客户端特性,扩展了基于浏览器的用户界面,超越了HTML所提供的。可扩展应用程序标记语言(XAML)提供了创建WPF元素的声明性标记。   ◆对于JavaScript的扩展。Silverlight提供了对于全球浏览器脚本语言的扩展,从而为浏览器用户界面提供更加强大的控件,包括与WPF元素工作的能力。   ◆跨浏览器,跨平台的支持。Silverlight在所有的流行浏览器(任何平台)运行一致。设计和开发应用程序不需要担心你的用户是什么平台什么浏览器。   ◆与现存应用程序的集成。Silverlight可以与已经存在的JavaScript和ASP. NET AJAX代码无缝集成,不会使已经创建的功能缺失。   ◆可访问.NET Framework编程模型和相关工具。可以使用托管的Jscript和IronPython或者C#和VB这样的动态语言来创建基于SilverLight的应用程序。可以使用Visual Studio这样的开发工具来创建基于Silverlight的应用程序。   ◆LINQ。Silverlight包含集成查询(LINQ)语言。   ◆如果已经使用ASP .NET,可以将Silverlight集成到熟悉的ASP. NET服务器和客户端功能。可以在ASP. NET中创建基于服务器的资源,使用ASP. NET的AJAX特性与服务器端资源交互而不会打断用户。

开发工具

  可以使用已经具有的技能和熟悉的工具来创建基于Silverlight的应用程序,在Web页面中,既可以使用HTML,也可以使用Silverlight的WPF元素,和HTML一样,在Web应用程序中XAML同样可以使用声明的标记来创建用户界面,不同的是,XAML提供了更强大的元素。   可以使用强大的Visual Studio 2008 创建Silverlight应用。(Silverlight在Visual Studio 2008 的IDE中作为一个插件而得到支持。)同样Visual Studio为Silverlight提供了开发工具,比如.NET Framework中已经为创建应用程序提供的强大的编辑器、项目管理、调试等等。   设计人员可以轻松的拥有使用Expression Studio进行设计、编译和发布Silverlight应用程序。Expression Studio有创建图像、媒体,设计交互和产生体验需要的一切能力。Expression Blend能够生成XAML进行输出,这样使用Visual Studio的程序员和使用Expression Blend的设计人员可以共享同样的文件。   Silverlight 的核心是浏览器增强模块,其作用是呈现 XAML 并在浏览器界面上绘制生成的图形。它的下载体积较小(不到 2 MB),可以在用户点击包含 Silverlight 内容的站点时进行安装。该模块向 JavaScript 开发人员公开 XAML 页面的底层框架,以便实现页面级的内容交互,这样,开发人员就可以进行自己的工作,例如编写事件处理程序或使用 JavaScript 代码来处理 XAML 页面内容。   在此,可以表明微软的Silverlight将会更加灵活和交互,并且具有超高的矢量方式,可以对图像进行无限制的伸缩,对flash MX地位发起了挑战。

silverlight+wcf:relationentityVS.relationentity’scode

  本文主要探讨一下,在使用silverlight+wcf进行数据库操作的时候,且约定的交互标准是实体的前提下,在实体中是该使用关系实体的编号作为属性呢?还是将关系实体整体作为属性呢?

  举个例子来说:两个实体,一个是person,用户信息,一个是District地域信息,暂时只考虑中国的5级地域层级,district和person是一个典型的0-1:N关系,在N的一端加入0-1一端的编号作为一个字段来存储,下面是用工具生成的数据库实体

  

代码

<!–<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />–>[DataContract]
    
public class Person
    {
        
private int _code;
        [DataMember]
        
public int Code {
            
get { return _code; }
            
set { _code = value; }
        }
        
        
private  string _name;
        [DataMember]
        
public string Name {
            
get { return _name; }
            
set { _name = value; }
        }
        
        
private int _disCode;
        [DataMember]
        
public int DisCode {
            
get { return _classCode; }
            
set { _classCode = value; }
        }
    }

    [DataContract]
    public class District
    {
        
private int _code;
        [DataMember]
        
public int Code {
            
get { return _code; }
            
set { _code = value; }
        }
        
        
private int _parentCode;
        [DataMember]
        
public int ParentCode {
            
get { return _parentCode; }
            
set { _parentCode = value; }
        }
        
        
private string _name;
        [DataMember]
        
public string Name {
            
get { return _name; }
            
set { _name = value; }
        }
    }
    

 

 

  生成之后,我们可能需要对实体进行调整,因为自动生成的肯定和我们的业务关系不大,它只能原始的反映数据库的结构,帮我们减少一些体力劳动,切忌,一定要修改,出来混迟早要还的。

  我们就像把关系属性的code,改成关系实体本身,修改如下

  

代码

<!–<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />–>    [DataContract]
    
public class Person
    {
        
private int _code;
        [DataMember]
        
public int Code {
            
get { return _code; }
            
set { _code = value; }
        }
        
        
private  string _name;
        [DataMember]
        
public string Name {
            
get { return _name; }
            
set { _name = value; }
        }
        
private District _district;
        [DataMember]
        
public District District {
            
get { return _district; }
            
set { _district = value; }
        }
        
    }

    [DataContract]
    public class District
    {
        
private int _code;
        [DataMember]
        
public int Code {
            
get { return _code; }
            
set { _code = value; }
        }
        
        
private District _parent;
        [DataMember]
        
public District Parent {
            
get { return _parent; }
            
set { _parent = value; }
        }
        
private string _name;
        [DataMember]
        
public string Name {
            
get { return _name; }
            
set { _name = value; }
        }
    }
    

 

 

  比较明显的就是关系,原来都是使用code,现在都换成关系本身了,包括原来是parentcode的属性,也换成parent,类型从int变成了district,看起来很好理解了,而且很容易的想到应该可以增加的好处,使用person.District就可以知道一个人所在地域的名称,要不然光有编号,还需要用编号来查询名称,甚至说显示的时候,不能只显示person的第五级地域信息,也就是不能光显示人员在那个村子,要显示完整的省-市-县-乡-村,这个时候如果地域中由一个District类型的parent就比由一个int类型的parentCode要好用的多。

  因为silverlight是RIA应用,而且在客户端还是有一个运行环境的,虽然运行在浏览器中,但是还是有点类似C/S结构的,只是受到一些限制,同时有自己的一些运行机制。不能直接访问数据库,只能依赖一些服务性的接口来完成数据库交互。wcf是一种可选的方案,wcf交互的标准是SOA,数据都是被序列化成xml,使用wcf之后,往返于client和server端的数据会被序列化,可以使用wcf特有的DataContract和DataMember来标记需要序列化的数据,在上面的实体类中我们已经加上标记。

  加入标记的数据在服务器端就会被反序列化成服务器实体,传输的时候又要将加入标记的数据序列化成xml,在客户端接收数据之后,又会将加上标记的属性反序列化成客户端实体,因为每次要传输数据在客户端的运行时中运行,这就需要我们设计的实体类要减少传输的量,减少传输的数据冗余。

  就拿前面类来说把,如果现在有一个addperson的功能,其实数据库需要的就是一个districtcode就可以保存了,不需要知道disrictname和其他的信息,所以在person中的属性districtcode还不能完全由int改成district类型的district,要不让会多序列化一些name和district的其他属性,如果district有了parent和child的话,那就不止多一两个了,就是说这时候还是用int的districtcode就可以满足要求了,至少需要保留两个属性,一个int的districtcode,一个是district的district,一个用在保存用户的时候,districtcode赋值,district=null;。

  很多时候,很多实体,像我们原来开发ASP.NET的话,关系实体的code,都会被修改成关系实体本身,其实在silverlight中,或者说在客户端有运行环境的情况下,其实一个code就可以了,因为

  1)其他的信息客户端可能早就从服务器获取了,例如code和name的对应关系,因为不像ASP.NET是无状态的,客户端看到的都是html,再丰富的页面到了客户端也都是html+JavaScript,类似silverlight这种RIA的话,客户端有点像C/S,可以有全局变量,可以建立客户端缓存,给client一个code,client就会根据本地信息知道code对应的name。

  2)ASP.NET 这种web应用的话,代码都是运行在server端的,所以由一个code不够,最好是由一个district实体,想要什么属性都可以,而且不存在数据要传输到client,就是几个server之间传输,搞个缓存加快速度,但是silverlight的代码是运行在client端的,就好像一个C/S程序,而且数据从server到client需要序列化,应该尽量减少传输的数据量。

  所以,有时候,一个code就够了。总之,满足要求即可,不必要追求摆放一个关系实体和一个parent好看和好理解的固定模式,可以视情况而定。

工作室將於7月開張

Dear All,

最近,開始籌備個人工作室的相關事宜,工作室會在7月中旬開張,
服務內容定為企業技術顧問及教育訓練,包含了新技術(LINQ,Silverlight 2.0)
的導入服務等等,如有需要,可用我的email與我聯絡,詳細服務內容請參照文末 ^_^

個人簡介:
【台灣微軟最有價值專家】
 Run! PC 雜誌專欄作者
 程序員雜誌文章作者
 PC Magazine 雜誌專欄作者
 MSDN 專欄作者
 MSDN 特約專屬講師
 博碩文化書籍作者
 碁峰資訊書籍作者
 Microsoft .NET專屬講師
 台積電Visual Studio教育訓練講師
 核心智識Visual Studio教育訓練講師
 捷鵬國際教育訓練講師
 文中資訊.NET技術顧問
 台灣通信.NET技術顧問
 富士通Delphi技術顧問

個人著作:

 深入剖析ASP.NET元件設計
 Windows Form框架設計實務
 極意之道-ASP.NET AJAX/Silverlight 聖典
 極意之道-次世代 .NET Framework 3.5 資料庫開發聖典

顧問服務內容及範圍:

 技術問題咨詢
 系統架構咨詢及建議
 特定問題解決方案之提供
 新技術導入

教育訓練:
 Windows Form實戰課程(30小時)
 ASP.NET實戰課程(30小時)
 ADO.NET精通班(20小時)
 LINQ實戰(24小時)
 Silverlight 2.0 實務課程(32小時)

Silverlight实现A*寻径算法

建议在新窗口中查看:
http://www.dotnet.pp.ru/silverlight/SilverlightAStar.html

花了几天的时间研究A*算法,总算是搞出来了。放上来给大伙儿瞧瞧。

点击“StartPoint”指定开始点,点击“EndPoint”指定目标点。点击“Impediment”指定不可通过区域。

GridSize设置节点大小,节点越小,容器中的节点就越多,填好后点Set保存设置。

Clear清除所有。

StartFindPath 开始寻径

Completed Tim 显示寻径所耗时间。

Diagonals 设置是否可以斜着走。

自我感觉速度不错。

下面说说算法的大致流程

 

首先定义两个列表

        private List<PathNote> openedList = new List<PathNote>(); //开启列表

        private List<PathNote> colsedList = new List<PathNote>(); //关闭列表

开启列表中存储待检测节点。关闭列表中存储已检测节点。

 

从开始点开始,拿到开始点周围48个方向的节点,把他们添加进开启列表中。

G等于当前节点的父节点加上10或者14,水平或垂直方向加10,对角线方向加14

H等于当前节点的X的差与目标的的X的差、Y与目标点Y的差的绝对值的和。

 

F = G + H

把当前节点从开启列表中删除。并添加进关闭列表中。以“F”值为依据从小到大排序,把F值最小的节点拿出来,重复以上过程。

大致流程是这样的。细节方面已经有一篇文章写的非常详细,在此也没有必要赘述了。

传送门:http://data.gameres.com/message.asp TopicID=25439

最后放上算法的代码,不多。直接以文本形式发出来算了。

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;

namespace SilverlightAStar
{
    public class PathNote
    {
        public int F; //F = G + H
        public int G;
        public int H;
        public int X;
        public int Y;
        public PathNote parentNote;
    }

    public class PathFinder
    {
        /// <summary>
        /// 矩阵
        /// </summary>
        private byte[,] matrix;
        /// <summary>
        /// 开始点
        /// </summary>
        private Point startPoint;
        /// <summary>
        /// 结束点
        /// </summary>
        private Point endPoint;
        /// <summary>
        /// 开启列表
        /// </summary>
        private List<PathNote> openedList = new List<PathNote>(); //开启列表
        /// <summary>
        /// 关闭列表
        /// </summary>
        private List<PathNote> colsedList = new List<PathNote>(); //关闭列表
        /// <summary>
        /// 是否允许斜线行走
        /// </summary>
        private bool diagonals;
        /// <summary>
        /// 方向
        /// </summary>
        private sbyte[,] direction = new sbyte[8, 2] { { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, 0 }, { 1, -1 }, { 1, 1 }, { -1, 1 }, { -1, -1 } }; //默认方向
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="matrix">待检测矩阵</param>
        /// <param name="startPoint">开始点</param>
        /// <param name="endPoint">结束点</param>
        public PathFinder(byte[,] matrix, Point startPoint, Point endPoint)
        {
            this.matrix = matrix;
            this.startPoint = startPoint;
            this.endPoint = endPoint;
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="matrix">矩阵</param>
        /// <param name="startPoint">开始点</param>
        /// <param name="endPoint">结束点</param>
        /// <param name="diagonals">是否允许斜线行走</param>
        public PathFinder(byte[,] matrix, Point startPoint, Point endPoint, bool diagonals)
        {
            this.matrix = matrix;
            this.startPoint = startPoint;
            this.endPoint = endPoint;
            this.diagonals = diagonals;
            if (!diagonals)
            {
                direction = new sbyte[4, 2] { { 0, -1 }, { 0, 1 }, { -1, 0 }, { 1, 0 } }; //不允许穿角,4方向
            }
        }
        /// <summary>
        /// 开始寻找路径
        /// </summary>
        /// <returns></returns>
        public List<Point> StartFindPath()
        {
            var found = false;
            var pathNote = new PathNote() { F = 0, G = 0, H = 0, X = (int)startPoint.X, Y = (int)startPoint.Y, parentNote = null };
            List<Point> resultPoints = null;
            while (true)
            {
                for (int i = 0; i < (diagonals   8 : 4); i++)  //找到pathNote四方向或八方向周围节点,取F值最小的那个继续此过程
                {
                    var x = pathNote.X + direction[i, 0];
                    var y = pathNote.Y + direction[i, 1];

                    if (x < 0 || y < 0 || x > matrix.GetUpperBound(0) || y > matrix.GetUpperBound(1)) //坐标过界
                        continue;

                    var newPathNote = new PathNote();
                    newPathNote.parentNote = pathNote;
                    newPathNote.X = x;
                    newPathNote.Y = y;

                    bool isClosed = false;
                    bool isOpened = false;
                    PathNote theOpendandSameNote = null;
                    foreach (var closedNote in colsedList)
                    {
                        if (closedNote.X == newPathNote.X && closedNote.Y == newPathNote.Y)
                        {
                            isClosed = true;  //节点已经在关闭列表中
                        }
                    }

                    foreach (var openedNote in openedList)
                    {
                        if (openedNote.X == newPathNote.X && openedNote.Y == newPathNote.Y)
                        {
                            isOpened = true; //节点已经在开启列表中,稍后比较两条路径
                            theOpendandSameNote = openedNote;
                        }
                    }

                    if (matrix[newPathNote.X, newPathNote.Y] != 0 || isClosed) //不能通行或者已经在关闭列表中存在
                        continue;

                    if (Math.Abs(direction[i, 0] + direction[i, 1]) == 2)  //G值
                    {
                        newPathNote.G = newPathNote.parentNote.G + 14;
                    }
                    else
                    {
                        newPathNote.G = newPathNote.parentNote.G + 10;
                    }

                    newPathNote.H = (int)(Math.Abs(endPoint.X - newPathNote.X) + Math.Abs(endPoint.Y - newPathNote.Y)) * 10;  //H值
                    newPathNote.F = newPathNote.G + newPathNote.H;  //F值


                    if (isOpened) //比较已在开启列表中的节点G值和准备创建的节点G值
                    {
                        if (newPathNote.G >= theOpendandSameNote.G)
                        {
                            this.openedList.Remove(pathNote);
                            continue;
                        }
                        else
                        {
                            this.openedList.Remove(theOpendandSameNote);
                            this.openedList.Add(newPathNote);
                            continue;
                        }
                    }

                    this.openedList.Add(newPathNote); //创建节点(添加进开启列表)
                }
                this.colsedList.Add(pathNote); //把当前节点放进关闭列表
                this.openedList.Remove(pathNote); //从开启列表移除当前节点
                foreach (var openedNote in openedList)
                {
                    if (openedNote.X == (int)endPoint.X && openedNote.Y == (int)endPoint.Y) // 到达终点
                    {
                        resultPoints = GetPointListByParent(openedNote, null); //得到以Point构成的路径
                        found = true;
                        break;
                    }
                }

                if (found)
                {
                    break;
                }
                else
                {
                    if (openedList.Count == 0)  //找不到路径
                    {
                        break;
                    }
                    else
                    {
                        openedList.Sort(Compare);
                        pathNote = openedList[0];
                    }
                }
            }
            return resultPoints;
        }

        /// <summary>
        /// 组织传入的PathNote的所有父节点为List
        /// </summary>
        /// <param name="pathNote">PathNote</param>
        /// <param name="pathPoints">列表</param>
        /// <returns>路径</returns>
        private List<Point> GetPointListByParent(PathNote pathNote, List<Point> pathPoints)
        {
            if (pathPoints == null)
                pathPoints = new List<Point>();
            if (pathNote.parentNote != null)
            {
                pathPoints.Add(new Point(pathNote.parentNote.X, pathNote.parentNote.Y));
                GetPointListByParent(pathNote.parentNote, pathPoints);
            }
            return pathPoints;
        }

        /// <summary>
        /// 比较两个节点的F值
        /// </summary>
        /// <param name="x">第一个节点</param>
        /// <param name="y">第二个节点</param>
        /// <returns></returns>
        private int Compare(PathNote x, PathNote y)
        {
            if (x.F > y.F)
                return 1;
            else if (x.F < y.F)
                return -1;
            return 0;
        }
    }
}

 

 

文章出处:http://www.cnblogs.com/zhubenwuzui/archive/2009/09/18/1569534.html 猪笨无罪的博客