想了解WPF/Silverlight为什么要使用Canvas.SetLeft()这样的方法?的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于wpf和silverlight的相关问题,此外,我
想了解WPF/Silverlight为什么要使用Canvas.SetLeft()这样的方法?的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于wpf和silverlight的相关问题,此外,我们还将为您介绍关于.net – 为什么我需要MVVM用于WPF / Silverlight,有什么理由不能使用MVC吗?、ArcGIS API for Silverlight开发入门(0):为什么要用Silverlight API?、C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(三十九)向Silverlight移植①、My Silverlight系列(10)—— Silverlight中的InkCanvas的新知识。
本文目录一览:- WPF/Silverlight为什么要使用Canvas.SetLeft()这样的方法?(wpf和silverlight)
- .net – 为什么我需要MVVM用于WPF / Silverlight,有什么理由不能使用MVC吗?
- ArcGIS API for Silverlight开发入门(0):为什么要用Silverlight API?
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(三十九)向Silverlight移植①
- My Silverlight系列(10)—— Silverlight中的InkCanvas
WPF/Silverlight为什么要使用Canvas.SetLeft()这样的方法?(wpf和silverlight)
http://www.cnblogs.com/yayx/archive/2008/04/23/1167110.html
看见园子里有兄弟在讨论到关于WPF/SL中的属性的问题,比如:
“为啥flex可以直接对控件的left,top这些属性直接操作,sl还要转一下。这个很难理解,难道是因为dp的好用?相对dp的使用flex的实现简单明了的多了”
正好我最近在研究WPF,在这儿说说我的看法。可能大家大多就是在用WPF或者SL就是做界面,因此首先比较关心界面布局的问题,我就先以WPF的layout为例解释一些用法。
WPF中的布局对象
WPF中不可以给每个界面元素控件都加上"Left"或者"Top"这样的属性吗?其实不是,在一般的布局时,WPF为每个继承自FrameworkElement的组件提供了Margin这个属性,通过这个属性,我们可以轻松的设置四周的边距。再加上HorizontalAlignment和VerticalAlignment属性,我们足以完成一般的元素定位。最常用的,我们在Windows中随便拖一个Button,就会看到生成类似这样的XAML代码:
使用Margin属性,渲染时的控件具体位置是如何决定的?我们可以说是“控件自己决定的”,或者说是“WPF统一决定的”。
除此之外,WPF还提供了另一种布局方式,也就是利用布局对象进行布局,这种布局方式最大的特点是,由父控件统一对子对象的布局进行管理。这样的控件有"Border"(单个子控件),"StackPanel"(流布局),"DockPanel"(停靠布局等),还有最常用的"Gird"。相信大家用这些布局控件已经很熟悉了。我们来看一些示例代码,看看WPF是怎样实现"由父控件统一对子对象的布局进行管理"的。以Canvas作为例子
详细的布局过程可以参考一些书籍(强烈推荐很经典的《Application = Code + Markup:WPF程序设计指南》),这里不多说,注意ArrangeOverride方法中的new Point((double)ele.GetValue(LeftProperty),(double)ele.GetValue(TopProperty)),这一句使用GetValue方法获得了每个子控件的Left和Top属性,然后据此对子控件进行定位。
我不熟悉Flex,就和以前其他布局方式对比一下,比如Winform,Winform时代有个老大帮我们布局。老大说了,我们每个能参与布局的对象都有Left,Top,或者还有Position来指定Relative还是Absolute这样(我确实想到css去了),现在不一样了,因为“权力下放”,WPF把布局的权利直接下放给了布局控件,这就麻烦了,Canvas需要的是Left属性,Top属性,Grid可能需要Row属性,Column属性,DockPanel可能需要Dock属性,那怎么办呢?于是我们就使用Attached Property,把属性定义在各个“小老大”下面,下面参与布局的“小兄弟”就使用Attached Property的方式来设置和读取这些属性的值。
也许你问这种“权力下放”有什么好处,如果你从WPF自带的一些布局控件还体会不到好处的话,我推荐一个链接,大家可以看看各式各样的炫酷的自定义Layout:
Why WPF Rocks (Custom Layout Panel Showcase)
其实,如果你坚定的想为每个“小兄弟”建立一个Left和Top的话,你完全可以自己实现类似如下的代码:
不知你感觉如何,反正我不喜欢这样的实现。MyFrameworkElement和MyCanvas被强耦合在一起了,我不知道DockPanel控件是否还需要Left和Top属性,但是这两个属性确实存在,难道我需要定义MyFrameworkElementForCanvas,MyFrameworkElementForDockPanel...?太恐怖了
不过插一句,WPF中并没有所谓的特定的“布局对象”,其实每一个视觉对象(Visual)都可以为自己的子对象(们)安排布局。
形成模式
抛开布局不谈,从设计模式和面向对象的设计来说,这种设置属性值的方式可以算一种很有意义的模式,他很漂亮的分离了属性(Left),拥有属性的对象(Element),定义属性的对象(Canvas),属性值四者之间的耦合关系。DependencyProperty和AttachedProperty不仅在layout system中有很大的用处,在数据绑定,动画支持,资源,风格等都有很好的应用。
当然,任何复杂的设计都是有代价的,这种方式最大的代价也许是性能,虽然在值得存储上WPF进行了很多优化(可以参考我的另一篇即将发布的Post),但性能损失肯定存在。另一方面,复杂的设计必定会增加用户(我们程序员)使用的复杂度,也就是我们必须使用GetValue或者是SetValue方法去获取值了。不过在使用复杂度上面,WPF进行了一些官方的规范处理,他希望普通的DependencyProperty都能被封装成名为"CLR Wapper"的get/set方法,AttachedProperty封装成类似Canvas.SetLeft(v,150) 这样的语法,于是,便出现了Canvas.SetLeft()这样的方法。。
另外Silverlight本身还只是Beta版本,所以最好别拿Silverlight说事儿。呵呵,我还是很喜欢WPF。
总结
这一篇Post首先从WPF的布局系统说起,介绍了布局系统中是如何应用AttachedProperty的,然后总结的阐述了为什么会出现Canvas.SetLeft()这样的语法。 以上是我个人的一些看法,如果有什么不对希望大家多多指正~
.net – 为什么我需要MVVM用于WPF / Silverlight,有什么理由不能使用MVC吗?
解决方法
MVC中缺少的部分实际上是MVVM模式,在我看来它只是MVVM的隐藏部分.如果你看一下大多数MVVM框架,大多数提供某种消息或通知系统,它真正提供了MVC缺少的控制器方面.
可以将viewmodel视为View的代码隐藏,View作为View的Designer,Model作为模型,Notification / Messaging系统作为Controller,我们有一个真正等效的模式.
这对我来说也很难理解(我也来自MVC模式,但现在喜欢MVVM模式).
ArcGIS API for Silverlight开发入门(0):为什么要用Silverlight API?
看看现在计算机应用的趋势吧。云(计算),这个东西可讲不清楚,因为云嘛,飘忽不定的。不过可以这样来看它,以后计算机网络上就有一坨(或者几坨)万能的云,有什么需求云都可以满足我们,包括各种资源或者计算工作,就不需要在自己的机器上安装任何软件了(甚至操作系统都可以由天边那朵云来提供给你)。更具体点,SaaS(Software as a Service),各种的网页邮件系统, google docs (一个在线的office)都是SaaS。收发邮件登陆一个网页就行,而不需要在自己机器上安装一个软件。这就是计算机应用的一个趋势,把所有东西都做到网上。再来看看网上的趋势:RIA(Rich InternetApplication)。RIA简单来讲就是一个网页(网络应用),在完成基本功能的同时,会让你觉得很漂亮,操作起来很舒服,效果很炫,而不是打开后立刻就想关掉它。其实大受欢迎的开心网(各种插件)和twitter,甚至QQ空间等,都有RIA的身影。
好了,ArcGIS之所以在行业领先,特点之一就是它能紧跟计算机发展的趋势。ArcGIS Online就是那朵天边的浮云;JavaScript API,Flex API,Siverlight API就是ArcGIS自己RIA的三驾马车。
这里还得插一句,我觉得ArcGIS Server的主角本来是ADF,通过它我们可以完成一个无所不能的ServerGIS。但在大多数情况下,GIS都是作为特定的业务嵌入在一些MIS中的,相比购买ADF这辆悍马来说,还是直接驾驭三套车跑的更轻快一些。
现在看看我们的主角。其实是ArcGIS API forSilverlight/WPF(以下专注Siverlight部分),那么Silverlight和WPF的关系如何呢?Silverlight原来叫WPF/E,E就是Everywhere,从命名可以看出它们的关系:Silverlight是WPF的一个子集。WPF是.NETFramework 3.0的组成部分之一,微软视其为下一代用户界面,总之很高档就是了(在Vista和Windows7中看到的大量与XP不同的界面,就是WPF的身影);Silverlight可以看做是WPF在浏览器里的一个外挂,用于向网络用户展示自己的强大能力,由于受限于网络环境,所以是WPF的一部分核心功能。Siverlight的设计初衷是跨平台,跨浏览器的。
如果这些还是比较抽象,那么可以造一个排比句来进一步说明。之前先肯定一点,Flash现在在网络中的的主导地位。开始造句。Adobe有Flash,微软有Silverlight;Adobe有AIR,微软有WPF;Flex有mxml,Silverlight有xaml;Adobe有ActionScript,微软有Code-Behind(C#/VB.NET)或者JavaScript;Adobe有CS(包括Dreamweaver,Flash,Fireworks,Photoshop,Illustrator),微软有ExpressionStudio(包括Blend,Web,Design,Media,Encoder)。现在,能够看来Siverlight到底是何方神圣了吧?
最后再来说说ArcGIS这三驾马车(JavaScript API,Flex API,SiverlightAPI)。国外有人说,随着Siverlight API的推出,与Flex API一起,将会使JavaScriptAPI慢慢退出历史舞台,因为前两者就是为RIA而生的。但其实也不然,随着Google和Mozilla工程师的推进,他们能够 使JavaScript的执行速度提高非常多 ,Chrome就是例子。在这种背景下,一些非常cool的程序员会让古老的JavaScript获得重生。到底哪匹马跑得更快?别回答这种问题,赶紧挑一匹自己的马儿,快马扬鞭吧~~
在今年的ESRI开发用户大会上,一阵鼓声过后,ESRI隆重推出了ArcGIS API for Silverlight/WPF(beta)。接下来我将把自己在学习Silverlight API中的一些经历和大家分享,与大伙共同进步。
C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(三十九)向Silverlight移植①
深蓝Silverlight-MMORPG游戏引擎单机部分即将开源;这两节里,我将为大家讲解本教程示例游戏从WPF向Silverlight移植的一些关键性优化与性能提升技巧,以及新增加的内容等等。接下来的时间里,我将接着前面的教程,通过Silverlight平台继续为大家演义,目标只有一个:誓将Silverlight游戏引擎完美到底!
一、主要改进:
1)Silverlight3.0上的右键实现:
HtmlPage.Document.AttachEvent("oncontextmenu", Game_MouseRightButtonDown);
}
通过上述方法还必须配合<param name="Windowless" value="true" />或System.Windows.Interop.Settings.Windowless = true才能实现右键功能。另外需要特别说明的是,此方法并非官方所提供的解决方案,而是第三方间接的实现方式。因此,在使用前,您必须解为Silverlight解禁右键将付出的代价:①Windowless = true将降低程序整体性能;②无法使用输入法;③无法被所有的浏览器所兼容,例如在Google Chrome中,虽然可以激发出右键功能,但是取消不了弹出右键菜单。综上,在Silverlight3.0中,您还是得谨慎再谨慎的考虑是否使用右键。
2)撤消精灵及其他所有控件中的x,y,z坐标定位用关联属性,取而代之的是一个名为Coordinate的关联属性,其完整定义如下:
}
Coordinate的类型为Point,因此,我将原先精灵移动用的DoubleAnimation动画类型替换成了PointAnimation;这样,不论是在代码结构还是性能上均得到很大的优化。更改控件坐标时,只需修改它的Coordinate = new Point(x,y)即可,系统会判断该关联属性的值是否发生改变而激发ChangeCoordinateProperty方法,从而更新该控件最终在画面中的LeftProperty、TopProperty和ZIndexProperty。没错,关联属性就是这么强大。
3)A*移动的优化。我已留下接口,根据不同的参数设置,可以启动不同效率、不同路径长短、不同精确度的A*寻路,这里我给大家推荐两种现成的方案,第一种—程序默认A*寻路方案,此方案找到的路径最精确,但性能消耗最高;另一种方案可以实现最高效的寻路,但得到的路径并非最短:
};
我在Silverlight引擎中封装的A*寻路DLL,是根据教程第七节的老外A*改编而成。因此,您完全可以将之作为一个调试器,调试不同的搭配方案,然后将参数赋予pathFinderFast里:
例如上图,我通过模拟测试,发现最终找到路径所消耗的时间为0.0071秒,假如我已对此设置所产生的路径长度与性能感到满意,那么接下来要做的就是将此方案的配置记录下来: Diagonals = true ; Heavy Diagonals = true ; Henuristic = 5 ; Formula = Max(DX,DY) ; Use Tie Breaker = false ; Search Limit = 40000 ; 寻路对象使用的是FastPathFinder。
OK,最后来在Silverlight引擎中,我就可以这样来启动A*寻路:
};
嘿嘿,其实使用A*是可以如此简单的,不是吗?
二、主要优化:
1) 地图切片实现了最优化加载方法。即不需要额外做多余判断,也无需每次对切片容器进行Clear。只需按从到8的顺序对这9个切片重新赋值Source即可,性能真的很优哦:
}
2)改进了 “托盘式”主位地图移动模式。首先我想向一些朋友道歉,一时找不到是哪篇文章后面评论中有提到对一个Canvas进行移动而不是遍历所有精灵,这样可以提升逻辑方面的性能;我当时有测试过,为什么一直坚持不行,因为我没转过弯,主角和其他所有对象是完全可以放在一个Canvas里的,这也意味着它们的ZIndex顺序照样可以很好的处理,同时实现“托盘式”地图移动模式。最终在QQ群里“内Cool超人”的感化下,我才得以觉醒。这样,虽然画面性并无提升,但是,配合上Coordinate坐标关联属性的回调方法使用,可以去掉循环遍历地图上所有对象位置,在逻辑上大大的提升了性能。
3)隐藏远离画面窗口的精灵对象。这是基于Web游戏所必须做的处理,它将大大减少不必要元素的呈现及逻辑运算:
……
}
……
}
……
在间隔0.5秒的辅助计时器事件中进行类似如上判断,当某个精灵超出了主角可视范围,即在我们屏幕窗口所能看到的区域以外,则将之隐藏掉,并停止它的切帧动作,否则反之。这对提升游戏整体性能起着决定性关键作用。如果是网络版,我们则可以拓展出2级范围,其中1级范围即为上述范围;而2级范围则为:当某个已被隐藏的精灵远离主角到了更遥远的地方,则我们将之移除掉,从而减少逻辑且实现不必要资源的及时释放与回收。
4)改进了时时障碍物系统。整个游戏有两个障碍物数组(可以记录0-255,代表障碍物,除外的所有其他字节均代表无障碍。这里我使用1标识无任何对象可通行区域,10-19用来标识传送点。如果以后需要加入新的地形效果拓展,那么同样可以使用类似设定:例如20用来标识可通行水域,21标识可通行沙漠等等;这样,现当主角在这些区域中移动时,会发出相应的脚步声,使游戏效果更为逼真)。动态障碍物系统实现代码如下,首先定义一个固定数组和一个动态数组:
byte[,] fixedObstruction, varyObstruction;
fixedObstruction是地图加载后永远不变的地图信息描述载体,它记录了地图中肯定无法通过的地形及传送点的位置等等。varyObstruction是时时的动态地图信息,会根据所有精灵时时的位置来填充障碍物。
在每次A*移动时,我们通过先去掉精灵脚底的障碍物区域(HoldWidth和HoldHeight),然后启动A*寻路,找到路径后再补回精灵的脚底障碍物区域:
……
SetSpriteObstruction(sprite, 0);
……
其中SetSpriteObstruction方法为:
}

出处: http://alamiye010.cnblogs.com/
教程目录及源码下载: 点击进入( 欢迎加入WPF/Silverlight小组 WPF/Silverlight博客团队)
本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面显著位置给出原文连接,否则保留追究法律责任的权利。
原文链接: http://www.cnblogs.com/alamiye010/archive/2009/11/03/1595141.html
My Silverlight系列(10)—— Silverlight中的InkCanvas
有许多人喜欢手写板或者涂鸦板之类的东西,而并不怎么喜欢输入法,因此Microsoft专门有Ink这个东西用于处理鼠标画图。不得不说这个东西功能十分的强大,也让许多用户使用起来非常方便,用微软开发出来的很多Ink与Bitmap结合的API,即使不会用Photoshop的人也能轻松打开一张图片,然后在自己喜欢的地方写上一段话或者签个名什么的。这个功能,Winform上面有,WPF上面也有,当然Silverlight上也有,只不过作为起步不久的Silverlight版Ink,功能尚不够强大,目前能够开放给我们使用的,只有InkPresenter这一个控件。
也许开发WPF的人都没怎么听说过这个控件而只听说过InkCanvas——那是一个在WPF上对Ink功能封装得非常完善的控件,我们可以使用它进行画图和橡皮擦等一系列的事情。当然,如果你去研究过这个控件,你就可以发现其实它其实是通过DataBinding在InkPresenter上进行了进一步的封装。由于WPF与Silverlight不同的继承结构,恐怕在Silverlight上很难照搬WPF上那一套,即我们不能对其进行一对一的Port,所以如果要在Silverlight上实现一个InkCanvas,就要另辟蹊径。
如果你使用过WPF的InkCanvas控件,你将会发现它支持EraseByPoint,EraseBystroke,Ink三种模式,而且支持复制、粘贴,而且可以轻松地扩展出撤销与重做两个功能。但是后面的一系列功能,不是InkCanvas的核心功能,只要前三者得以实现,那么这个InkCanvas就可以正常的运作了。那么,我们首先从这三种模式中用于画图的Ink模式说起。
InkCanvas的核心,其实在于它内部的InkPresenter,在Silverlight中InkPresenter仅仅是Canvas的子类,只不过它多了strokes这么一个属性用于存储和展示画上去的所有stroke。因此,它把如何生成一个stroke的问题完全留给了我们。先来看一下stroke的定义:
其中DrawingAttributes这个属性是用于描述画笔的颜色的,而StylusPoints描述了stroke内点的集合。学过数学的人都知道,线是由点组成的,因此只要我们找到了应该插入到这个stroke中所有的点,那么生成一个新的stroke不在话下。所幸MouseEventArgs中,有一个StylusDevice只读属性,而它的一个公共方法public StylusPointCollection GetStylusPoints(UIElement relativeto)可以在鼠标事件触发的时候,得到这些“点”的集合。我们只需要为InkPresenter加上MouseLeftButtonDown,MouseMove,MouseLeftButtonUp三个handler,那么我们就可以在鼠标进行轨迹上把那些点加到线上,并将这条线加入到InkPresenter这个“面”里。代码比较多,最后我会把工程放在下面,就不一段一段的贴了。
其实这个Ink模式,不算什么难点,而后面这个EraseBystroke也相对简单,最笨的方法就是遍历InkPresenter内所有的stroke,然后一一检验它是否与我们的"Eraser"有交叉,如果有,则将它Remove。但是,最后这个EraseByPoint可没那么容易了,因为当橡皮将一条线拦腰截断的时候,不但要把擦掉的部分去掉,还要把余下的两段保留在strokes这个strokeCollection中,这才能达到一分为二的效果。我最初在实现这个功能的时候,由于设计的算法时间复杂度居高不下,造成如果相交的线过多,或者橡皮拖动太快,就会出现卡死的现象。在与微软silverlight开发小组的stefan swick交流之后,他决定实现这一功能,并且将其做成一个Custom Control。昨天他告诉我他把这个东西做好了,要我去他的Blog上下载。今天我仔细研究了他的算法,发现这个算法与我的算法有一个最大的不同之处就是:我在将一条线一分为二的过程中,完全是按照从前向后的顺序,将每个点一一挎贝并缓存,从前向后判断这个点是否被橡皮擦中,如果被擦中的话,马上生成一个新的stroke,把旧的加入strokes内,并对新的stroke进行上述相同的操作。而stefan的算法则分为了两个部分,首先从前向后把前面没有被擦中的点取出来存到一个新的stroke中,然后停止,再从后往前寻找后面的点,将没有被擦中的点加入到一个新的stroke中,直到遇到被擦中的点停止。这样的话,可以保证一个stroke可以被一分为二。
经过我的测试,执行并没有什么问题。但是由于我们向stroke中插入点,完全依赖于MouseMove事件,如果我们的鼠标移动速度过快,那么被插入的这些本就离散的点,它们之前的间隔会变得更大。这在Ink模式下不会有什么问题,但是在EraseByPoint模式下,就会因被去掉的点附近没有其他的点,而一次性擦掉很大的一段,这是由于我们在插入点和擦除的时候没有做任何的优化造成的,希望这个问题能得到解决。
大家可以到http://blogs.msdn.com/swick/archive/2008/11/30/erasing-ink-in-silverlight-2.aspx去看stefan的原文,那里提供工程原件的下载,我就不再多此一举把它上传到博客园来浪费空间了。至于上面提到的问题,如果大家有什么优化的方式和算法,希望可以告诉我们,谢谢!
今天的关于WPF/Silverlight为什么要使用Canvas.SetLeft()这样的方法?和wpf和silverlight的分享已经结束,谢谢您的关注,如果想了解更多关于.net – 为什么我需要MVVM用于WPF / Silverlight,有什么理由不能使用MVC吗?、ArcGIS API for Silverlight开发入门(0):为什么要用Silverlight API?、C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(三十九)向Silverlight移植①、My Silverlight系列(10)—— Silverlight中的InkCanvas的相关知识,请在本站进行查询。
本文标签: