MediaPlayerElement 具有可自訂的 XAML 媒體控制元件,用於管理 Windows 應用程式內的音訊和視訊內容。 在這裡,我們將示範如何自定義 MediaTransportControls 範本。 我們將示範如何使用溢位功能表、新增自訂按鈕並修改滑桿。
重要 API: MediaPlayerElement、 MediaPlayerElement.AreTransportControlsEnabled、 MediaTransportControls
開始之前,您應該先熟悉 MediaPlayerElement 和 MediaTransportControls 類別。 如需詳細資訊,請參閱 MediaPlayerElement 控件指南。
小提示
本主題中的範例是以 媒體傳輸控件範例為基礎。 您可以下載範例來檢視並執行已完成的程式代碼。
備註
MediaPlayerElement 僅適用於 Windows 10 版本 1607 和更新版本。 如果您要開發舊版 Windows 10 的應用程式,您必須改用 MediaElement 。 此頁面上的所有範例也都使用 MediaElement 。
何時應該自定義範本?
MediaPlayerElement 具有內建的傳輸控件,其設計目的是在大部分的視訊和音訊播放應用程式中都能夠順利運作。 它們是由 MediaTransportControls 類別提供,並包含播放、停止和瀏覽媒體、調整音量、切換全螢幕、轉換成第二個裝置、啟用輔助字幕、切換曲目,以及調整播放速率的按鈕。 MediaTransportControls 具有屬性,可讓您控制是否顯示並啟用每個按鈕。 您也可以設定 IsCompact 屬性,以指定控制項是否顯示在一個資料列或兩個數據列中。
不過,在某些情況下,您可能需要進一步自定義控件的外觀或變更其行為。 以下是一些範例:
- 變更圖示、滑桿行為和色彩。
- 將較不常用的命令按鈕移至溢位功能表。
- 在控制項調整大小時,變更卸除命令的順序。
- 提供不是在預設組中的指令按鈕。
備註
如果螢幕上沒有足夠的空間,螢幕上顯示的按鈕將會以預先定義的順序去除內建傳輸控制。 若要變更此排序或放置不符合溢位功能表的命令,您必須自定義控件。
您可以修改預設範本來自定義控制件的外觀。 若要修改控件的行為或新增命令,您可以建立衍生自 MediaTransportControls 的自定義控件。
小提示
可自定義的控件範本是 XAML 平台的強大功能,但也有您應該考慮的結果。 當您自定義範本時,它會成為您應用程式的靜態部分,因此不會收到由Microsoft對範本所做的任何平臺更新。 如果Microsoft進行範本更新,您應該採用新的範本並重新修改,以取得更新範本的優點。
範本結構
ControlTemplate 是預設樣式的一部分。 您可以將此預設樣式複製到專案以修改它。 ControlTemplate 分成類似其他 XAML 控件範本的區段。
- 範本的第一個區段包含 MediaTransportControls 各種元件的 Style 定義。
- 第二個區段會定義 MediaTransportControls 所使用的各種視覺狀態。
- 第三個區段包含 Grid,其中 保存著各種 MediaTransportControls 元素,並定義元件配置的方式。
備註
如需修改範本的詳細資訊,請參閱 控制範本。 您可以使用 IDE 中的文本編輯器或類似編輯器,在 [程序檔]\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\(SDK 版本)\Generic 中開啟 XAML 檔案。 每個控件的預設樣式和範本都會定義在 generic.xaml 檔案中。 您可以搜尋 “MediaTransportControls”,在 generic.xaml 中找到 MediaTransportControls 範本。
在下列各節中,您將瞭解如何自定義傳輸控件的數個主要元素:
- 進度滑桿:允許使用者快速瀏覽其媒體,並顯示進度。
- CommandBar:包含所有按鈕。 如需詳細資訊,請參閱 MediaTransportControls 參考主題的剖析一節。
自定義傳輸控制件
如果您只想要修改 MediaTransportControls 的外觀,您可以建立預設控件樣式和範本的複本,並加以修改。 不過,如果您也想要新增或修改控件的功能,您需要建立衍生自 MediaTransportControls 的新類別。
重新設計控制元件的模板
自訂 MediaTransportControls 的預設樣式和模板
- 將預設樣式從 MediaTransportControls 樣式和範本複製到專案中的 ResourceDictionary。
- 為 Style 提供 x:Key 值來識別它,如下所示。
<Style TargetType="MediaTransportControls" x:Key="myTransportControlsStyle">
<!-- Style content ... -->
</Style>
- 將 MediaPlayerElement 與 MediaTransportControls 新增至您的 UI。
- 將 MediaTransportControls 元素的 Style 屬性設定為自定義 Style 資源,如下所示。
<MediaPlayerElement AreTransportControlsEnabled="True">
<MediaPlayerElement.TransportControls>
<MediaTransportControls Style="{StaticResource myTransportControlsStyle}"/>
</MediaPlayerElement.TransportControls>
</MediaPlayerElement>
如需有關修改控制項樣式和範本的詳細資訊,請參閱 控制項樣式 和 控制項範本。
建立衍生控件
若要新增或修改傳輸控件的功能,您必須建立衍生自 MediaTransportControls 的新類別。
媒體傳輸控制範例中會顯示一個名為 CustomMediaTransportControls
的衍生類別,以及此頁面上的其餘範例。
建立衍生自 MediaTransportControls 的新類別
- 將新的類別檔案新增至您的專案。
- 在 Visual Studio 中,選取 [專案 > 新增類別]。 [新增項目] 對話框隨即開啟。
- 在 [新增專案] 對話框中,輸入類別檔案的名稱,然後按兩下[新增]。 (在媒體傳輸控制項範例中,類別名為
CustomMediaTransportControls
。)
- 修改類別程序代碼,以衍生自 MediaTransportControls 類別。
public sealed class CustomMediaTransportControls : MediaTransportControls
{
}
- 將 MediaTransportControls 的預設樣式複製到你的專案中的 ResourceDictionary。 這是您修改的樣式和範本。 (在媒體傳輸控件範例中,會建立名為 “Themes” 的新資料夾,並將名為 generic.xaml 的 ResourceDictionary 檔案新增至其中。
- 將樣式的 TargetType 變更為新的自定義控件類型。 (在範例中,TargetType 已變更為
local:CustomMediaTransportControls
。)
xmlns:local="using:CustomMediaTransportControls">
...
<Style TargetType="local:CustomMediaTransportControls">
- 設定自定義類別 DefaultStyleKey。 這會告知您的自定義類別使用一個目標類型為
local:CustomMediaTransportControls
的 Style。
public sealed class CustomMediaTransportControls : MediaTransportControls
{
public CustomMediaTransportControls()
{
this.DefaultStyleKey = typeof(CustomMediaTransportControls);
}
}
- 將 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 控制項範本。
若要將命令移至溢位功能表:
- 在控件範本中,尋找名為 的
MediaControlsCommandBar
CommandBar 元素。 - 將 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=""/>
</AppBarButton.Icon>
</AppBarButton>
...
</CommandBar.PrimaryCommands>
<!-- Add secondary commands (overflow menu) here -->
<CommandBar.SecondaryCommands>
...
</CommandBar.SecondaryCommands>
</CommandBar>
若要將命令填入功能表,請從 PrimaryCommands 剪下所需的 AppBarButton 物件的 XAML,然後貼到 SecondaryCommands。 在此範例中,我們會將
PlaybackRateButton
移至隱藏選單。將標籤新增至按鈕並移除樣式資訊,如下所示。 由於溢位功能表是由文字按鈕所組成,因此您必須將文字標籤新增至按鈕,並移除設定按鈕高度和寬度的樣式。 否則,它不會出現在溢位功能表中。
<CommandBar.SecondaryCommands>
<AppBarButton x:Name='PlaybackRateButton'
Label='Playback Rate'>
</AppBarButton>
</CommandBar.SecondaryCommands>
這很重要
您仍然必須讓按鈕顯示並加以啟用,才能在溢位功能表中使用它。 在此範例中,除非IsPlaybackRateButtonVisible 屬性為 true,否則在溢位功能表中看不到 PlaybackRateButton 元素。 除非IsPlaybackRateEnabled屬性為 true,否則不會啟用。 設定這些屬性會顯示在上一節中。
新增自訂按鈕
您可能想要自定義 MediaTransportControls 的其中一個原因是將自定義命令新增至控件。 無論您是將它新增為主要命令或次要命令,建立命令按鈕和修改其行為的程式都相同。 在 媒體傳輸控件範例中,會將 [評等] 按鈕新增至主要命令。
若要新增自定義命令按鈕
- 建立 AppBarButton 物件,並將其新增至控件範本中的 CommandBar。
<AppBarButton x:Name="LikeButton"
Icon="Like"
Style="{StaticResource AppBarButtonStyle}"
MediaTransportControlsHelper.DropoutOrder="3"
VerticalAlignment="Center" />
您必須將它新增至 CommandBar 的適當位置。 (如需詳細資訊,請參閱使用溢出選單一節。)在 UI 中的位置是由按鈕在標記中的位置決定的。 例如,如果您希望此按鈕顯示為主要命令的最後一個項目,請將它添加到主要命令清單的最後。
您也可以自訂按鈕的圖示。 如需詳細資訊,請參閱 AppBarButton 參考資料。
- 在 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();
}
//...
}
- 將程式代碼新增至 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.MediaPlayerMediaPlayerElement1
。
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;
}
}