介绍 2005 年 12 月 CTP:Windows Presentation Foundation中的新增功能

 

卡尔斯滕·贾努谢夫斯基
Microsoft Corporation

2005 年 12 月

总结:2005 年 12 月,Microsoft 发布了 Windows Presentation Foundation 社区技术预览版 (CTP) ,这是适用于 Windows 的新演示文稿子系统,可将文档、图形和应用程序的开发统一到一个通用平台中。 在本文中,我们将简要介绍 12 月 CTP 中的一些新功能,以及自以前版本以来所做的更改。 ) (24 个打印页

下载代码示例,NovCTP.msi

目录

简介
   Avalon 12 月社区技术预览版
   社区技术预览版说明
探索新功能
   CompositionTarget
   PropertyTrigger
   改进了三维数据绑定
重大更改
   Mini-Language删除
   删除了 ~ (波形符) 语法
   删除 WebServiceDataProvider 并更改 ObjectDataProvider
   .WBA 将 更改为 。XBAP
   控件更改
   三维更改
   更改为视觉对象
   媒体更改
   HitTesting Changes
   ItemsControl 更改
   下标和上标的版式更改
   菜单更改
   DocumentStructures 更改
   删除 MonthCalendar 和 DatePicker
   TimeManager 已删除
致谢

简介

Microsoft Windows Presentation Foundation (以前代号为“Avalon”) 为在 Windows Vista 中构建应用程序和高保真体验提供了基础,将应用程序 UI、文档和媒体内容混合在一起,同时利用计算机的全部功能。 该功能扩展到对平板电脑和其他形式的输入的支持、更现代的映像和打印管道、辅助功能和 UI 自动化基础结构、数据驱动的 UI 和可视化,以及用于将应用程序体验融入 Windows shell 的集成点。

有关下载 CTP 的信息,请参阅 发行说明

有关 Microsoft Windows Presentation Foundation (WPF) 的概述,请参阅 Windows Presentation Foundation Beta 1 版本的体系结构概述

Avalon 12 月社区技术预览版

此版本中有一些令人兴奋的新功能,下面将枚举这些功能。 对于以前使用 CTP 版本的人员,有一些更改。 本文将涉及其中一些更改,但并不全面。

社区技术预览版说明

社区技术预览版 (CTP) 版本不会经历与 beta 版本相同的严格测试。 虽然 beta 版本可获得更高级别的测试和功能工作,但 CTP 旨在向开发人员展示最新的工作版本。 因此,CTP 不受支持,预发行软件,应采取一些预防措施。 在下载或安装预发行版软件之前,请阅读最新的 自述文件和安装指南

探索新功能

CompositionTarget

WPF 动画引擎功能强大。 将动画连接到任何 Avalon 元素上的任何属性的功能为创建动态用户界面提供了许多令人兴奋的可能性。 虽然动画引擎功能非常强大,但它并不符合所有场景,尤其是在 (条件(例如,物理、碰撞) 在更精细的时间刻度上影响动画过程、动画需要创建视觉对象或需要进行后期布局动画时)。 因此,引入了 CompositionTarget API,该 API 允许基于每帧回调创建自定义动画。

CompositionTarget.Rendering 事件在 Avalon 的呈现期间触发。 若要使用 CompositionTarget.Rendering,只需将 EventHandler 委托注册到 CompositionTarget 上的静态 Rendering 方法即可。 可以在处理程序方法中创建所需的任何效果,它将每帧调用一次。 每次 Avalon 跨通道将可视化树封送到合成树和/或对合成树进行更新时,动画都将更新。 这在计算布局后发生;但是,如果影响委托中的布局,则会在呈现之前再次计算该布局。 有关 Avalon 体系结构的详细信息,请参阅 Chris Anderson 和 Greg Schechter 的 PDC 演讲

在事件触发时添加或删除呈现委托将延迟到事件完成触发之后。 这与 CLR 中基于 MulticastDelegate 的事件的处理方式一致。 另请注意,无法保证按照任何特定顺序来调用呈现事件。 如果有多个依赖于特定顺序的委托,则应注册单个 Rendering 事件,并自行按正确的顺序对其进行多路复用。

让我们看一个简单的示例。 下面的代码示例将创建一个应用程序,该应用程序可随机更改 Page 上的背景色。 应注意的是,在实践中,可以使用自定义的“随机颜色”动画执行此操作:但是,此示例旨在仅显示如何挂钩事件,而不是有关在事件中执行的操作的最佳做法。

        Random rand = new Random();

        public Page1()
            : base()
        {
            CompositionTarget.Rendering += UpdateColor;
        }

        protected void UpdateColor(object sender, EventArgs e)
        {
            //set a random color
            this.Background = new SolidColorBrush(
                                Color.FromRgb((byte)rand.Next(255),
                                              (byte)rand.Next(255),
                                              (byte)rand.Next(255)));
        }

如上所示,注册 UpdateColor 将导致每次 Avalon 呈现此页面时更新页面的背景画笔。 运行此方法可能会对眼睛有点苛刻,但可以让你了解 API 的工作原理。 此内容的完整源包含在与本文关联的下载中。

如果发现动画在不同计算机上以不同的速度运行,则可能是由于动画与帧速率无关。 根据正在运行的系统以及该系统的工作负载, 渲染 事件每秒的调用次数可能不同。 若要使动画帧速率独立,应基于实时动画。 实现此目的的一种方法是创建 ParallelTimeline 来跟踪帧之间的运行时间。 在 AnimateMotion 示例中,演示了一个矩形,该矩形后面是一些物理效果的鼠标滞后,可以使用一个实现此技术的 TimeTracker 类。

最后,你可能有兴趣创建涉及创建视觉对象的效果,而不是简单地操作已属于树的一部分的视觉对象。 你可能会遇到的问题是实际放置视觉对象的位置。 例如,考虑烟花效果。 此效果将像修饰器一样,每当单击子元素时,“烟花”的爆发都会向外产生动画效果,并随着重力而下降。

可以使用矩形形状和径向渐变制作烟花,并将其添加到效果的父级。 但是,如果父级本身是修饰器,则它只能有一个子元素,因此它会对效果的使用位置施加限制。 此外,添加许多形状的性能不如向绘图上下文添加视觉对象好。 因此,你可能会决定在效果 OnRender 方法中呈现烟花。 这也存在问题: OnRender 中的视觉对象显示在子视觉对象) (之前。 我们真正需要的是一个类似修饰器的类,该类具有类似于 OnRender 的方法,但会将视觉对象放在子级之后。 有关如何实现此类的示例,请参阅 CreateVisuals 示例中的 OverlayRenderDecorator.cs。

Aa480187.intronovctp01 (en-us,MSDN.10) .jpg

Aa480187.intronovctp02 (en-us,MSDN.10) .jpg

PropertyTrigger

触发器现在支持 EnterActions 和 ExitActions 集合,这实际上允许在任何类型的触发器上启动动画。 由于这些集合已添加到 TriggerBase 类,因此所有派生的 Trigger 类现在都支持这些集合。 在此 CTP 之前,只有 EventTriggers 支持通过其 Actions 集合启动动画,这使你可以在触发路由事件时开始情节提要。 现在,所有触发器都能够启动动画。 在这些其他类型的触发器上开始情节提要的功能非常重要,因为在许多情况下,你希望动画开始,但不一定可以订阅触发事件。

例如,现在可以基于属性值启动动画。 下面的示例中可以看到这一点,当 IsMouseOver 属性更改为 true 时,该示例将启动动画。 当 属性返回到 false 时,它将启动另一个动画。

  <Grid xmlns="https://schemas.microsoft.com/winfx/avalon/2005" 
xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005" >
    <Grid.Resources>
      <Style x:Key="PropertyTriggerExampleButtonStyle" 
TargetType="{x:Type Button}">
        <Setter Property="Opacity" Value="0.25" />
        <Setter Property="Button.Background">
          <Setter.Value>
            <SolidColorBrush Color="Orange" />
          </Setter.Value>
        </Setter>
        <Style.Triggers>
          <Trigger Property="IsMouseOver" Value="True">
            <Trigger.EnterActions>
              <BeginStoryboard>
                <Storyboard>
                  <DoubleAnimation Storyboard.TargetProperty="Opacity"
                    To="1" Duration="0:0:1" />
                </Storyboard>
              </BeginStoryboard>
            </Trigger.EnterActions>
            <Trigger.ExitActions>
              <BeginStoryboard>
                <Storyboard>
                  <DoubleAnimation Storyboard.TargetProperty="Opacity"
                    To="0.25" Duration="0:0:1" />
                </Storyboard>
              </BeginStoryboard>
            </Trigger.ExitActions>
          </Trigger>
        </Style.Triggers>
      </Style>
    </Grid.Resources>
    <Button Height="100" Width="100" Style="{StaticResource PropertyTriggerExampleButtonStyle}">
    </Button>
  </Grid>

更有趣的是 使用 DataTriggers。 例如,可以想象数据绑定到 Web 服务,如果 Web 服务返回了特定值,则可以触发动画。

此外,使用 MultiTriggersMultiDataTriggers 将允许基于多个属性或数据值有条件地启动这些动画。

改进的三维数据绑定

DataBinding 只能面向 DependencyProperties。 为了启用将条形图中条形图中的条形高度数据绑定到 ScaleTransform3D 的 Y 刻度等方案,X/Y/Z 现在是属于 double 类型的独立 DependencyProperties 的属性。 这与二维转换中的现有 OffsetScaleSkew 以及 Avalon 中的大多数其他 DependencyProperties 一致。

新建
TranslateTransform3D.Offset TranslateTransform3D.OffsetX

TranslateTransform3D.OffsetY

TranslateTransform3D.OffsetZ

ScaleTransform3D.Scale

 

 

ScaleTransfrom3D.Center

ScaleTransform3D.ScaleX
ScaleTransform3D.ScaleY
ScaleTransform3D.ScaleZ
ScaleTransform3D.CenterX
ScaleTransform3D.CenterY
ScaleTransform3D.CenterZ
RotateTransform3D.Center RotateTransform3D.CenterX

RotateTransform3D.CenterY
RotateTransform3D.CenterZ

ScaleTransform.Center ScaleTransform.CenterX
ScaleTransform.CenterY
SkewTransform.Center SkewTransform.CenterX
SkewTransform.CenterY
RotateTransform.Center RotateTransform.CenterX
RotateTransform.CenterY

下面是一个示例,说明现在可以使用此新语法完成的数据绑定类型。 该示例将滑块控件绑定到平移的 OffsetX 和刻度的 ScaleY。 它还演示了三维引擎现在如何支持数据绑定;在本例中,它使用 VisualBrush 将数据绑定到 XML 数据源的值。 使用 ModelVisual3D 构造启用数据绑定,下面的中断性变更对此进行了详细介绍。

  <Grid xmlns="https://schemas.microsoft.com/winfx/avalon/2005"
    xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005">
    <Grid.Resources>
      <Style x:Key="Horizontal" TargetType="{x:Type Slider}">
        <Setter Property = "IsSnapToTickEnabled" Value ="False"/>
        <Setter Property = "TickPlacement" Value ="BottomRight"/>
        <Setter Property = "TickFrequency" Value =".5"/>
        <Setter Property = "Minimum" Value ="-5"/>
        <Setter Property = "Maximum" Value ="5"/>
        <Setter Property = "Orientation" Value ="Horizontal"/>
        <Setter Property = "Value" Value ="1"/>
      </Style>
      <XmlDataProvider x:Key="ImageData">
        <data  >
          <text>TEXT.</text>
        </data>
      </XmlDataProvider>
      <MeshGeometry3D x:Key="meshData" 
                  Positions="-1 -1 0  1 -1 0  -1 1 0  1 1 0"
                  Normals="0 0 1  0 0 1  0 0 1  0 0 1"
                  TextureCoordinates="0 1  1 1  0 0  1 0   "
                  TriangleIndices="0 1 2  1 3 2" />
    </Grid.Resources>
    <StackPanel Orientation="Horizontal">
      <Label>Translate OffsetX</Label>
      <Slider Width="100" Style="{StaticResource Horizontal}" Name="sliderOffsetX"/>
      <Label>Scale ScaleY</Label>
      <Slider Width="100" Style="{StaticResource Horizontal}" Name="sliderScaleY"/>
    </StackPanel>
    <Grid>
      <Viewport3D Name="myViewport" >
        <ModelVisual3D>
          <ModelVisual3D.Content>
            <Model3DGroup >
              <Model3DGroup.Children>
                <DirectionalLight Color="#FFFFFFFF" Direction="-3,-4,-5" />
                <GeometryModel3D Geometry="{StaticResource meshData}">
                  <GeometryModel3D.Material>
                    <DiffuseMaterial>
                      <DiffuseMaterial.Brush>
                        <VisualBrush >
                          <VisualBrush.Visual>
                            <TextBlock Text="{Binding Source={StaticResource ImageData}, XPath=data/text}" >
                            </TextBlock>
                          </VisualBrush.Visual>
                        </VisualBrush>
                      </DiffuseMaterial.Brush>
                    </DiffuseMaterial>
                  </GeometryModel3D.Material>
                  <GeometryModel3D.Transform>
                    <Transform3DGroup>
                      <ScaleTransform3D ScaleX="1" ScaleY="{Binding 
ElementName=sliderScaleY, Path=Value}" ScaleZ="1"/>
                      <TranslateTransform3D OffsetX="{Binding 
ElementName=sliderOffsetX, Path=Value}" OffsetY="-0" OffsetZ="1">
                      </TranslateTransform3D>
                      <RotateTransform3D>
                        <RotateTransform3D.Rotation>
                          <AxisAngleRotation3D  Axis="0,3,0" Angle="45" />
                        </RotateTransform3D.Rotation>
                      </RotateTransform3D>
                    </Transform3DGroup>
                  </GeometryModel3D.Transform>
                </GeometryModel3D>
              </Model3DGroup.Children>
            </Model3DGroup>
          </ModelVisual3D.Content>
        </ModelVisual3D>
        <Viewport3D.Camera>
          <PerspectiveCamera FarPlaneDistance="20"  UpDirection="0,1,0" 
NearPlaneDistance="1" Position="0,0,10" FieldOfView="45" />
        </Viewport3D.Camera>
      </Viewport3D>
    </Grid>
  </Grid>

Aa480187.intronovctp03 (en-us,MSDN.10) .jpg

重大更改

Mini-Language删除

要删除的格式包括:

  • “HorizontalGradient color1 color2”
  • “VerticalGradient color1 color2”
  • “LinearGradient x1,y1 x2,y2 color1 color2”
  • “RadialGradient color1 color2”
  • “Image filename.extension”
  • 整个转换微型语言 (“缩放 (1,2) 旋转 (45) ...”)

供参考:

<Rectangle Fill="HorizontalGradient color1 color2" .../>

变为:

<Rectangle ...>
  <Rectangle.Fill>
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
      <LinearGradientBrush.GradientStops>
        <GradientStopCollection>
          <GradientStop Offset="0" Color="color1"/>
          <GradientStop Offset="1" Color="color2"/>
        </GradientStopCollection>
      </LinearGradientBrush.GradientStops>
    </LinearGradient>
  </Rectangle.Fill>
</Rectangle>

VerticalGradient 与此类似,只需将 EndPoint 更改为“0,1”, 而 LinearGradient 只需将 StartPoint 设置为 x1,y1, 将 EndPoint 设置为 x2,y2。 对于 RadialGradient,使用 Center 和 Radii 的默认值,因此无需设置它们;同样, 对于 ImageBrush ,除 Source=“filename.extension”之外,所有值都是默认值。

对于转换,可以转换一个字符串,例如“缩放 (1,2) 旋转 (45) ...”自

<TransformGroup>
  <TransformGroup.Children>
    <ScaleTransform ScaleX="1" ScaleY="2"/>
    <RotateTransform Angle="45"/>
  </TransformGroup.Children>
</TransformGroup>

Matrix 的现有微型语言取代了转换语言,即表示仿射转换或“Identity”中的 m11、m12、m21、m22、offsetX、offsetY 的 6 双精度值。

与本文关联的下载中提供了一个工具,该工具将缓解将代码移植到此新语法的难题。

删除 ~ (波形符) 语法

WPF 已删除对相对 URI 中使用的 ~/ 的支持。 进行此更改后,必须使用 Pack Uri 语法来引用源站点上的文件。 例如, <Image Source=“~/foo.jpg” /> 更改为 <Image Source=“pack://siteoforigin:.../foo.jpg” />

删除 WebServiceDataProvider 和对 ObjectDataProvider 的更改

WebServiceDataSource 已弃用,其功能正在合并到 ObjectDataSource 中ObjectDataProvider 将不再采用 TypeName,而是采用 ObjectType。 此外, ObjectDataProvider 将不再采用字符串中的 参数 ,而是具有参数集合。 最后,ObjectDataProvider 可以接受任何对象作为其 ObjectInstance,并使用分配给 ObjectInstanceDataSourceProvider 的数据。

旧方式:

<Page>
  <Page.Resources>

    <ObjectDataProvider x:Key="myClass" TypeName="MyClass,MyAssembly" 
Parameters="some-string,2" />

    <WebServiceDataProvider x:Key="wsdp" Service="myServiceProxy,assembly" QueryMethod="wsMethod" />

新方法:

<?Mapping XmlNamespace="local" ClrNamespace="System"?>
<?Mapping XmlNamespace="ws" ClrNamespace="Web.Service.Namespace" 
Assembly="assembly" ?>
<Page xmlns:local="local" xmlns:ws="ws">
  <Page.Resources>

    <ObjectDataProvider x:Key="myClass" ObjectType="{x:Type 
local:MyClass}">
      <ObjectDataProvider.ConstructorParameters>
        <x:string>some-string</x:string>
        <x:Int32>2</x:Int32>
      </ObjectDataProvider.ConstructorParameters>
    </ObjectDataProvider>

    <ObjectDataProvider x:Key="wsdp" ObjectType="{x:Type 
ws:myServiceProxy}" MethodName="wsMethod" />

.WBA 将 更改为 。XBAP

WPF Web 浏览器应用程序文件扩展名将从“.wba”更改为“.xbap”,MIME 内容类型将从“application/x-ms-wba”更改为“application/x-ms-xbap”。

控件更改

WPF 中对多个控件进行了一些更改:

  • 已将 TabStripPlacement枚举 替换为 Dock

  • 已删除 BeginStoryboard.Placeholder 事件

  • 已将 DictionaryLocation 重命名为 ResourceDictionaryLocation

    System.Windows.DictionaryLocation 枚举重命名为 ResourceDictionaryLocation。

需要修改任何 ThemeInfoAttributes

老:

[ThemeInfoAttribute(DictionaryLocation.*, DictionaryLocation.*)]

新增功能:

[ThemeInfoAttribute(ResourceDictionaryLocation.*, 
ResourceDictionaryLocation.*)]
  • 删除 popup.HasDropShadow

    HasDropShadow 属性已从弹出窗口中删除。

  • ScrollBar 使用PART_名称,并使 IsStandAlone 属性为 Internal。

    现在应指定以下名称之一:PART_HorizontalScrollBar或PART_VerticalScrollBar,而不是在 ScrollViewer 模板的滚动条上指定 IsStandalone=“false”。 scrollviewer 模板外部的 ScrollBar 将继续工作,无需修改。

老:

      <!-- ScrollViewer's Control Template-->
                  <...>
                              <ScrollBar Orientation="Horizontal" 
IsStandalone="false" .../>
                              <ScrollBar Orientation="Vertical" 
IsStandalone="false" .../>
                  <...>
                        </ControlTemplate>

                        <!-- Standalone Scrollbar-- >
                        <ScrollBar IsStandalone="true"/>

新增功能:

      <!-- ScrollViewer's Control Template-->
                  <…>
                              <ScrollBar Orientation="Horizontal" 
Name="PART_HorizontalScrollBar" .../>
                              <ScrollBar Orientation="Vertical" 
Name="PART_VerticalScrollBar" .../>
                  <...>
                        </ControlTemplate>

                        <!-- Standalone Scrollbar-- >
                        <ScrollBar/>

三维更改

挂起 ViewPort3D 的新 Children 集合的类型为 Visual3DcollectionModels 集合已被删除。 要添加到此 Children 集合的主要类型是新的 ModelVisual3DModelVisual3D 具有 一个 Content 属性,该属性采用 Model3D 当然派生自 Model3DGroup 。 这是所有 Model3DGroup 对象(包括灯光和几何图形)的位置。 ModelVisual3D 还具有 Visual3DCollection 类型的 Children 属性,以便可以嵌套其他 ModelVisual3D 对象。 

实质上,此更改是视区与模型之间的附加层,即视觉层。  Daniel Lehenbauer 在最近的一篇博客文章中 解释了添加此附加视觉层的确切原因。 他对管理变革的体系结构基础进行了相对深入的讨论。

此更改具有两个好处:

  1. 扩展性。 Model3DGroupGeometryModel3D 是密封的,这意味着无法从它们派生并创建类。 例如,无法创建自己的可在 XAML 中直接实例化的多维数据集类。  但 ModelVisual3D 不是密封的,因此从它继承的能力使你能够创建自己的类来创建可重用模型。
  2. 数据绑定。 通过此更改,直接在三维对象的属性上启用数据绑定,而不是间接数据绑定。

对三维 API 进行了其他 API 更改。

Up 属性已重命名为 UpDirectionLookAtPoint 属性将成为 LookDirection。 类型将是 Vector3D 而不是 Point3D。 相机将具有 Transform 属性,该属性转换 PositionLookDirectionUpDirection 的方式与 Model3D.Transform 影响 SpotLight 的位置和方向的方式相同。 这将启用“将相机旋转到世界各地”的类似场景,而仅使用 Point3D/Vector3D 动画是无法实现的。 这还将在 MatrixCamera 上启用动画,以前始终需要自定义代码进行动画处理。

最后, Rotation3D 现在是抽象的,其 API 是新的 AxisAngleRotation3D。 在 XAML 中,这是纯重命名。 在以前使用 Rotation3D 的位置使用 AxisAngleRotation3D

如果通过代码与三维旋转进行交互,需要注意以下几点:

  • RotateTransform3D.Rotation 的返回结果为抽象 Rotation3D。 需要强制转换为 AxisAngleRotation3D 才能访问 Axis/Angle 属性。
  • 删除了将轴/角度夹在一起的 RotationTransform3D 函数。 请改用新的 RotateTransform3D (新的 AxisAngleRotation3D (轴, angle) )
  • Rotation3D.Quaternion 属性已删除;可以使用新的四元数 (aarot 构造四元数。轴、aarot。角度)

更改为视觉对象

  • VisualTreeHelper (以前是 VisualOperations) 现在仅用作公共“Getter”类,不再提供“Set”方法。 

媒体更改

在 WPF 中播放音频和视频的方式发生了一些根本性的变化。 引入了一个新的 对象,称为 MediaPlayerMediaPlayer 对象可在两种不同的模式下使用,具体取决于驱动玩家的内容:独立模式或时钟模式。 在独立模式下使用时, MediaPlayer 对象不使用 WPF 计时系统,直接播放媒体。 在时钟模式下, 可以将 MediaPlayer 视为动画的目标,因此它将在计时树中具有相应的时间线和时钟条目。 如果媒体需要与其他时间线同步,时钟模式非常有用;如果不需要同步,则不需要创建时钟的开销,独立模式就足够了。

MediaPlayer.Clock 属性确定玩家处于哪个模式:null 表示独立模式;非 null 表示时钟模式。

MediaElement 仍在 API 中,并且是 MediaPlayer 和 WPF 框架之间的链接,用于处理实际媒体的布局和组合等任务。 MediaPlayerMediaElement 之间的关系如下所示:MediaPlayer 可能与MediaElement 相关联,但 MediaElement始终具有基础 MediaPlayer

只有在时钟模式下使用 MediaPlayer 时,MediaClockMediaTimeline 才具有相关性。 它们派生自 WPF 动画系统,工作方式与所有时钟和时间线一样,时间线是时钟的模板;实际驱动 MediaPlayer 的是 MediaClock(如果使用)。

默认情况下,MediaPlayer 处于独立模式,但有两种方法可以切换到时钟模式:

  1. 在情节提要中,当 MediaTimelineMediaElement 为目标时,将创建 MediaClock 并将其分配给 MediaElement 的关联播放器;
  2. MediaTimeline 显式创建 MediaClock 并将其分配给 MediaPlayer 对象。

有几个控件选项仅在独立模式下可用:

  • 设置 MediaPlayer.Source;
  • 在 MediaPlayer 上使用 PlayPauseStop 方法;
  • 更改 MediaPlayer 的 PositionSpeedRatio 属性。

如果用户尝试在时钟模式下使用这些功能,则将引发 InvalidOperationException 。 在这种情况下,必须使用 计时 引擎控件来操作媒体。

设置正在播放的媒体的源在独立模式和时钟模式之间有所不同。 这可能会令人困惑,因为 MediaElementMediaPlayerMediaTimeline 上有一个 Source 属性。

在独立模式下,可以在 MediaElementMediaPlayer 上设置源。 MediaElement.Source 中的更改将反映在 MediaElement.Player.Source 中,反之亦然。 在 MediaElement 上设置源将立即开始播放音频/视频;但是,在 MediaPlayer 上设置源需要实际启动媒体。

在时钟模式下,必须在 MediaTimeline 中设置媒体源。 这会影响在 MediaPlayer 上设置源。 请注意,在将时钟分配给 MediaPlayer 之前,媒体不会开始播放。

以下代码示例应有助于阐明新模型。

基本 XAML 方案

这将创建一个 MediaPlayer,在 MediaElement 上设置 Source,这将设置 MediaElement.Player.Source,进而开始加载媒体并播放它。

<Canvas xmlns="https://schemas.microsoft.com/winfx/avalon/2005" 
xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005">
  <MediaElement Source = "ep2.wmv"/>
</Canvas>

情节提要 XAML 方案

在这种情况下, MediaElement 没有预先指定的 SourceMediaElement.Player 仍将在加载时创建,但 为空。 在 BeginStoryboard 中,将在 MediaTimeline 上自动创建 MediaClock,并将其设置为 myvideo。Player.Clock。 设置 MediaPlayer.Clock 还具有设置 MediaPlayer.Source 的效果。

<Canvas xmlns="https://schemas.microsoft.com/winfx/avalon/2005" 
xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005">

  <Canvas.Triggers>
    <EventTrigger RoutedEvent="Button.Click" SourceName="playButton">
      <EventTrigger.Actions>
        <BeginStoryboard Name= "myBegin">
          <Storyboard>
            <MediaTimeline Source="ep2.wmv" Storyboard.TargetName="myvideo"/>  
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger.Actions>
    </EventTrigger>
    <EventTrigger RoutedEvent="Button.Click" SourceName="pauseButton">
      <EventTrigger.Actions>
        <PauseStoryboard BeginStoryboardName="myBegin" />
      </EventTrigger.Actions>
    </EventTrigger>
  </Canvas.Triggers>

  <StackPanel>
    <MediaElement Name="myvideo"/>
    <Button Name="playButton" >Play</Button>
    <Button Name="pauseButton" >Pause</Button>
  </StackPanel>

</Canvas>

在新 API 下,可以通过将 MPs.Source 设置为所需的 URI,通过代码实现预滚动。 例如,这可以在加载页面时完成。 一旦 BeginStoryboard 被调用和 ME。设置 Player.Source 后,MP 会知道它是同一 URI,并会保留打开的文件。

音频方案

<Canvas xmlns="https://schemas.microsoft.com/winfx/avalon/2005" 
xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005">
  <MediaElement Source="sound.wav"/>
</Canvas>

更改卷属性

<Canvas xmlns="https://schemas.microsoft.com/winfx/avalon/2005" 
xmlns:x="https://schemas.microsoft.com/winfx/xaml/2005">
  <MediaElement Source="ep2.wmv" Volume="0.2" Balance="-1"/>
</Canvas> 

使用转换、剪辑和不透明度操作 MediaElement

<Canvas xmlns="https://schemas.microsoft.com/winfx/avalon/2005">

  <MediaElement Source="ep2.wmv" Opacity="0.7" >
    <MediaElement.LayoutTransform>
      <TransformGroup>
        <RotateTransform Center="200,100" Angle="305" />
      </TransformGroup>
    </MediaElement.LayoutTransform>
  </MediaElement>

  <MediaElement Source=" ep2.wmv" Opacity="0.5" >
    <MediaElement.Clip>
      <EllipseGeometry Center="200,100" RadiusX="150" RadiusY="100" />
    </MediaElement.Clip>
    <MediaElement.LayoutTransform>
      <TransformGroup>
        <SkewTransform AngleX="15" AngleY="15" />
        <RotateTransform Center="25,50" Angle="45" />
      </TransformGroup>
    </MediaElement.LayoutTransform>
  </MediaElement>

</Canvas>

使用计时引擎的音频方案

MediaPlayer player;

void startClick(object sender, RoutedEventArgs e)
{
  MediaTimeline mt = new MediaTimeline(new Uri("sound.wav"));
  MediaClock mc = mt.CreateClock();
  player.Clock = mc; // starts prerolling
}

void beginClick(object sender, RoutedEventArgs e)
{
  player.Clock.ClockController.Begin();
}
void stopClick(object sender, RoutedEventArgs e)
{
  player.Clock.ClockController.Stop();
}
void pauseClick(object sender, RoutedEventArgs e)
{
  player.Clock.ClockController.Pause();
}
void resumeClick(object sender, RoutedEventArgs e)
{
  player.Clock.ClockController.Resume();
}
void volumeIncClick(object sender, RoutedEventArgs e)
{
  player.Volume+=0.25;
}
void volumeDecClick(object sender, RoutedEventArgs e)
{
  player.Volume-=0.25;
}

不使用计时引擎的音频方案

MediaPlayer player;

void startClick(object sender, RoutedEventArgs e)
{
  player.Clock = null; // this will ensure no clocks are driving this player
  player.Source = new Uri("sound.wav"); // starts prerolling
}

void beginClick(object sender, RoutedEventArgs e)
{
  player.Position = 0; 
  player.Play();
}
void stopClick(object sender, RoutedEventArgs e)
{
  player.Stop();
}
void pauseClick(object sender, RoutedEventArgs e)
{
  player.Pause();
}
void resumeClick(object sender, RoutedEventArgs e)
{
  player.Play();
}
void volumeIncClick(object sender, RoutedEventArgs e)
{
  player.Volume+=0.25;
}
void volumeDecClick(object sender, RoutedEventArgs e)
{
  player.Volume-=0.25;
}

使用计时引擎创建绘图

视频还可以在绘图中使用,然后可在 DrawingBrush 中使用。 这是一个示例,其中使用 MediaPlayer 时没有 MediaElement

private static Drawing MakeVideo()
{
  MediaTimeline mt = new MediaTimeline(new Uri("ep.wmv"));
  MediaClock mc = mt.CreateClock();
  MediaPlayer mp = new MediaPlayer();
  mp.Clock = mc;
  DrawingGroup dg = new DrawingGroup();
  using (DrawingContext ctx = dg.Open())
  {
    ctx.DrawVideo(mp, new Rect(0, 0, 500, 30));
  }

  return dg;
}

在不使用计时引擎的情况下创建绘图

视频还可以在绘图中使用,然后可在 DrawingBrush 中使用。

private static Drawing MakeVideo()
{
  MediaPlayer mp = new MediaPlayer();
  mp.Source = new Uri("ep.wmv");
  DrawingGroup dg = new DrawingGroup();
  using (DrawingContext ctx = dg.Open())
  {
    ctx.DrawVideo(mp, new Rect(0, 0, 500, 30));
  }

  return dg;
}

创建 VisualBrush

<Canvas xmlns="https://schemas.microsoft.com/winfx/avalon/2005">
  <Button Height="300" Width="500">
    <Button.Background>
      <VisualBrush>
        <VisualBrush.Visual>
          <MediaElement Source="ep2.wmv" />
        </VisualBrush.Visual>
      </VisualBrush>
    </Button.Background>
  </Button>
</Canvas>

HitTesting Changes

二维更改

新建
HitTestFilter HitTestFilterCallback
HitTestResultDelegate HitTestResultCallback
HitTestResult.Visual HitTestResult.VisualHit
PointHitTestResult.Point PointHitTestResult.PointHit
GeometryHitTestResult.Geometry (使用转换服务和/或 VisualOperations.GetTransform () 转换命中测试 geometry.)

三维更改

新建
Ray3DHitTestResult RayHitTestResult

除删除 GeometryHitTestResult.Geometry API 外,上述所有更改都是纯重命名,行为没有任何变化。 此属性用于返回转换为命中视觉对象的本地空间的命中测试几何图形。 仍可通过两种方式通过 Visual API 获取此信息:

  1. 使用 TransformToAncestor (hitVisual、startVisual) 尝试强制转换为 MatrixTransform 并将结果应用于命中几何图形。 此方法将包括 ImageEffects 应用的转换。 但是,如果已使用非线性转换应用 ImageEffect ,则强制转换可能会失败。
  2. 将视觉对象父级从 hitVisual 访问到 startVisual,连接视觉对象转换。 此方法忽略 ImageEffects

ItemsControl 更改

描述

与派生类(如 ListBox) )相比,纯 ItemsControl (现在生成 ContentPresenter 类型的容器,而不是 ContentControl。 一些后果是:

  • 如果任何) 必须指定 ContentPresenter 的目标类型,并且其 setter 中命名的属性必须适用于 ContentPresenter,则 ItemContainerStyle (。
  • 在可视化树中查找 ContentControl 的任何代码都应更改为查找 ContentPresenter

下标和上标的版式更改

删除下标和上标元素

老:

<Superscript>Hello</Superscript>
<Subscript>Hello</Subscript>

新增功能:

<Span Typography.Variants="Superscript">Hello</Span>
<Span Typography.Variants="Subscript">Hello</Span>

MenuItems 进行了一些基本更改:

<MenuItem Mode=“Separator” /> 替换为 <Separator />。

<MenuItem Mode=“Checkable” /> 替换为 <MenuItem IsCheckable=“true” />。

DocumentStructures 更改

Break 已重命名为 StoryBreak。

图已重命名为 FigureStructure。

List 已重命名为 ListStructure。

ListItem 已重命名为 ListItemStructure。

Paragraph 已重命名为 ParagraphStructure。

Section 已重命名为 SectionStructure。

表已重命名为 TableStructure。

TableCell 已重命名为 TableCellStructure。

TableRow 已重命名为 TableRowStructure。

TableRowGroup 已重命名为 TableRowGroupStructure。

删除 MonthCalendar 和 DatePicker

MonthCalendarDatePicker 控件已弃用。

TimeManager 已删除

TimeManager 已删除。

致谢

感谢 Adam Smith 的迷你语言修复工具、Avalon 动画团队(用于 CompositionTarget 示例)和 Avalon 媒体团队(用于媒体示例)。