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 各元件的 樣式 定義。
- 第二節定義了 MediaTransportControls 所使用的各種視覺狀態。
- 第三區包含將多個 MediaTransportControls 元素連結在一起的 網格 ,並定義元件的佈局方式。
備註
欲了解更多修改範本的資訊,請參見控制範本。 你可以在 IDE 中使用文字編輯器或類似編輯器,打開 (Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\(SDK 版本)\Generic 裡的 XAML 檔案。 每個控制項的預設樣式與範本定義於 generic.xaml 檔案中。 你可以在 generic.xaml 搜尋「MediaTransportControls」找到 MediaTransportControls 範本。
在接下來的章節中,你會學習如何自訂運輸控制的幾個主要元素:
- 滑桿:允許使用者瀏覽媒體並顯示進度
- CommandBar:包含所有按鍵。 欲了解更多資訊,請參閱 MediaTransportControls 參考主題中的解剖學章節。
自訂傳輸控制
如果你只想修改 MediaTransportControls 的外觀,可以建立預設控制樣式和範本的副本,然後修改它。 不過,如果你也想新增或修改控制項的功能,就需要建立一個源自 MediaTransportControls 的新類別。
重新模板化控制
自訂 MediaTransportControls 預設樣式與範本
- 將 MediaTransportControls 的預設樣式與範本複製到專案中的 ResourceDictionary。
- 給風格一個 x:Key 值來識別它,就像這樣。
<Style TargetType="MediaTransportControls" x:Key="myTransportControlsStyle">
<!-- Style content ... -->
</Style>
- 在你的介面中新增一個帶有 MediaTransportControls 的 MediaPlayerElement。
- 將 MediaTransportControls 元素的 Style 屬性設為你自訂的 Style 資源,如圖所示。
<MediaPlayerElement AreTransportControlsEnabled="True">
<MediaPlayerElement.TransportControls>
<MediaTransportControls Style="{StaticResource myTransportControlsStyle}"/>
</MediaPlayerElement.TransportControls>
</MediaPlayerElement>
欲了解更多修改樣式與範本的資訊,請參閱「樣式控制項」和「控制項範本」。
建立導出控制項
若要新增或修改傳輸控制的功能,您必須建立一個源自 MediaTransportControls 的新類別。 一個衍生類別稱為 CustomMediaTransportControls ,已在 媒體傳輸控制範例 及本頁其他範例中展示。
建立一個由 MediaTransportControls 衍生的新類別
- 為你的專案新增一個類別檔案。
- 在 Visual Studio 中,選擇專案 > 新增類別。 新增物品對話框會打開。
- 在新增項目對話框中,輸入類別檔案名稱,然後點選新增。 (在 Media Transport Controls 範例中,該類別被命名
CustomMediaTransportControls為 。)
- 修改類別程式碼,使其衍生自 MediaTransportControls 類別。
public sealed class CustomMediaTransportControls : MediaTransportControls
{
}
- 將 MediaTransportControls 的預設樣式複製到你的專案中的 ResourceDictionary 。 這就是你要修改的樣式和範本。 (在 Media Transport Controls 範例中,會建立一個名為「Themes」的新資料夾,並新增一個名為 generic.xaml 的 ResourceDictionary 檔案。)
- 將樣式的 TargetType 改成新的自訂控制類型。 (在範例中,TargetType 會被改為
local:CustomMediaTransportControls。)
xmlns:local="using:CustomMediaTransportControls">
...
<Style TargetType="local:CustomMediaTransportControls">
- 設定你自訂類別的 DefaultStyleKey 。 這會告訴你的自訂類別使用帶有 TargetType 的
local:CustomMediaTransportControlsStyle。
public sealed class CustomMediaTransportControls : MediaTransportControls
{
public CustomMediaTransportControls()
{
this.DefaultStyleKey = typeof(CustomMediaTransportControls);
}
}
- 在你的 XAML 標記中加入 MediaPlayerElement ,並加入自訂傳輸控制。 要注意的是,用於隱藏、顯示、停用和啟用預設按鈕的 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 元素中。 指令列有主指令與次指令的概念。 主要指令是預設出現在控制鍵中且永遠可見的按鈕(除非你關閉按鈕、隱藏按鈕或空間不足)。 次要指令會在使用者點擊省略號(...)按鈕時出現的溢出選單中顯示。 更多資訊請參閱 應用程式欄與指令欄 文章。
要將元素從指令列的主要指令移到 overflow 選單,你需要編輯 XAML 控制範本。
要將指令移到溢出選單:
- 在控制範本中,找到名為
MediaControlsCommandBar的 CommandBar 元素。 - 在 XAML 中新增一個 CommandBar 的 SecondaryCommands 區塊。 把它放在 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 屬性成立,否則 PlaybackRateButton 元素在溢位選單中不會顯示。 除非 IsPlaybackRateEnabled 屬性為真,否則它不會被啟用。 設定這些屬性的方法已在前一節說明。
新增自訂按鈕
你可能想自訂 MediaTransportControls 的一個原因是,在控制項中加入自訂指令。 無論你把它當作主要指令還是次要指令,建立指令按鈕並修改其行為的流程都是一樣的。 在 媒體傳輸控制範例中,主要指令中加入了一個「評分」按鈕。
新增自訂指令按鈕
- 建立一個 AppBarButton 物件,並加入控制範本中的 CommandBar。
<AppBarButton x:Name="LikeButton"
Icon="Like"
Style="{StaticResource AppBarButtonStyle}"
MediaTransportControlsHelper.DropoutOrder="3"
VerticalAlignment="Center" />
你必須在 CommandBar 中的適當位置新增。 (更多資訊請參閱「與溢出選單合作」章節。)它在 UI 中的位置取決於按鈕在標記中的位置。 例如,如果你想讓這個按鈕出現在主要指令的最後一個元素,就把它加在主要指令列表的最後。
你也可以自訂按鈕的圖示。 欲了解更多資訊,請參閱 AppBarButton 參考資料。
- 在 OnApplyTemplate 覆寫中,從範本取得按鈕,並為其 點擊 事件註冊一個處理程式。 這段程式碼會放在
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();
}
//...
}
- 在點擊事件處理程序中加入程式碼,以執行按鈕被點擊時發生的動作。 這是這門課的完整程式碼。
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 的「搜索」控制由 滑桿 元件提供。 你可以自訂的一種方式是改變尋覓行為的細緻度。
預設的尋道滑桿被分成 100 個部分,因此尋道行為限制在這幾個區塊。 你可以透過 MediaOpened 事件處理程式從 XAML 視覺樹獲取滑桿,來調整 MediaPlayerElement.MediaPlayer 的尋求滑桿的細緻度。 這個範例展示了如何使用 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;
}
}