Silverlight 5 有什么新特性?






4.68/5 (32投票s)
在本文中,我们将全面讨论 Silverlight 5 Beta 版的新功能。
- 下载 New_in_Silverlight_5.zip - 204.37 KB
- 在此处观看 Silverlight 5 完整免费课程。
- 本文基于 Beta 版本,最终版本可能会有所更改。
介绍
关于 Silverlight 5,首先要知道的是它目前处于测试阶段,这意味着它肯定有 bug,并且功能还不完整;一些功能将在最终版本中发布。此外,处于测试阶段意味着没有可用的上线许可,这仅供内部使用和测试,因此请勿在用户机器上安装。
值得一提的是,Silverlight 5 于 PDC 2010 大会(2010年10月)首次公布,Beta 版本随后在 MIX11(2011年4月)发布,最终版本将于今年稍后发布。
目标
版本 5 的目标包括- 提高性能
- 更接近 WPF
- 支持业务场景
- 更好的开发体验
改进
Silverlight 5 带来了许多改进和变化,这些改进可以分为几个方面- XAML 变化
- 控件和文本改进
- 图形变化
- 媒体变化
- 高信任度变化
- 性能及其他改进
入门
要开始使用,您首先需要在电脑上安装 Microsoft Visual Studio 2010 Service Pack 1。之后,您可以访问 http://silverlight.net 并下载 适用于 VS2010 的 Beta SDK 和工具。
此外,如果您喜欢使用它,还可以安装 Microsoft Expression Blend Preview for Silverlight 5 Beta。
在您的电脑上安装了 VS2010 SP1 和 Silverlight 5 SDK 后,您可以继续阅读并开始制作您的酷炫作品!
现在让我们从 XAML 更改开始,但首先让我们看看将在所有示例中使用的模型。
XAML 变化
Silverlight 5 在 XAML 堆栈中有以下变化- 隐式数据模板
- 祖先 RelativeSource
- 样式中的绑定
- 标记扩展
- XAML 调试
模型
本节中的演示基于一个非常简单的模型,它仅包含纸质书和有声书的集合。我们有以下业务模型public class Book
{
public string Title { get; set; }
public string Author { get; set; }
public decimal Price { get; set; }
}
public class PaperBook : Book
{
public string Isbn { get; set; }
public int Pages { get; set; }
}
public class AudioBook : Book
{
public TimeSpan Duration { get; set; }
}
这是我们的收藏public class BookData : List
{
public List PaperBooks
{
get
{
return (from b in this where b is PaperBook
select (PaperBook)b).ToList();
}
}
public List AudioBooks
{
get
{
return (from b in this where b is AudioBook
select (AudioBook)b).ToList();
}
}
public BookData()
{
this.Add(new PaperBook()
{
Title = "The Sixth Man",
Author = "David Baldacci",
Isbn = "9780446573108",
Pages = 432,
Price = 14.28m,
});
...
this.Add(new AudioBook()
{
Title = "Water for Elephants",
Author = "Sara Gruen",
Duration = new TimeSpan(11, 29, 00),
Price = 21.56m,
});
}
}
隐式数据模板
Silverlight 5 拥有 WPF 数据模板的一大强大功能,即隐式数据模板。您无需将数据模板显式附加到每个控件,而是可以设置数据类型(通过 DataType 属性),数据模板将应用于该类型,然后该数据模板将自动应用于任何尝试显示该数据类型的控件。
请记住,隐式数据模板仅适用于符合以下条件的控件:
- 尝试显示指定数据类型
- 具有可模板化内容(例如集合控件)
- 在模板范围内定义
因此,隐式数据模板不会应用于任何不符合这些要求的其他控件
实现
让我们看看隐式数据模板的实际应用。在以下场景中,我们有一个列表框,它使用数据模板显示一些书籍,并通过代码填充
<ListBox x:Name="books">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Title}" FontWeight="Bold" />
<TextBlock Text="{Binding Author}" />
<TextBlock Text="{Binding Price, StringFormat='C'}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
我们可以通过使数据模板隐式来重构此代码,这可以通过将数据模板从列表框移动到应用程序资源(例如)并指定数据类型来完成,然后数据模板将自动应用于尝试显示指定数据类型的每个可模板化内容控件<Application.Resources>
<DataTemplate DataType="loc:Book">
<StackPanel>
<TextBlock Text="{Binding Title}" FontWeight="Bold" />
<TextBlock Text="{Binding Author}" />
<TextBlock Text="{Binding Price, StringFormat='C'}" />
</StackPanel>
</DataTemplate>
</Application.Resources>
<ListBox x:Name="books" />
清晰简洁,对吗?
现在让我们做一些更有趣的事情,看看隐式数据模板的真正威力。除了一个简单的数据模板,我们将为两种类型的书籍提供两个模板,一个用于纸质书,另一个用于有声书。
<DataTemplate DataType="loc:PaperBook">
<StackPanel>
<TextBlock Text="{Binding Title}" FontWeight="Bold" />
<TextBlock Text="{Binding Author}" />
<TextBlock Text="{Binding Price, StringFormat='C'}" />
<TextBlock Text="{Binding Isbn}" />
<TextBlock Text="{Binding Pages}" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="loc:AudioBook">
<StackPanel>
<TextBlock Text="{Binding Title}" FontWeight="Bold" />
<TextBlock Text="{Binding Author}" />
<TextBlock Text="{Binding Price, StringFormat='C'}" />
<TextBlock Text="{Binding Duration}" />
</StackPanel>
</DataTemplate>
如您所见,每个数据模板将应用于一个尝试显示其指定数据类型的可模板化内容控件。此外,这两个数据模板都将应用于一个尝试显示 PaperBook 和 AudioBook 集合的集合控件。祖先 RelativeSource
这是 Silverlight 5 从 WPF 获得的 XAML 的另一个功能。它允许您绑定到父控件中的属性。这在您处于数据模板中并希望绑定到渲染树中更高位置的模板外部控件中的属性时特别有用。
实现
您使用 {Binding.RelativeSource} 来指定树中的源。
- 使用 AncestorType 属性来指定您希望绑定的父控件的类型。
- 使用 AncestorLevel 来指定指定类型的父控件与当前控件的距离。
<StackPanel Tag="Hello, World">
<TextBlock Text="{Binding Tag,
RelativeSource={RelativeSource AncestorType=StackPanel}}" />
<TextBlock Text="{Binding Tag,
RelativeSource={RelativeSource AncestorType=StackPanel, AncestorLevel=1}}" />
<StackPanel>
<TextBlock Text="{Binding Tag,
RelativeSource={RelativeSource AncestorType=StackPanel, AncestorLevel=2}}" />
<Grid>
<TextBlock Text="{Binding Tag,
RelativeSource={RelativeSource AncestorType=StackPanel, AncestorLevel=2}}" />
</Grid>
</StackPanel>
</StackPanel>
这是一个更复杂的例子。在下面的例子中,我们根据项目是否被选中来改变项目模板内部控件的颜色。为了实现这一点,我们绑定到 ListBoxItem 控件(表示列表框中的一个项目)的 IsSelected 属性,并使用类型转换器根据布尔值返回颜色<ListBox x:Name="books">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Title}" FontWeight="Bold"
Foreground="{Binding IsSelected, Converter={StaticResource conv},
RelativeSource={RelativeSource AncestorType=ListBoxItem}}" />
<TextBlock Text="{Binding Author}" />
<TextBlock Text="{Binding Price, StringFormat='C'}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
样式绑定
这是 Silverlight 5 从 WPF 获得的 XAML 的另一个功能。它允许您直接在样式设置器中进行绑定,这将允许通过更改源对象在运行时自动更改样式。
实现
在以下场景中,我们有一个包含应用程序中使用的画刷的类
public class MyBrushes
{
public SolidColorBrush MainBrush { get; set; }
public MyBrushes()
{
MainBrush = new SolidColorBrush(Colors.Red);
}
}
我们有一个绑定到该类并从中获取主画刷的样式(如您所见,所有绑定功能现在都可在样式设置器中使用)<loc:MyBrushes x:Key="brushes" />
<Style TargetType="TextBlock">
<Style.Setters>
<Setter Property="FontSize" Value="20" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground"
Value="{Binding MainBrush, Source={StaticResource brushes}}" />
</Style.Setters>
</Style>
最后,我们可以通过更改源画刷在运行时自动更改样式,代码如下 MyBrushes brshes = Application.Current.Resources["brushes"] as MyBrushes;
brshes.MainBrush.Color = Colors.Red;
标记扩展
标记扩展允许您在 XAML 解析时执行代码,它们类似于 {Binding}、{StaticResource}、{RelativeSource} 等。Silverlight 5 中 XAML 的新功能是能够创建自定义标记扩展。它们提供更简洁的语法,并且比附加属性更容易、更简单。
实现
一个非常简单的标记扩展示例是,该扩展将两个数字相加并将结果返回给控件(以下 TextBlock 在运行时将显示文本“3”)
<TextBlock Text="{my:SumExtension FirstNumber=1, SecondNumber=2}" />
那么如何创建这样的扩展呢?您可以通过实现泛型 IMarkupExtenstion 接口(在 System.Xaml 命名空间中)来创建标记扩展,该接口接受一个类型参数,指定扩展的返回类型(必须是引用类型)。之后,您将扩展参数作为属性提供,并实现 ProvideValue() 来完成工作并将结果返回给 XAML。
以下代码定义了我们的求和扩展
public class SumExtension : IMarkupExtension<object>
{
public int FirstNumber { get; set; }
public int SecondNumber { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
return (FirstNumber + SecondNumber).ToString();
}
}
这是一个更复杂的例子。在书籍场景中,我们定义了一个标记扩展,它根据书籍类型(纸质/有声)返回书籍集合。public class BookLocatorExtension : IMarkupExtension<object>
{
public BookType Type { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Type == BookType.Paper)
return BookData.PaperBooks;
else
return BookData.AudioBooks;
}
}
public enum BookType { Paper, Audio }
这是我们如何使用扩展的示例<ListBox ItemsSource="{loc:BookLocator Type=Paper}" />
<ComboBox ItemsSource="{loc:BookLocator Type=Audio}" />
XAML 调试
Silverlight 5 中引入的最后一个 XAML 新功能是调试数据绑定的能力。在观察绑定错误时非常有用,它通过在 XAML 的绑定内部设置断点并观察“局部变量”窗口和其他 Visual Studio 窗口以获取绑定详细信息来工作。
请记住,XAML 调试仅适用于 Internet Explorer 9(同时在 Internet 选项中启用调试)。
实现:
在我们的书籍场景中,我们有以下数据表单
<UserControl.Resources>
<loc:BookData x:Key="data" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox x:Name="booksList"
DataContext="{StaticResource data}"
ItemsSource="{Binding}" />
<StackPanel Grid.Column="1"
DataContext="{Binding SelectedItem, ElementName=booksList}">
<TextBlock>Title</TextBlock>
<TextBox Text="{Binding Title, Mode=TwoWay}" />
<TextBlock>Author</TextBlock>
<TextBox Text="{Binding Author, Mode=TwoWay}" />
<TextBlock>Price</TextBlock>
<TextBox Text="{Binding Price, StringFormat='C', Mode=TwoWay}" />
</StackPanel>
</Grid>
现在,在列表框的绑定内部设置一个断点,然后运行应用程序,看看会发生什么。
当您运行应用程序时,Visual Studio 在列表框加载数据时停在断点处。查看“局部变量”窗口,我们可以看到绑定详细信息:
这里我们有封装在 BindingState 中的详细信息,当前状态是 UpdatingTarget,这意味着它是一个 Pull 操作,列表框正在加载数据。
我们可以看到列表中有 5 个项目,由 FinalSource 引用。此外,我们还没有任何错误或验证错误。
现在停止应用程序,让我们尝试其他操作。尝试将断点插入“价格”文本框,然后运行应用程序。
如您所见,Visual Studio 会在“推送”和“拉取”操作时停止。当文本框加载数据时发生“拉取”操作,当文本框中的值更改并更新到源时发生“推送”操作。
现在尝试在价格文本框中输入一些无效数据(例如一些字母),然后查看局部变量窗口
现在您可以发现绑定中可能发生的任何错误。
最后要提到的是,条件和过滤器可以在断点中使用。例如,您可以使用以下条件告诉 Visual Studio 仅在绑定错误时停止,而不是在每个操作时都停止
((System.Windows.Data.Debugging.BindingDebugState)BindingState).Error != null
控件和文本更改
Silverlight 5 在控件和文本方面进行了一些改进;为控件新增了功能,并增强了文本的渲染和性能。以下是 Silverlight 5 中控件的新功能- 文本跟踪和行距控制
- 文本溢出
- 多点点击支持
- 预输入文本搜索
- SaveFileDialog DefaultFilename
- DataContextChanged 事件(Beta 版中没有)
- 渲染效果现在更好
- 文本布局的性能已得到改善
- 通过像素对齐提高了文本清晰度
- OpenType 支持已增强
文本跟踪和行距控制
Silverlight 5 为文本控件(TextBlock、TextBox 和 RichTextBox)添加了三项功能,让您可以精确控制字符和行的文本跟踪和行距- 字符间距
- 行高
- 行堆叠策略
字符间距
此功能允许您精确设置每个字符之间的距离。此功能在所有文本控件中通过一个名为 CharacterSpacing 的属性提供,该属性指定字符之间的距离。此距离以当前字体大小的 千分之一 为单位测量,这意味着例如,如果您将字体大小设置为 20px,字符间距设置为 500,则每个字符之间的距离将为 10px(因为 20 * 500 / 1000 = 10px)。
以下是一个 TextBlock 的示例,它使用字符间距功能在每个字符之间放置 10px 的距离
<TextBlock FontSize="20" CharacterSpacing="500">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</TextBlock>
行高
此功能允许您精确设置文本控件中内容每行的高度。它通过名为 LineHeight 的属性在所有文本控件中可用,并且与 CharacterSpacing 不同,它以像素为单位测量。
以下代码将文本中每行的高度设置为 50px
<TextBlock Margin="5" LineHeight="50">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<LineBreak />
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<LineBreak />
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</TextBlock>
行堆叠策略
此功能允许您指定如何确定每个行框。例如,如果您处于以下场景中,其中某些文本比其他文本大,您会怎么做?您会增加每行的高度以适应较大文本的大小并使其可读吗?或者您会像没有不同字号文本一样保留文本?这就是堆叠策略的全部意义所在。<TextBlock Margin="25" FontSize="12">
Lorem ipsum <Span FontSize="20">dolor sit amet</Span>, ...
<LineBreak />
Proin aliquam augue quis ipsum <Span FontSize="38">rhoncus</Span> ...
<LineBreak />
Quisque eleifend ante vitae velit vehicula luctus. ...
</TextBlock>
堆叠策略通过一个名为 LineStackingStrategy 的新属性在您的代码中可用。此属性接受以下三个值之一
- MaxHeight (默认)
增加每行框的大小以容纳其内容。如果设置了 LineHeight,则将 LineHeight 的值添加到行框高度的确定值。 - BlockLineHeight:
如果指定,则使用 LineHeight 中的值。否则,增加每行框的大小以容纳其各种字体大小的内容。 - BaselineToBaseline:
如果指定,则使用 LineHeight 中的值。否则,使用默认行高,不考虑内容是否包含较大文本。
下图比较了设置 LineHeight 和不设置 LineHeight 时三种堆叠策略的区别。
明白了吗?
文本溢出
此功能允许多列和自由格式文本布局。它仅适用于 RichTextBoxes。您可以将 RichTextBox 设置为主元素,并将其链接到新的 RichTextBoxOverflow 以捕获主 RichTextBox 中无法容纳的额外文本。您还可以继续链接,将另一个 RichTextBoxOverflow 链接到上一个,以捕获其中无法容纳的额外文本,依此类推。要将溢出控件链接到另一个控件,您可以使用上一个控件中可用的新 OverflowContentTarget 属性来绑定到下一个溢出控件。
下图展示了如何使用溢出控件创建多列文本
以下显示了一个自由格式文本的示例,其中文本围绕中心的对象换行
以下示例创建多列文本
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<RichTextBox OverflowContentTarget="{Binding ElementName=firstOverflow}" />
<RichTextBoxOverflow x:Name="firstOverflow" Grid.Column="1"
OverflowContentTarget="{Binding ElementName=secondOverflow}"/>
<RichTextBoxOverflow x:Name="secondOverflow" Grid.Column="2" />
多点点击支持
Silverlight 5 现在允许您在控件中捕获多次点击。它可以捕获任意 n 次点击,但大多数情况下您会捕获双击,有时会捕获三次点击。此功能通过 MouseButtonEventArgs 中名为 ClickCount 的属性提供。虽然 MouseButtonEventArgs 在 ButtonDown 和 ButtonUp 事件中可用,但 ClickCount 仅在 MouseLeftButtonDown 和 MouseRightButtonDown 中有效,它始终从 ButtonUp 事件返回 1。
以下代码显示了如何在 TextBlock 中捕获多次点击,它会根据每次点击更新 TextBlock
private void theTextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 1)
theTextBlock.Text += "Single-click\n";
else if (e.ClickCount == 2)
theTextBlock.Text += "Double-clicks\n";
else if (e.ClickCount == 3)
theTextBlock.Text += "Triple-clicks\n";
else
theTextBlock.Text += e.ClickCount.ToString() + "\n";
}
预输入文本搜索
Silverlight 5 中的预输入文本搜索功能允许您使用键盘在集合控件(例如 ComboBox、ListBox 等)中进行搜索;您可以通过键入其内容的第一个字母来找到所需的项目。
控件搜索的内容必须在 DisplayMemberPath 中指定。例如,在我们的书籍场景中,要搜索书籍标题,您必须将 DisplayMemberPath 设置为 Title 字段。这引出了另一个问题,如果您设置了数据模板,则不能同时设置 DisplayMemberPath。此问题可以通过使用新的 Silverlight 5 XAML 功能(隐式数据模板)来解决,该功能已在上一篇文章中介绍。
在我们的书籍场景中,我们有以下 ComboBox,它应用了隐式数据模板
<ComboBox x:Name="books" />
我们还有以下代码,用于填充 ComboBox 并设置 DisplayMemberPath 以允许使用键盘搜索books.ItemsSource = new BookData().OrderBy(b => b.Title);
books.DisplayMemberPath = "Title";
应用程序现在运行完美。但是,如果您将数据模板转换为显式数据模板,如下所示<ComboBox x:Name="books>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Title}" FontWeight="Bold" />
<TextBlock Text="{Binding Author}" />
<TextBlock Text="{Binding Price, StringFormat='C'}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
您会收到以下错误,因为设置 ItemTemplate 时无法设置 DisplayMemberPath
SaveFileDialog DefaultFilename
现在在 Silverlight 5 中,您可以在 SaveFileDialog 中设置默认文件名(使用新的 DefaultFileName 属性),该文件名将在启动对话框时显示在文件名框中SaveFileDialog dialog = new SaveFileDialog();
dialog.DefaultFileName = "Foo";
dialog.ShowDialog();
DataContextChanged 事件
此功能目前在 Beta 版中不可用;它应该在最终版本中可用。它在控件的 DataContext 对象更改时发生。
图形变化
Silverlight 5 在图形堆栈方面进行了一些更改- 改进的性能和渲染
通过借鉴 Windows Phone 7 的经验,性能得到了显著提升。本文稍后会有更多内容。 - 硬件加速
Silverlight 5 现在更依赖 GPU 进行图形处理。这使得 CPU 从大量工作中解脱出来,从而提高了性能。 - 新的 3D API
迄今为止最令人兴奋的功能。Silverlight 5 现在支持原生 3D API。稍后会有更多内容。 - 矢量打印
对于某些情况非常有用,在 Beta 版中不可用。 - 打印预览
期待已久的打印功能。Silverlight 5 现在允许您向用户显示他将要打印内容的预览。Beta 版中尚不可用。
性能改进
为了提高渲染性能,Silverlight 5 采用了 Windows Phone 7 中提供的合成模型。该模型意味着使用单独的专用线程进行图形渲染,而不是使用 UI 线程。这有助于将 UI 线程从图形工作中解放出来,从而提高 UI 元素的渲染性能,并减少 UI 线程中断时发生的闪烁和卡顿动画。
此外,将图形渲染转移到另一个线程增加了对独立动画的支持,并有助于在 GPU 上进行即时模式渲染(其中图形直接发送并在显示器上渲染)。
3D API
Silverlight 5 现在原生支持 3D API。此 API 基于 XNA API;您拥有相同的类和相同的代码,但是,Silverlight 的 3D API 不是基于游戏循环的。
虽然 Silverlight 原生支持 3D API 令人惊叹,但事情并非看起来那么美好。Silverlight 5 的 3D API 非常底层,这意味着您可以访问 GPU、顶点着色器和其他 3D 基本体。它不像应该的那样容易;它要求您对底层图形和游戏开发有扎实的理解才能与此 API 交互。然而,好消息是社区可能会将这个底层 API 封装成更简单的组件。
从技术上讲,要在屏幕上绘制图形,您需要使用新的控件 DrawingSurface,所有渲染和图形都将在其上进行。此控件提供一个 Draw 事件,您可以将其用于提供绘图调用。这些调用被传递到 GraphicsDevice 对象,然后进行处理并传递到显示器。
由于这种底层 API 的复杂性,并且由于我们假设您是一名业务开发人员,我们不会讨论 3D API。相反,我们将简要介绍此 API 的两个出色示例。
立方体示例
立方体示例(从 http://bit.ly/sl5-cubesample 下载,彩色,无纹理)演示了如何在 Silverlight 5 中创建和旋转 3D 立方体。这是此示例的屏幕截图
查看解决方案资源管理器中的项目文件,我们可以看到项目包含一些像素着色器(PS)和顶点着色器(VS)文件。这些文件以及 HLSL 文件包含用于渲染立方体所需效果的代码(用 HLSL 语言编写)。
转到 MainPage.xaml,您可以看到用于显示图形和绘图的 DrawingSurface 对象。
<DrawingSurface Draw="OnDraw" SizeChanged="OnSizeChanged" />
查看代码后面的 Draw 事件处理程序,我们可以看到示例已将绘制立方体和旋转立方体所需的所有代码封装到一个名为 Scene 的新类中。Draw 事件将 GraphicsDevice 对象传递给 Scene,以便它将立方体和其他图形绘制到设备中。// init the 3D scene
Scene scene = new Scene();
public MainPage()
{
InitializeComponent();
}
void OnDraw(object sender, DrawEventArgs args)
{
// draw 3D scene
scene.Draw(args.GraphicsDevice, args.TotalTime);
// invalidate to get a callback next frame
args.InvalidateSurface();
}
转到 Scene 类,我们可以看到它创建了另一个处理立方体绘制的类,并配置了视图和相机位置,并通过清除屏幕并调用立方体的 Draw() 函数来完成 Draw() 函数中的绘制。public class Scene
{
Matrix view; // The view or camera transform
Matrix projection;
// The single Cube at the root of the scene
Cube Cube = new Cube();
public Scene()
{
// the camera's position
Vector3 cameraPosition = new Vector3(0, 0, 5.0f);
// the place the camera is looking (towards world origin)
Vector3 cameraTarget = Vector3.Zero;
// the transform representing a camera at a position looking at a target
view = Matrix.CreateLookAt(cameraPosition, cameraTarget, Vector3.Up);
}
...
public void Draw(GraphicsDevice graphicsDevice, TimeSpan totalTime)
{
// clear the existing render target
graphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer,
Color.Transparent, 1.0f, 0);
// draw the Cube
Cube.Draw(graphicsDevice, totalTime, view * projection);
}
}
最后,Cube 类通过在其构造函数中加载顶点和像素着色器,在 CreateCube() 函数中配置立方体表面和表面颜色,然后在 Draw() 函数中执行绘图和处理动画来完成所有绘图。public class Cube
{
// the device to use when creating resources
static readonly GraphicsDevice resourceDevice
= GraphicsDeviceManager.Current.GraphicsDevice;
// resources
VertexShader vertexShader;
PixelShader pixelShader;
public Cube()
{
// Initialize resources required to draw the Cube
vertexBuffer = CreateCube();
Stream shaderStream = Application.GetResourceStream(
new Uri(@"CubeSample;component/Cube.vs", UriKind.Relative)).Stream;
vertexShader = VertexShader.FromStream(resourceDevice, shaderStream);
shaderStream = Application.GetResourceStream(...);
,,,
}
VertexBuffer CreateCube()
{
// cube vertices
var cube = new VertexPositionColor[36];
// face coordinates
Vector3 topLeftFront = new Vector3(-1.0f, 1.0f, 1.0f);
Vector3 bottomLeftFront = new Vector3(-1.0f, -1.0f, 1.0f);
...
return vb;
}
public void Draw(GraphicsDevice graphicsDevice, ...)
{
// update cube transform
Matrix position = Matrix.Identity; // origin
Matrix scale = Matrix.CreateScale(1.0f); // no scale modifier
...
// setup pixel pipeline
graphicsDevice.SetPixelShader(pixelShader);
// draw using the configured pipeline
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 12);
}
}
冗长,不是吗?现在,让我们看另一个例子。太阳风
Solar Wind 3D 示例(从 http://bit.ly/sl5-solarwind 下载)利用 Silverlight 5 的新 3D 功能绘制了具有昼夜过渡、大气层和人口密度叠加层的地球。它展示了高级概念,非常酷,您会喜欢运行和玩它。
巴比伦3D
迄今为止最令人惊叹的示例(从 http://bit.ly/sl5-babylon3d 下载),它展示了一个完整的 3D 实时引擎,具有一些高级功能和集成的碰撞系统。
媒体更改
Silverlight 5 在媒体堆栈方面进行了一些更改- 更好的电池管理
播放媒体时电池消耗更少。此外,全屏模式下没有屏幕保护程序。 - 遥控器支持
现在您可以使用遥控器控制 Silverlight 5 中播放的媒体。此功能目前在 Beta 版中不可用。 - 硬件解码;更多 GPU 支持
为了更好的性能,Silverlight 5 更依赖 GPU 进行媒体解码,尤其是高清 H.264 格式。在 Beta 版中,不支持 DRM 或 Mac。 - 1080p 支持
结合硬件解码,用户现在可以在上网本或平板电脑上观看高清 1080p 媒体。 - IIS 媒体服务 4
增加了对使用 IIS Media Services 4 进行媒体流的支持。
- 速度控制;花式播放
允许您控制播放速度,并可以向前或向后播放媒体。 - 低延迟声音
Silverlight 5 新增了对原始波形文件的原生支持。
速度控制;花式播放
此功能允许您控制播放速度,以加速或减慢媒体。更改播放速度的能力称为花式播放(Trick Play)。此功能在 MediaElement 控件中通过一个名为 PlaybackRate 的新属性提供。此属性接受一个十进制值,范围从 -8、-4、-2……到……0.5、1.2、1.4、2、4、8,默认值为 1。Beta 版本的一个缺点是它没有音高校正,这意味着当您将速率更改为非默认值 (1) 时,将没有任何声音。由于 Beta 版本中发现的一个错误,您必须在代码中设置此属性,如果您在 XAML 中设置它,应用程序启动时将重置为默认值。
以下是更改媒体元素播放速度的三个示例
// Normal Speed
media.PlaybackRate = 1.0;
// Fast
media.PlaybackRate = 4.0;
// Slow
media.PlaybackRate = -2.0;
低延迟声音
过去,您必须创建一个波形文件解析器,该解析器读取文件头以确定是否是波形文件,识别波形文件后,解析器读取文件内容并对其进行编码,以便您的应用程序能够播放它。Silverlight 5 完全改变了这一点。现在,您原生支持原始声音数据(即低延迟声音)。您现在可以直接在应用程序中播放波形文件和波形数据,而无需对它们进行编码。
此功能通过基于 XNA 框架的新 API 提供。它使用 XNA 中可用的相同类和函数。您拥有的主要类是 SoundEffect (Microsoft.Xna.Framework.Audio),您可以使用它来播放波形文件和原始数据。您可以完全控制播放的媒体;您可以设置音量、音高和立体声空间。您可以创建一个更复杂的 SoundEffect 类,名为 SoundEffectInstance,它代表该声音文件的一个实例。此实例可以重复播放,并允许您拥有像 SoundEffect 一样以及更多的所有控制,我们将在示例中看到。
最后,请记住 Silverlight 5 具有与 XNA 相同的限制;它只允许 8/16 位 PCM、单声道/立体声、22.5/44.1/48khz 波形文件。
以下代码将 SoundEffect 类与应用程序资源中可用的波形文件加载
var resource = Application.GetResourceStream(
new Uri("MediaLowLatency;component/tada.wav",
UriKind.RelativeOrAbsolute));
SoundEffect effect = SoundEffect.FromStream(resource.Stream);
拥有 SoundEffect 后,您可以调用 Play() 方法来播放它。此方法有两个重载,一个不接受任何参数,在这种情况下,它会以默认音量正常播放媒体,并且音高或立体声空间没有变化。另一个重载接受三个值- 音量:
范围从 0.0f 到 1.0f。 - 音高:
范围从 -1.0f 到 1.0f。默认值为 0f。 - 平移:
控制立体声空间。范围从 -1.0f 到 1.0f。默认值为 0f。
// Normal
effect.Play();
// Normal (default values)
effect.Play(1.0f, 0f, 0f);
// Faster
effect.Play(1.0f, 1.0f, 0f);
// Slower
effect.Play(1.0f, -1.0f, 0f);
最后,您可以使用 SoundEffectInstance 创建同一音频的多个实例,或重复播放(音量、音高和声像值通过属性提供) SoundEffectInstance instance = effect.CreateInstance();
instance.IsLooped = true;
instance.Play();
高信任度变化
Silverlight 5 中的高信任度应用程序发生了一些变化- 浏览器内支持
- 多窗口支持
- 文件系统访问
- 平台调用
浏览器内支持
与以前的版本不同,在 Silverlight 5 中,您无需将应用程序作为 OOB 运行即可获得高信任功能,您现在可以在浏览器中运行高信任应用程序并获得所需的所有功能。
要在浏览器中运行高信任应用程序,需要考虑两个安全问题
- 您必须通过 客户端访问策略文件 或 Windows 注册表 启用在浏览器中运行应用程序。使用策略文件允许您的应用程序在私有网络中运行。使用 Windows 注册表方法允许您的应用程序在单台机器上运行。在任何一种方法中,您都无法将浏览器内高信任应用程序部署到网络上的所有人。
- 此外,您的 XAP 必须使用 受信任的发布者证书 存储中可用的受信任证书(例如 X.509 证书)进行签名。
如果没有这些要求,您将无法在浏览器中运行您的受信任应用程序。但是等等,这里有一个陷阱!
在您的开发机器上,您只能在白名单域中运行浏览器内高信任应用程序。例如,默认情况下,_localhost_ 在白名单中,因此您可以轻松地在 localhost 的浏览器中运行高信任应用程序。如果您切换到另一个域,请确保将此名称添加到白名单,否则您将无法运行应用程序。稍后会有更多关于此的内容。
最后要记住的是,在 Beta 版中,浏览器内高信任应用程序仅在 Windows 中受支持。其他平台将在最终版本中提供。
客户端访问策略方法
如果您希望您的应用程序在私有网络中可用,您需要对客户端访问策略文件进行一些更改,以允许它作为高信任度在浏览器中运行。更改如下;只需将 SecuritySettings 的 ElevatedPermissions 属性设置为 Required:<Deployment.OutOfBrowserSettings>
...
<OutOfBrowserSettings.SecuritySettings>
<SecuritySettings ElevatedPermissions="Required" />
<OutOfBrowserSettings.SecuritySettings>
...
</Deployment.OutOfBrowserSettings>
Windows 注册表方法
您拥有的另一种方法是使用 Windows 注册表来启用浏览器内高信任应用程序在特定计算机上运行。为此,请转到 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Silverlight。在此注册表项中,您有几个与高信任应用程序相关的值- AllowElevatedTrustAppsInBrowser: 设置为 TRUE (0x00000001) 以启用在浏览器中运行高信任应用程序。
- AllowInstallOfElevatedTrustApps: 设置为 TRUE 以启用在高信任应用程序到 PC 的安装(即 OOB)。
- AllowLaunchOfElevatedTrustApps: 设置为 TRUE 以启用启动高信任应用程序(浏览器内或 OOB)。
示例
要在浏览器中运行高信任应用程序,您需要首先从项目属性中启用 OOB 和高信任功能。之后,创建一个 Web 应用程序并将其链接到 Silverlight 应用程序以托管它。如果您不这样做,您的 Silverlight 应用程序将作为 OOB 运行。您的应用程序现在能够在浏览器中作为高信任运行。要确保这一点,您可以检查 Application.HasElevatedPermissions 属性 theTextBlock.Text = "Is Elevated-Trust: " +
Application.Current.HasElevatedPermissions.ToString();
现在尝试一些更有趣的事情。尝试读取只有高信任应用程序才能访问的文件系统中的文件
theTextBlock.Text =
File.ReadAllText(@"C:\Windows\System32\Drivers\etc\hosts");
如您所见,应用程序按预期运行,并具有 OOB 应用程序的所有高信任功能。
现在让我们尝试将域从 localhost 更改为另一个域。转到 Web 应用程序项目属性,切换到“Web”选项卡,然后转到“服务器设置”,将服务器从 Visual Studio 开发服务器更改为本地 IIS Web 服务器,并使用您的机器名作为域并保存设置。(您可能会被要求确认虚拟目录创建,这是因为您已更改为另一个域并使用了另一个虚拟目录。)
现在尝试运行应用程序。应用程序将无法运行,并且您会收到安全异常,这是因为新域未像 _localhost_ 那样列入白名单。
多窗口支持
多窗口支持或 Ad-hoc 窗口是 Silverlight 5 中高信任 OOB 应用程序的一项功能,它允许应用程序拥有主窗口之外的其他窗口。该功能通过现在可实例化的 Window 类提供。您可以使用 Window 类创建另一个窗口,并通过 Content 属性设置其内容,并使用 Visibility 属性显示它。以下代码创建一个宽 400 像素、长 300 像素的窗口,界面中只有一个按钮 Window wnd = new Window();
wnd.Width = 400;
wnd.Height = 300;
wnd.Content = new Button { Content = "Say Hello" };
wnd.Visibility = System.Windows.Visibility.Visible;
请注意,您可以通过关闭主窗口来结束应用程序;关闭任何其他窗口都无关紧要。您不仅限于窗口内容中的按钮或单个对象。您可以创建另一个页面(即用户控件)并将其设置为窗口的内容。 Window wnd = new Window();
wnd.Width = 400;
wnd.Height = 300;
wnd.Content = new MyOtherPage();
wnd.Visibility = System.Windows.Visibility.Visible;
您还可以通过删除工具栏和边框并自行通过代码创建它们来创建具有自定义外观的窗口。 Window wnd = new Window();
wnd.Width = 400;
wnd.Height = 300;
wnd.Content = new MyOtherPageWithCustomChrome();
wnd.WindowStyle = WindowStyle.None;
wnd.Visibility = System.Windows.Visibility.Visible;
请注意,如果您没有高信任功能,则无法生成其他窗口。如果您尝试这样做,您将收到安全异常。文件系统访问
与 Silverlight 4 中仅能访问“我的文档”文件夹的高信任应用程序不同,Silverlight 5 高信任应用程序(浏览器内和浏览器外)可以完全访问文件系统。但请记住,尽管您拥有对文件系统的完全访问权限,但您仍然受限于运行您应用程序的用户的权限。如果用户无权访问特定文件或文件夹,则您也无权访问该文件或文件夹。要测试此功能,请尝试从系统文件夹(例如)中的文件读取内容。theTextBlock.Text =
File.ReadAllText(@"C:\Windows\System32\Drivers\etc\hosts");
如您所见,您可以访问该文件。默认情况下,如果您运行的是 Windows Vista 或 Windows 7,您的用户将不具有管理员权限,除非他以提升模式启动 Visual Studio(或您的应用程序)。因此,如果您没有管理员权限并尝试获得对同一文件的写入权限,您的应用程序将失败,因为您的应用程序受用户权限的限制,并且用户没有对该文件的写入权限。 File.AppendAllText
(@"C:\Windows\System32\Drivers\etc\hosts",
"\nfoo");
在没有用户提升权限的情况下尝试写入系统驱动器时也会得到相同的结果 File.WriteAllText(@"C:\test.txt", "Foo");
平台调用
Silverlight 4 引入了对 自动化和 COM 组件 的支持。Silverlight 5 增加了对平台调用(或 P/Invoke)的支持。平台调用允许您从 Silverlight 应用程序调用原生代码(例如 DLL 和 Windows API)。这当然是一个巨大的改进。它使用与其他 WinForms 应用程序相同的机制。不幸的是,此功能目前在 Beta 版中不可用。
性能及其他更改
性能
Silverlight 5 的性能在多个方面得到了改进- 整个产品的性能显著提升
- 通过多核后台 JIT 编译器提高了启动性能
- XAML 解析时间得到改善,特别是对于 UserControl 和 ResourceDictionary
- 增加了 64 位运行时版本。Beta 版中没有
- Internet Explorer 9 在无窗口模式下的硬件加速渲染
网络
网络也得到了一系列改进- 网络延迟显著改善
- ClientHttpWebRequest 场景性能提升 90%
服务
增加了对 WCF 中 WS-Trust 的支持。(WS-Trust 是旨在提高安全性和验证的规范。)分析和测试
- 自动化 UI 测试
- 改进的性能分析支持
- 内存
- CPU
- 线程竞争
其他
- 支持 Windows Azure
- 浏览器内 HTML 支持
- 整个产品还有更多修复和改进