Silverlight 2 Beta 1版本缺陷列表
自Silverlight(以下称SL)1.0 Alpha发布一来,一直对该技术备加关注,加上项目组正好有用到该技术,所以对SL也有了一定程度的了解。SL是一种强大的RIA技术,但同时由于其产品的不成熟,存在很多困扰开发者的问题。不论是对中文的支持,还是对媒体播放的支持,还是对WebService的支持,SL都没能提供很好的解决方案。(当然SL2 Beta 1对中文支持已经很好了)。其实本人一直看好SL,但所谓爱之越深,恨之越切,在此就仅对SL 2Beta 1的不足之处作个说明。当然,如果有不对之处,还请博友们指正。
Silverlight 2 Beta 1版本缺陷列表
1、WebService不支持同步调用
在SL工程中添加Service Reference后,自动生成代理类ServiceSoapClient,实例化ServiceSoapClient后,我们只能看到异步调用的方法。比如,我的WebService提供了一个GetVideoTypes方法,在ServiceSoapClient中却只有GetVideoTypesAsync与GetVideoTypesCompleted,前者是异步方法,后者是相应的事件。上网找了资料,发现在有的外国论坛上,有人也提出了这个问题。
2、WebRequest不支持同步调用
与WebService一样,WebRequest也不支持同步,具体不再详述。在此说一下,WebRequest在System.Net.dll中,大家在开发时要自动引用一下。
3、System.Runtime.Serialization.Json.DataContractJsonSerializer方法不友好
在SL2 Beta 1中用JSON,我只想说,这是一个比较奢侈的要求,目前MS封闭的System.Runtime.Serialization.Json.DataContractJsonSerializer类接口函数很不友好,只支持ReadObject与WriteObject,没有我期待的Serialize与Deserialize。呵呵,你看看ReadObject接受的参数是什么,Stream!!哈哈,你还要构造一个Stream,而如果在分布式系统中,这个Stream就要从WebRequest与WebResponse得到了,嘿嘿,这两类还不支持同步调用。麻烦啊。不过我记得早期版本是有Serialize与Deserialize的,不知道是给去掉了,还是我没找到。
BTW,System.Runtime.Serialization.Json.DataContractJsonSerializer在System.ServiceModel.Web.dll中,很不好找啊。
4、对相对路径支持很不好
我有一个视频播放的页面,要动态加载一些图片,一开始这可把我难住了。因为SL是客户端执行的,而这些图片是在服务器上。我在Xaml中直接写相对路径如"images/1.png",不好使。为什么呢,我觉得也是可以理解嘛,毕竟SL在客户端执行,客户端哪有这个文件,但你SL的Runtime是不是应该动态的去服务器把这图片download下来啊。我记得老版本是可以的啊。没办法,我一开始只能写完整的uri,如http://localhost/vodsl/images/1.png。
不过还有一个奇怪的现象,在同一个SL页面中,有的图片显示不出来(如果用相对路径的话),但有的图片又可以显示。My God,想来想去,答案是:SL还是做了动态下载,只不过这个下载可能在SL渲染后完成,就是说有的图片下载不赶趟了。
5、重绘SilderBar控件会让你抓狂
SL 2 Beta 1引入了TextBox Button ScrollBar等控件,值得夸奖,毕竟在1.1时,自己封装TextBox 还麻烦了(绝对地狱似的编程)。
而这些控件在美观上是远远不能满足人们日益增长的审美要求的。于是乎,我想重绘它们。感谢SL为我们提供了重绘控件的机制。具体方法是为控件(如:Button ScrollBar)指定Style,这个Style其实就是一个Resource,你可以直接在Xaml中写。但要写在相应控件的前面,否则在运行时,SL会认为控件的Style是一个无效对象。
但定义这一个Style可不简单耶!!看看SDK中的例子,那是相当长的一段代码。而且你很难知道控件的各个元素叫什么名(我是通过SDK/Google才知道的)。很不人性啊。其实我就是想改一个小滑块的样式,(ScrollBar中的小滑块),就要写一大堆Xaml。大家可以试试,我是花了很长时间才明白这大堆Xaml的具体含义。
好了,终于可以自定义ScrollBar的样式了,但发现ScrollBar总有一个背景图去不掉,就是下面这个图片:
无论我怎么修改Style,这个底图总存在。没办法,我最近只好放弃重绘ScrollBar。
6、说说Grid与DataGrid
Grid是SL的一个相对定位容器,在Grid中的控件是不能绝对定位的,如果你也与我一样试图在Blend中拖动Grid中的控件,一定感触颇深。我觉得这是很合理的,Grid就像Html中的Table,可用作页面整体的布局,事实上SL的很多控件(比如ScrollBar)内部也是用Grid布局的。但Grid没有提供Rows.Add与Columns.Add等接口,在想动态放置子控件时比较不方便。但Grid引入了RowDefinition与ColumnDefinition的概念,这个我个人比较喜欢。它实现了Grid布局定义与子控件放置的分离,你先定义Grid有几行几列,然后在后面加子控件,再为这些子控件指定Grid.Row与Grid.Column,这样就避免了HTML Table中的层层嵌套。这样的缺陷就是不代码不直观。
BTW,Grid的单元格似乎不能自动随子控件撑大,我只看到了Maxheight与MinHeight属性,但似乎不能实现这个功能。
DataGrid居然没有Rows.Add接口,但有Columns.Add接口。
7、有些属性要通过SetValue与GetValue方法
.Net 3.0与SL引入了DependencyProperty机制,很好很强大,我们可以在一个类中定义属性,然后别的对象也能用这个属性,没有明白?比如说在Canvas中定义了Left,我们可以在任何控件对象中SetValue(Canvas.Left,v)。凡是可以嵌在Canvas中的控件都可以通过这种方式来设置Left;而Grid也有LeftProperty,同样,凡是可以嵌在Grid中的控件都可以SetValue(Grid.Left,v)。仔细想想,不难发现,在任何一个控件对象中SetValue(Grid.Left,v),最终都会调用Grid类中的一段逻辑。你要是自己定义一个容器控件,比如MyPanel,你在这个类中加一个LeftProperty,然后实现一个设置子控件Left的逻辑,那么所有子控件都可以SetValue(MyPanel.Left,v)了。(关于DependencyProperty以后再说)
用DependencyProperty定义控件属性的缺点就是不方便,如果是GetValue还要将返回值强制转换。即使是Left,Right这样的常用属性,也要通过SetValue与GetValue方式,很是麻烦。相信下一版本的SL会封闭友好的属性接口。当然这仅仅是为了一个方便而已。
如果大家发现有地方说的不对,还请指正。