创建自定义传输控件

MediaPlayerElement 具有可自定义的 XAML 传输控件,用于管理 Windows 应用中的音频和视频内容控件。 在这里,我们演示如何自定义 MediaTransportControls 模板。 我们将向你演示如何使用溢出菜单、添加自定义按钮和修改滑块。

重要 APIMediaPlayerElementMediaPlayerElement.AreTransportControlsEnabledMediaTransportControls

在开始之前,应熟悉 MediaPlayerElement 和 MediaTransportControls 类。 有关详细信息,请参阅 MediaPlayerElement 控件指南。

提示

本主题中的示例基于 媒体传输控件示例。 可以下载示例以查看并运行已完成的代码。

注意

MediaPlayerElement 仅在 Windows 10 版本 1607 及更高版本中可用。 如果要为早期版本的 Windows 10 开发应用,则需要改用 MediaElement 此页上 的所有示例也适用于 MediaElement

何时应自定义模板?

MediaPlayerElement 具有内置的传输控件,这些控件设计为在大多数视频和音频播放应用中都正常运行。 它们由 MediaTransportControls 类提供,其中包括用于播放、停止和导航媒体、调整音量、切换全屏、强制转换到第二台设备、启用字幕、切换音频轨以及调整播放速率的按钮。 MediaTransportControls 具有属性,可用于控制是否显示和启用每个按钮。 还可以设置 IsCompact 属性以指定控件是显示在一行还是两行中。

但是,在某些情况下,可能需要进一步自定义控件的外观或更改其行为。 以下是一些示例:

  • 更改图标、滑块行为和颜色。
  • 将不太常用的命令按钮移动到溢出菜单中。
  • 更改命令在调整控件大小时退出的顺序。
  • 提供不在默认集中的命令按钮。

注意

如果屏幕上没有足够的空间,屏幕上可见的按钮将以预定义的顺序退出内置传输控件。 若要更改此排序或放置不适合溢出菜单的命令,需要自定义控件。

可以通过修改默认模板来自定义控件的外观。 若要修改控件的行为或添加新命令,可以创建自定义控件,该控件派生自 MediaTransportControls。

提示

可自定义控件模板是 XAML 平台的一项强大功能,但也需要考虑后果。 自定义模板时,它将成为应用的静态部分,因此不会收到通过Microsoft对模板进行的任何平台更新。 如果模板更新由Microsoft进行,则应获取新模板并重新修改它,以获取更新后的模板的好处。

模板结构

ControlTemplate 是默认样式的一部分。 可以将此默认样式复制到项目中以对其进行修改。 ControlTemplate 分为类似于其他 XAML 控件模板的部分。

注意

有关修改模板的详细信息,请参阅 控件模板。 可以在 IDE 中使用文本编辑器或类似编辑器打开 (Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\(SDK version)\Generic 中的 XAML 文件。 每个控件的默认样式和模板在 generic.xaml 文件中定义。 可以通过搜索“MediaTransportControls”在 generic.xaml 中找到 MediaTransportControls 模板。

以下部分介绍如何自定义传输控件的多个主要元素:

  • Slider:允许用户在其媒体上进行推移,同时显示相关进度
  • CommandBar:包含所有按钮。 有关详细信息,请参阅 MediaTransportControls 参考主题的“剖析”部分。

自定义传输控件

如果只想修改 MediaTransportControls 的外观,可以创建默认控件样式和模板的副本,然后对其进行修改。 但是,如果还需要添加或修改控件的功能,则需要创建派生自 MediaTransportControls 的新类。

重新模板化控件

自定义 MediaTransportControls 默认样式和模板

  1. 将 MediaTransportControls 样式和模板中的默认样式复制到项目中的 ResourceDictionary。
  2. 为样式提供一个 x:Key 值来标识它,如下所示。
<Style TargetType="MediaTransportControls" x:Key="myTransportControlsStyle">
    <!-- Style content ... -->
</Style>
  1. 使用 MediaTransportControls 将 MediaPlayerElement 添加到 UI。
  2. 将 MediaTransportControls 元素的 Style 属性设置为自定义样式资源,如下所示。
<MediaPlayerElement AreTransportControlsEnabled="True">
    <MediaPlayerElement.TransportControls>
        <MediaTransportControls Style="{StaticResource myTransportControlsStyle}"/>
    </MediaPlayerElement.TransportControls>
</MediaPlayerElement>

有关修改样式和模板的详细信息,请参阅设置控件和控件模板样式。

创建派生控件

若要添加或修改传输控件的功能,必须创建派生自 MediaTransportControls 的新类。 调用 CustomMediaTransportControls 的派生类显示在 媒体传输控件示例 和此页面的其余示例中。

创建一个派生自 MediaTransportControls 的新类

  1. 向你的项目中添加一个新类文件。
    • 在 Visual Studio 中,选择“项目”>“添加类”。 “添加新项” 对话框随即打开。
    • 在“添加新项”对话框中,输入类文件的名称,然后单击“添加”。 (在媒体传输控件示例中,类命名为 CustomMediaTransportControls.)
  2. 修改类代码以派生自 MediaTransportControls 类。
public sealed class CustomMediaTransportControls : MediaTransportControls
{
}
  1. 将 MediaTransportControls 的默认样式复制到项目中的 ResourceDictionary 中。 这是你修改的样式和模板。 (在媒体传输控件示例中,将创建一个名为“主题”的新文件夹,并将名为 generic.xaml 的 ResourceDictionary 文件添加到其中。
  2. 样式的 TargetType 更改为新的自定义控件类型。 (在示例中,TargetType 更改为 local:CustomMediaTransportControls.)
xmlns:local="using:CustomMediaTransportControls">
...
<Style TargetType="local:CustomMediaTransportControls">
  1. 设置自定义类的 DefaultStyleKey。 这会告知自定义类将 Style 与 TargetType 配合使用 local:CustomMediaTransportControls
public sealed class CustomMediaTransportControls : MediaTransportControls
{
    public CustomMediaTransportControls()
    {
        this.DefaultStyleKey = typeof(CustomMediaTransportControls);
    }
}
  1. MediaPlayerElement 添加到 XAML 标记,并向其添加自定义传输控件。 需要注意的一点是,用于隐藏、显示、禁用和启用默认按钮的 API 仍使用自定义模板。
<MediaPlayerElement Name="MediaPlayerElement1" AreTransportControlsEnabled="True" Source="video.mp4">
    <MediaPlayerElement.TransportControls>
        <local:CustomMediaTransportControls x:Name="customMTC"
                                            IsFastForwardButtonVisible="True"
                                            IsFastForwardEnabled="True"
                                            IsFastRewindButtonVisible="True"
                                            IsFastRewindEnabled="True"
                                            IsPlaybackRateButtonVisible="True"
                                            IsPlaybackRateEnabled="True"
                                            IsCompact="False">
        </local:CustomMediaTransportControls>
    </MediaPlayerElement.TransportControls>
</MediaPlayerElement>

现在可以修改控件样式和模板来更新自定义控件的外观,以及用于更新其行为的控件代码。

使用溢出菜单

可以将 MediaTransportControls 命令按钮移动到溢出菜单中,以便隐藏不太常用的命令,直到用户需要它们。

在 MediaTransportControls 模板中,命令按钮包含在 CommandBar 元素中 命令栏具有主要命令和辅助命令的概念。 主要命令是默认情况下显示在控件中的按钮,并且始终可见(除非禁用该按钮、隐藏按钮或没有足够的空间)。 辅助命令显示在用户单击省略号 (...) 按钮时显示的溢出菜单中。 有关详细信息,请参阅 应用栏和命令栏 文章。

若要将元素从命令栏主命令移动到溢出菜单,需要编辑 XAML 控件模板。

将命令移动到“溢出”菜单:

  1. 在控件模板中,找到名为 MediaControlsCommandBar 的 CommandBar 元素。
  2. SecondaryCommands 节添加到 CommandBar 的 XAML。 将其置于 PrimaryCommands结束标记之后。
<CommandBar x:Name="MediaControlsCommandBar" ... >  
  <CommandBar.PrimaryCommands>
...
    <AppBarButton x:Name='PlaybackRateButton'
                    Style='{StaticResource AppBarButtonStyle}'
                    MediaTransportControlsHelper.DropoutOrder='4'
                    Visibility='Collapsed'>
      <AppBarButton.Icon>
        <FontIcon Glyph="&#xEC57;"/>
      </AppBarButton.Icon>
    </AppBarButton>
...
  </CommandBar.PrimaryCommands>
<!-- Add secondary commands (overflow menu) here -->
  <CommandBar.SecondaryCommands>
    ...
  </CommandBar.SecondaryCommands>
</CommandBar>
  1. 若要使用命令填充菜单,请将所需 AppBarButton 对象的 XAML 从 PrimaryCommand 剪切并粘贴到 SecondaryCommands。 在此示例中,我们将转到 PlaybackRateButton 溢出菜单。

  2. 将标签添加到按钮并删除样式信息,如下所示。 由于溢出菜单由文本按钮组成,因此必须将文本标签添加到按钮,并删除设置按钮高度和宽度的样式。 否则,它不会在溢出菜单中正确显示。

<CommandBar.SecondaryCommands>
    <AppBarButton x:Name='PlaybackRateButton'
                  Label='Playback Rate'>
    </AppBarButton>
</CommandBar.SecondaryCommands>

重要

你仍必须使按钮可见并启用它,才能在溢出菜单中使用它。 在此示例中,除非 IsPlaybackRateButtonVisible 属性为 true,否则 PlaybackRateButton 元素在溢出菜单中不可见。 除非 IsPlaybackRateEnabled 属性为 true,否则不会启用它。 设置这些属性显示在上一部分。

添加自定义按钮

你可能想要自定义 MediaTransportControls 的一个原因是向控件添加自定义命令。 无论是将其添加为主命令还是辅助命令,创建命令按钮和修改其行为的过程都是相同的。 在 媒体传输控件示例中,将“分级”按钮添加到主要命令。

添加自定义命令按钮

  1. 创建 AppBarButton 对象并将其添加到控件模板中的 CommandBar。
<AppBarButton x:Name="LikeButton"
              Icon="Like"
              Style="{StaticResource AppBarButtonStyle}"
              MediaTransportControlsHelper.DropoutOrder="3"
              VerticalAlignment="Center" />

必须在合适的位置将它添加到 CommandBar。 (有关详细信息,请参阅“使用溢出菜单”部分。它在 UI 中的位置取决于按钮在标记中的位置。 例如,如果希望该按钮在主要命令中显示为最后一个元素,请将其添加到主要命令列表的最末尾。

还可以自定义按钮的图标。 有关详细信息,请查看 AppBarButton 参考。

  1. 在 OnApplyTemplate 重写中,从模板获取按钮并为其 Click 事件注册处理程序。 此代码位于类中 CustomMediaTransportControls
public sealed class CustomMediaTransportControls :  MediaTransportControls
{
    // ...

    protected override void OnApplyTemplate()
    {
        // Find the custom button and create an event handler for its Click event.
        var likeButton = GetTemplateChild("LikeButton") as Button;
        likeButton.Click += LikeButton_Click;
        base.OnApplyTemplate();
    }

    //...
}
  1. 将代码添加到 Click 事件处理程序,以执行单击按钮时发生的操作。 下面是该类的完整代码。
public sealed class CustomMediaTransportControls : MediaTransportControls
{
    public event EventHandler< EventArgs> Liked;

    public CustomMediaTransportControls()
    {
        this.DefaultStyleKey = typeof(CustomMediaTransportControls);
    }

    protected override void OnApplyTemplate()
    {
        // Find the custom button and create an event handler for its Click event.
        var likeButton = GetTemplateChild("LikeButton") as Button;
        likeButton.Click += LikeButton_Click;
        base.OnApplyTemplate();
    }

    private void LikeButton_Click(object sender, RoutedEventArgs e)
    {
        // Raise an event on the custom control when 'like' is clicked.
        var handler = Liked;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}

修改滑块

MediaTransportControls 的“seek”控件由 Slider 元素提供。 自定义它的一种方法是更改搜寻行为的粒度。

默认查找滑块分为 100 个部分,因此搜寻行为仅限于该多个部分。 可以通过从 MediaPlayerElement.MediaPlayer 上的 MediaOpened 事件处理程序中的 XAML 可视化树获取滑块来更改查找滑块的粒度。 此示例演示如何使用 VisualTreeHelper 获取对滑块的引用,如果媒体超过 120 分钟,则将滑块的默认步骤频率从 1% 更改为 0.1% (1000 步骤)。 MediaPlayerElement 命名 MediaPlayerElement1

protected override void OnNavigatedTo(NavigationEventArgs e)
{
  MediaPlayerElement1.MediaPlayer.MediaOpened += MediaPlayerElement_MediaPlayer_MediaOpened;
  base.OnNavigatedTo(e);
}

private void MediaPlayerElement_MediaPlayer_MediaOpened(object sender, RoutedEventArgs e)
{
  FrameworkElement transportControlsTemplateRoot = (FrameworkElement)VisualTreeHelper.GetChild(MediaPlayerElement1.TransportControls, 0);
  Slider sliderControl = (Slider)transportControlsTemplateRoot.FindName("ProgressSlider");
  if (sliderControl != null && MediaPlayerElement1.NaturalDuration.TimeSpan.TotalMinutes > 120)
  {
    // Default is 1%. Change to 0.1% for more granular seeking.
    sliderControl.StepFrequency = 0.1;
  }
}