silverlight:如何样调用 Silverlight 客户端 APIs

  介绍  Microsoft Silverlight 插件 支持 个扩展编程模型,这包括 托管 和非托管 代码. 非托管 APIs 在 Silverlight 1.0 (formerly WPF/E) Beta release是有效,同样也存在于Silverlight 1.1 Alpha (May 2007) release. 而 托管 APIs 是在 Silverlight 1.1 Alpha (May 2007) release才支持. 你可以使用CLR 托管 APIs ,这个特性也是在新版本VS也就是 Visual Studio Code Name "Orcas."中将要集成, 目前, C# 和 Visual Basic 是可以在1.1中使用.你也可以使用 dynamic language runtime (DLR). 更多有关 DLR, 请查看 如何样使用动态语言来开发 Silverlight .

  详细介绍 Siverlight 托管 API 目前不能提供. 然而, 你可以使用些反射工具来查看 托管 集而来了解有些什么 APIs 是可以. 有关此项详细消息, 请查看 如何样使用Visual Studio Object Browser浏览Silverlight 集.

  在本篇我们将介绍些你在开发基于Silverlight 应用些常用使用托管代码APIs . 在大多数情况下, 对于object model而言,托管 API 般和对语法和出现位置都比较严格,这和 非托管 API是. 因此, 你甚至可以在非托管 代码基础上来进行 托管代码开发. 然而, object model或命名方式致,这种等价还是需要商榷.

  Silverlight 托管 类库 层次  很多托管类依靠Silverlight control 和其UI 特性进行编程,它们都是遵循这些层次关系:

  依赖对象

  UIElement

  FrameworkElement

  如果你曾经有过Windows Presentation Foundation (WPF)开发基础, 那么你就会对这里层次关系感到熟悉. 然而, 却不像WPF中表面样, 当在开发 Silverlight时,你将自己整理总结和体会对每个类所充当在层次关系中角色. 在Silverlight 中你可以这样认为: FrameworkElement 类是基础 "element" 类,它们包含了很多你在XAML中定义或UI中定义元素有用 APIs.

  但是这不代表所有你在 XAML中例示元素都是 FrameworkElement. 这里有许多元素,它们起了给其它些UI元素某些属性赋值作用, 但是这些属性可能会被精心包装过. 我们举个确切例子, Animation 或 Storyboard派生类, 它们都不是 FrameworkElement 对象. 事实上, animations Storyboard 经常用来控制些UI 元素.

  浏览 Object Tree 并且 找到已经命名Objects  个独立XAML页object tree般都是以个 XAML root element开始. 当前存在 object tree 假设 XAML 页 已经是 Silverlight control源并且已经解析成功了 . (当然也可以直接创建个作为resources XAML 文件, 或者直接将其载入到object tree中,在这种状况下object tree加入到XAML root 里来.)

  对于 托管代码, 当你为XAML root定义了个 x:Class , 这样你就可以轻松得到XAML root引用: 你可以直接在后台敲入 "this" 或 "Me". 然而, 某个objectobject tree中属性并不是都可以引用到,比如它构造. 如果构造,在这种情况下, object tree大部分还没有构造出来; 你必须等到XAML被解析了.

  对于根结点前些object对象,你有 3种思路方法来使用它们, 其中有两点是有密切关系.

  你可以顺着object treeroot直往下, 使用关相 内容模型所提供属性来得到所需要对象引用, 比如 Panel.Children, 或使用泛型集合索引. 这种思路方法可能并不是你最好选择, 这需要你对XAML文件结构非常熟悉. 这通常只是用来进入内容模型,奇怪是, 目前确没有单个 API 是提供这项功能. ,你可能只是使用这种思路方法来进入内容模型或集合个层次而已.

  你可以给XAML element敲入个 x:Name属性 . 然后你就可以使用DependencyObject.FindName这个API来得到该对象引用了.(DependencyObject 是个很基础类, 所以你几乎可以在所有Element中找到这个API.) 如果你使用过 非托管 APIs 来开发过 Microsoft Silverlight 1.0 (formerly WPF/E), 那这个思路方法你可能就会比较熟悉了. FindName 返回个类型 Object, 但FindName 有个不太方便就是你必须指定它返回类型,这样你才能正确有使用它. 这意味你必须了解当前思路方法所返回正确类型.

  CS//using 'this' against the root where this x:Class applies
//in this we know that we are trying to find a TextBlock and can cast
TextBlock tb = this.FindName("myTextBlock") as TextBlock;


  VB'using 'this' against the root where this x:Class applies
'in this we know that we are trying to find a TextBlock and can cast
Dim tb As TextBlock = CType(Me.FindName("myTextBlock"), TextBlock)


  只要你使用Visual Studio Code Name "Orcas" 和其提供 Silverlight 模板,并使用它 build过程, 这你就可以有个更好选择了. 给你Element个x:Name 属性. 这样, 你可以不用定要使用 FindName了, 考虑到 x:Name 其实是和后台相对应类是引用关系. 打个比方, 如果你创建了个element <TextBlock x:Name="myTextBlock"/>, 并且你编程对象是 x:Class,这样,你只需要要简单敲入 myTextBlock 就可以得到引用了, 然后你敲入个点, 相对应属性,思路方法或者事件处理事件就能出来了. 通过IntelliSense你可以浏览对象所提供所有可供内容. 每次生成后台代码过程可以确保这些自动引用正确添加. 这个生成代码文件其实是x:Class个partial类,它们将在使用时候起编译 . 你可以查看Silverlight project编译机制: x:Classpartial 定义, XAML root中 Loaded handler 其实会后台文件 InitializeComponent, 和在obj 目录中生成文件 (它重定义了 InitializeComponent 以此来在每次加载时,能正确提供这种引用关系). 你可以发现当你加入个已经命名element到 XAML文件中来, 你可能需要预编译,这样才能得到相应有着最新对象名 IntelliSense .

  生成后台代码和其引用都是能简单获得,但你应该注意,你并不是时刻都能有效使用它. 比如, 当你想进行 Silverlight control 合并, 你会发现后台文件和XAML文件关系似乎是反着, XAML文件总要比后台文件慢点. 因此, 你可能会觉得在创建自定义Control控件时使用 FindName 要更频繁些.

  从object tree 向 root element方向遍历, 你可以用 API FrameworkElement.Parent. 当到达 root时, FrameworkElement.Parent将返回 null.

  获取或设置些附加属性   附加属性是XAML 语言定义,以此来介绍说明如何样给 elements 各种特殊属性赋值, 甚至这个属性并不存在于当前element成员列表中. 举附加属性个例子,在 Silverlight 客户端有个 API 由 3个 Canvas 属性组成, 他们可以定位Canvas子elements呈现外观. 他们是 Canvas.Left, Canvas.Top, 和 Canvas.ZIndex. 当你想在XAML文件中进行这些属性设置时候, 你必须以 Canvas owner类型来限定并以Owner.Property 形式来, 注意,你不要直接在 Canvas中来设置该属性. 相反, 你应该在 Canvas直接子对象中来设置, 父对象 Canvas 会读入这些属性信息,来控制子对象呈现效果.

  附加属性特殊性,在托管代码中,你不能使用 Object.Property 形式来给其赋值, 这总有两个对象在使用 (个是 XAML 中对象本身, 还有个是在属性被设置时候对象例子).

  在 托管 代码中,你可以通过DependencyObject.GetValue来得到 附加属性值 .第个参数是指属性从属者, 它是后台类中个成员.你可以通过 DependencyObject.SetValue来设置属性值. 第个参数同样是指属性从属者, 第 2个是要设置值. 在每个举例中,都是使用例子思路方法, 它们都依靠例子所提供可以设置附加属性.

  CS//myTextBlock is a TextBlock from XAML, which is child of a Canvas
double currentLeft = (double) myTextBlock.GetValue(Canvas.LeftProperty);
(currentLeft > 400.0) { myTextBlock.SetValue(Canvas.LeftProperty, 400); }


  VB'myTextBlock is a TextBlock from XAML, which is child of a Canvas
Dim currentLeft As Double = CType(myTextBlock.GetValue(Canvas.LeftProperty), Double)
If (currentLeft > 400.0) Then
  myTextBlock.SetValue(Canvas.LeftProperty, 400)
End If


  GetValue 和 SetValue 其实有很广用处.对于 Silverlight client,只要对象提供了相应属性,你就可以通过这两个思路方法来取得或者设置它们值.例如, 你可以 myTextBlock.SetValue(TextBlock.TextProperty "hello"). 但是在这些举例中,并没有 "regular" (非附加) 属性, 然而 Instance.Property 形式对于设置或获取属性取来说还是要更直观些.

  高和宽  Height 和 Width 存在于 FrameworkElement. 你可以设置 Height 和 Width 在 Canvas, TextBlock 和各种 Shape 基础类上.

  有小部分elements (比如 TextBlock) 还存在个 ActualWidth 和 ActualHeight 属性. 它们是在实际情况下被计算出来,只读属性. ActualWidth 和 ActualHeight将受到多种原因影响而改变,这将帮助你得到实际上显示出来尺寸. 比如, 当你 TextBlock里包含些文字, 文字大小受 FontSize, FontFamily, FontSpacing, 等影响, 当然,TextBlock 实际展示大小也会受这些原因影响了.

  注意   Height 和 Width 对于自定义Control控件,目前还需要有个工作区来配合使用, 这取决于你如何使用基础属性. 想查看详细介绍说明, 点击 如何样创建个自定义 Silverlight Controls.

  TextBlock 和 Text APIs  TextBlock 类 包括 系列APIs. 在此我们只是简单介绍下text 对象 , 它们是些常见和TEXT相关属性,可以用来设置TEXT外观等:

  FontFamily: 以对象来对Text font family进行设置. Silverlight 默认只支持几种字体(请查看非托管 文档 TextBlock 来了解更详细内容).你可以 TextBlock.SetFontSource思路方法来取得更多字体.

  FontSize: 以pixels为单位来设置.

  FontStretch: 使用 FontStretches 枚举. 你可以在object browser中查看枚举值, 或是从 Silverlight 1.0 beta documentation来了解更多细节.

  FontStyle: 设置成 FontStyles 枚举, Normal, 或 Italic.

  FontWeight: 设置成 FontWeights 枚举. 你可以在object browser中查看枚举值, 或者查看非托管 Silverlight 文档来了解更多细节.

  Foreground: , 这将由XAML设置成 solid color , 但也可以设置成任何从 Brush类派生类 (例如, ImageBrush 或 GradientBrush) 这样可以为其添加更多特效.

  TextDecorations: 设置成 TextDecorations 枚举, None, 或者 Underline.

  TextWrapping: 设置成 TextWrapping 枚举, NoWrap, 或者 Wrap.

  Text

  CSTextBlock tb = TextBlock;
tb.FontFamily = "Arial"; //one of the initial fonts
tb.FontSize = 20;
tb.FontStretch = FontStretches.SemiExpanded;
tb.FontStyle = FontStyles.Italic;
tb.FontWeight = FontWeights.DemiBold;
SolidColorBrush golden = SolidColorBrush;
golden.Color = Color.FromRgb(211, 147, 12);
tb.Foreground = golden;
tb.TextDecorations = TextDecorations.Underline;
tb.TextWrapping = TextWrapping.Wrap;
tb.Text = "I am nondefault!";
Run il = Run;
il.FontSize = 40;
il.Text = "Hello!";
tb.Inlines.Insert(0,il);


  VBDim tb As TextBlock = New TextBlock
tb.FontFamily = "Arial" 'one of the initial fonts
tb.FontSize = 20
tb.FontStretch = FontStretches.SemiExpanded
tb.FontStyle = FontStyles.Italic
tb.FontWeight = FontWeights.DemiBold
Dim golden As SolidColorBrush = New SolidColorBrush
golden.Color = Color.FromRgb(211, 147, 12)
tb.Foreground = golden
tb.TextDecorations = TextDecorations.Underline
tb.TextWrapping = TextWrapping.Wrap
tb.Text = "I am nondefault!"
Dim il As Run = New Run
il.FontSize = 40
il.Text = "Hello!"
tb.Inlines.Insert(0, il)


  Colors 和 Brushes  当你在XAML中设置颜色值时,你可以设置基于UNIX X11已经命名几乎256种solid colors颜色参数 , 包括有趣 "MistyRose" 和 "PapayaWhip". 或者, 你可以使用个#,再加串量来设置 RGB 或者 ARGB . 在 Silverlight 托管 API中, 预定义可用颜色是很少,只有16种颜色. 因此, 主要定义 solid color 思路方法是 静态 Color.FromArgb, Color.FromScRgb, 或者 Color.FromRgb 思路方法. 然而, 各种从 Brush 中派生(比如SolidColorBrush) 只有默认构造. 他们并没有提供方便人们使用构造. 在你构造后,还必须为其它些相关属性进行赋值. 象这些类 RadialGradientBrush 你必须设置每个 GradientStop 并将其添加到 GradientCollection.

  CSRectangle r = Rectangle;
r.Width = 400;
r.Height = 300;
SolidColorBrush golden = SolidColorBrush;
golden.Color = Color.FromRgb(211,147,12);
r.Fill = golden;


  VBDim r As Rectangle = New Rectangle
r.Width = 400
r.Height = 300
Dim golden As SolidColorBrush = New SolidColorBrush
golden.Color = Color.FromRgb(211, 147, 12)
r.Fill = golden


  这儿包含些常规代码, 比如创建个 brushes 和创建些用于重用brush机制. 下面创建brush代码会有些复杂,但你可以发现这将是有用:

  定义个brush,并使其保存个XAML文件, 或者存成个在XAML中(包含根中xmlns 声明).

  把刚才那个文件或者作为你应用个嵌入资源.

  以stream方式来访问当前资源, 使用这个stream作为资源,并 XamlReader.Load API (更多有关些 API 信息将在以后部分介绍).

  把得到结果应用到 适当 Brush 类, 并以此来设置相应 属性.

  对于此种思路方法,你可以使用些设计工具,比如Microsoft Expression Blend来生成XAML, 使用这些工具你将可以大大减少你工作量,你不用在对ARGB值进行麻烦设置,也不用从别地方复制s. Silverlight 托管 API没有包含资源系统, 该系统目前应用在基于 ResourceDictionary-based WPF中,但嵌入资源是目前我们可用.

  鼠标 和 鼠标位置  浏览客户端 APIs 可以用来得到 鼠标 位置,这几乎可以在所有支持浏览器中使用了, 但对于 基于Silverlight 应用这并不够完美.取代以往个service来不断监视鼠标动作(这用在 WPF中)思路方法,现在我们只在触发某些事件事才返回鼠标座标位置. 然而, 这有个特殊事件 MouseMove, 这个事件将不断监视鼠标动作. 极端情况,如果鼠标从不移动, 你也可以得到鼠标位置,这可以使用主 Canvas上 MouseEnter 事件, 这只要 Canvas 被载入就将触发 (只要鼠标位置在该区域内). 你可以通过鼠标事件实体中 MouseEventArgs.GetPosition思路方法来得到鼠标位置, 和以往得到直接 X 和 Y 位置参数区别. 这个思路方法需要UIElement参数; 你提供给此思路方法element参数将用来计算成位置数值. 如果你不设置值,将其为 null, 那么当前座标系统将和 Silverlight Control控件内容区域有关. , 个典型用作传入到GetPosition参数element是这个事件 sender (你需要给sender转化类型来使其成为个UIElement).你可以填入任何element, 包括和这次点击事件无关些Control控件, 这可能会导致你从GetPosition得到 X 和 Y 值为负值.

  CSvoid el_MouseClick(object sender, MouseEventArgs e) {
  //sender is a 200px ellipse, the closer you click to its relative center, the more it disappears
  Ellipse el = sender as Ellipse;
  double x = e.GetPosition(el).X;
  el.Opacity = Math.Abs(x - 100)/100;
}


  VBSub el_MouseClick(ByVal sender As Object, ByVal e As MouseEventArgs) Handles HotMouse.MouseLeftButtonUp
  'sender is a 200px ellipse, the closer you click to its relative center, the more it disappears
  Dim el As Ellipse = CType(sender, Ellipse)
  Dim x As Double = e.GetPosition(el).X
  el.Opacity = Math.Abs(x - 100) / 100
End Sub


  最常见需要得到鼠标 位置场景分别是 :当 鼠标 点击时, 或当鼠标越过某个边界线时候.这两个应用已经加入到到 drag-and-drop 应用中了.

  XamlReader  在JavaScript中, 不存在构造说, 所以你不能向树中添加你创建某个element例子对象. 但你可以使用像 DHTML些思路方法, 向已经构造完 parallel trees和使用 hide-show 思路方法, 你可使用animations (但只能更改属性值, 而不能添加新到tree中), 或者你需要 Control.content.createFromXAML 来有效并和转换配合来创建个构造引擎. 为此,你会发现你会经常在Silverlight 1.0中 createFromXAML 来创建你特殊动态UI.

  在 托管 代码中, 你需要访问构造. 因此, 在很多情况下, XamlReader.Load (它和非托管代码中 createFromXaml 是) 却并不是很多, 你现在已经处于个 编程模型的中了,你构造已经是很容易事情了. 构造, 你可以将各种属性设置并添加到Control控件中,并能动态添加到当前存在object tree中, 如果你动态界面改变比较简单,那么这种模式是个不错选择.

  对于另种情况, 如果界面改变比较复杂, 而且你承担了美工和代码两方面工作,美工方面希望对于两个区别状态有着两个区别外观,你可能会想到从XAML中动态载入内容来刷新 UI. 然而, 在这种情况下, 你不应该直接从里来载入内容到 XAML, 就像 XamlReader.Load 介绍说明提示样. 相反, 你应该从个文件或个保存好源中来载入, 你可以使用 .IO.StreamReader, 这样,对于设计和编码人员来说,他们的间联系就可以建立在个文件上,这比明显要好多了吧.

  CSAssembly assembly = this.GetType.Assembly;
//BigBrush.xaml is a LinearGradientBrush with half a dozen stops
//and perhaps it gets used frequently, from dferent files
Stream s = assembly.GetManestResourceStream("CallClientAPIs.BigBrush.xaml");
StreamReader sr = StreamReader(s);
Brush b = (Brush)XamlReader.Load(sr.ReadToEnd);
sr.Close;


  VBDim assembly As Assembly = Me.GetType.Assembly
'BigBrush.xaml is a LinearGradientBrush with half a dozen stops
'and perhaps it gets used frequently, from dferent files
Dim s As Stream = assembly.GetManestResourceStream("CallClientAPIsVB.BigBrush.xaml")
Dim sr As StreamReader = New StreamReader(s)
Dim b As Brush = CType(XamlReader.Load(sr.ReadToEnd), Brush)
sr.Close


  无论是JavaScript createFromXAML 和托管 XamlReader.Load 思路方法,你还需要考虑这些区别思路方法对于区别UI设计工具产生出来markup语言兼容性.

Tags:  silverlight2 silverlight.2.0 silverlight是什么 silverlight

延伸阅读

最新评论

发表评论