カスタム トランスポート コントロール

MediaPlayerElement には、Windows アプリ内でオーディオおよびビデオ コンテンツのコントロールを管理するためのカスタマイズ可能な XAML トランスポート コントロールがあります。 ここでは、MediaTransportControls テンプレートをカスタマイズする方法を示します。 オーバーフロー メニューの操作方法、カスタム ボタンの追加方法、スライダーの変更方法について説明します。

重要な API: MediaPlayerElementMediaPlayerElement.AreTransportControlsEnabledMediaTransportControls

開始する前に、MediaPlayerElement クラスと MediaTransportControls クラスについて理解しておく必要があります。 詳細については、MediaPlayerElement コントロール ガイドを参照してください。

ヒント

このトピックの例は、 Media トランスポート コントロールのサンプルに基づいています。 サンプルをダウンロードして、完成したコードを表示して実行できます。

Note

MediaPlayerElement は、Windows 10 バージョン 1607 以降でのみ使用できます。 以前のバージョンの Windows 10 用のアプリを開発する場合は、代わりに MediaElement を使用する必要があります。 このページのすべての例は、 MediaElement でも動作します。

テンプレートをカスタマイズする必要があるタイミング

MediaPlayerElement には、ほとんどのビデオおよびオーディオ再生アプリで変更を加えることなく適切に動作するように設計されたトランスポート コントロールが組み込まれています。 これらは、MediaTransportControls クラスによって提供され、再生、停止、メディアのナビゲーション、音量の調節、全画面表示の切り替え、2 台目のデバイスへのキャスト、字幕の有効化、オーディオ トラックの切り替え、再生速度の調整を行うためのボタンが含まれています。 MediaTransportControls には、各ボタンを表示および有効にするかどうかを制御できるプロパティがあります。 IsCompact プロパティを設定して、コントロールを 1 行または 2 行に表示するかどうかを指定することもできます。

ただし、コントロールの外観をさらにカスタマイズしたり、その動作を変更したりする必要があるシナリオもあります。 次に例をいくつか示します。

  • アイコン、スライダーの動作、色を変更します。
  • 使用頻度の低いコマンド ボタンをオーバーフロー メニューに移動します。
  • コントロールのサイズを変更するときにコマンドがドロップアウトする順序を変更します。
  • 既定のセットには含まれていないコマンド ボタンを提供する。

Note

画面に表示されるボタンは、画面上に十分な領域がない場合、定義済みの順序で組み込みのトランスポート コントロールから削除されます。 この順序を変更したり、オーバーフロー メニューに収まらないコマンドを配置したりするには、コントロールをカスタマイズする必要があります。

既定のテンプレートを変更することで、コントロールの外観をカスタマイズできます。 コントロールの動作を変更したり、新しいコマンドを追加したりするには、MediaTransportControls から派生したカスタム コントロールを作成します。

ヒント

カスタマイズ可能なコントロール テンプレートは XAML プラットフォームの強力な機能ですが、考慮する必要がある結果もあります。 テンプレートをカスタマイズすると、アプリの静的な部分になるため、Microsoft によってテンプレートに対して行われたプラットフォーム更新プログラムは受け取りません。 テンプレートの更新が Microsoft によって行われる場合は、新しいテンプレートを取得し、更新されたテンプレートの利点を得るために変更し直す必要があります。

テンプレートの構造

ControlTemplate は既定のスタイルの一部です。 この既定のスタイルをプロジェクトにコピーして変更できます。 ControlTemplate は、他の XAML コントロール テンプレートと同様のセクションに分かれています。

  • テンプレートの最初のセクションには、MediaTransportControls のさまざまなコンポーネントの Style 定義が含まれています。
  • 2 番目のセクションでは、MediaTransportControls で使用されるさまざまな表示状態を定義します。
  • 3 番目のセクションには、さまざまな MediaTransportControls 要素を一緒に保持しコンポーネントのレイアウト方法を定義するGrid が含まれています。

Note

テンプレートの変更の詳細については、「 Control テンプレート」を参照してください。 テキスト エディターか、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 プロパティをカスタム Style リソースに設定します。
<MediaPlayerElement AreTransportControlsEnabled="True">
    <MediaPlayerElement.TransportControls>
        <MediaTransportControls Style="{StaticResource myTransportControlsStyle}"/>
    </MediaPlayerElement.TransportControls>
</MediaPlayerElement>

スタイルとテンプレートの変更の詳細については、「 コントロール および Control テンプレートを参照してください。

派生コントロールを作成する

トランスポート コントロールの機能を追加または変更するには、MediaTransportControls から派生した新しいクラスを作成する必要があります。 CustomMediaTransportControlsと呼ばれる派生クラスは、Media トランスポート コントロールのサンプルとこのページの残りの例に示されています。

MediaTransportControls から派生した新しいクラスを作成するには

  1. プロジェクトに新しいクラス ファイルを追加します。
    • Visual Studio で、[プロジェクト] > [クラスの追加] の順に選択します。 [新しい項目の追加] ダイアログが開きます。
    • [新しい項目の追加] ダイアログで、クラス ファイルの名前を入力し、[追加] をクリックします。 (メディア トランスポート コントロールのサンプルでは、クラスの名前は CustomMediaTransportControls です)。
  2. MediaTransportControls クラスから派生するようにクラス コードを変更します。
public sealed class CustomMediaTransportControls : MediaTransportControls
{
}
  1. MediaTransportControls の既定のスタイルをプロジェクトの ResourceDictionary にコピーします。 これは、変更するスタイルとテンプレートです。 (メディア トランスポート コントロールのサンプルでは、"Themes" という名前の新しいフォルダーが作成され、generic.xaml という ResourceDictionary ファイルが追加されます)。
  2. スタイルの TargetType を新しいカスタム コントロール型に変更します。 (このサンプルでは、TargetType が local:CustomMediaTransportControls に変更されています)。
xmlns:local="using:CustomMediaTransportControls">
...
<Style TargetType="local:CustomMediaTransportControls">
  1. カスタム クラスの DefaultStyleKey を設定します。 これにより、 local:CustomMediaTransportControlsの TargetType で Style を使用するようにカスタム クラスに指示します。
public sealed class CustomMediaTransportControls : MediaTransportControls
{
    public CustomMediaTransportControls()
    {
        this.DefaultStyleKey = typeof(CustomMediaTransportControls);
    }
}
  1. XAML マークアップに MediaPlayerElement を追加し、それにカスタム トランスポート コントロールを追加します。 注意すべき点の 1 つは、既定のボタンを非表示、表示、無効化、有効化する 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. CommandBar の XAML に SecondaryCommands セクションを追加します。 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. メニューにコマンドを設定するには、PrimaryCommands から SecondaryCommands に、目的の AppBarButton オブジェクトの XAML を切り取って貼り付けます。 この例では、 PlaybackRateButton をオーバーフロー メニューに移動します。

  2. 次に示すように、ボタンにラベルを追加し、スタイル情報を削除します。 オーバーフロー メニューはテキスト ボタンで構成されているため、ボタンにテキスト ラベルを追加し、ボタンの高さと幅を設定するスタイルも削除する必要があります。 そうしないと、オーバーフロー メニューに正しく表示されません。

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

重要

ボタンをオーバーフロー メニューで使用するには、ボタンを表示して有効にする必要があります。 この例では、IsPlaybackRateButtonVisible プロパティが true でない限り、PlaybackRateButton 要素はオーバーフロー メニューに表示されません。 IsPlaybackRateEnabled プロパティが true でない限り、有効になりません。 これらのプロパティの設定は、前のセクションで示されています。

カスタム ボタンの追加

MediaTransportControls をカスタマイズする理由の 1 つは、コントロールにカスタム コマンドを追加することです。 プライマリ コマンドとして追加する場合も、セカンダリ コマンドとして追加する場合も、コマンド ボタンを作成してその動作を変更する手順は同じです。 Media トランスポート コントロールのサンプルでは、プライマリ コマンドに "評価" ボタンが追加されます。

カスタム コマンド ボタンを追加するには

  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 要素によって提供されます。 これをカスタマイズする 1 つの方法は、シーク動作の粒度を変更することです。

既定のシーク スライダーは 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;
  }
}