详细介绍 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
CS
TextBlock 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);
VB
Dim 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.
CS
Rectangle r = Rectangle;
r.Width = 400;
r.Height = 300;
SolidColorBrush golden = SolidColorBrush;
golden.Color = Color.FromRgb(211,147,12);
r.Fill = golden;
VB
Dim 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 值为负值.
CS
void 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;
}
VB
Sub 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, 这样,对于设计和编码人员来说,他们的间联系就可以建立在个文件上,这比个明显要好多了吧.
CS
Assembly 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;
VB
Dim 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语言兼容性.
最新评论