다음을 통해 공유


사용자 지정 전송 컨트롤 만들기

MediaPlayerElement에는 Windows 앱 내에서 오디오 및 비디오 콘텐츠의 제어를 관리하는 사용자 지정 가능한 XAML 전송 컨트롤이 있습니다. 여기서는 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 요소를 함께 보관하고 구성 요소가 배치되는 방법을 정의하는 Grid 가 포함되어 있습니다.

비고

템플릿 수정에 대한 자세한 내용은 컨트롤 템플릿을 참조하세요. IDE의 텍스트 편집기 또는 유사한 편집기를 사용하여 (Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\(SDK version)\Generic에서 XAML 파일을 열 수 있습니다. 각 컨트롤의 기본 스타일 및 템플릿은 generic.xaml 파일에 정의되어 있습니다. "MediaTransportControls"를 검색하여 generic.xaml에서 MediaTransportControls 템플릿을 찾을 수 있습니다.

다음 섹션에서는 전송 컨트롤의 몇 가지 주요 요소를 사용자 지정하는 방법을 알아봅니다.

  • 슬라이더: 사용자가 미디어를 스크러빙하고 진행률을 표시할 수 있습니다.
  • 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>

스타일 및 템플릿 수정에 대한 자세한 내용은 스타일 지정 컨트롤컨트롤 템플릿을 참조하세요.

파생 컨트롤 만들기

전송 컨트롤의 기능을 추가하거나 수정하려면 MediaTransportControls에서 파생된 새 클래스를 만들어야 합니다. CustomMediaTransportControls라는 파생 클래스는 Media Transport Controls 샘플과 이 페이지의 나머지 예제에서 보여집니다.

MediaTransportControls에서 파생된 새 클래스를 만들려면

  1. 프로젝트에 새 클래스 파일을 추가합니다.
    • Visual Studio에서 프로젝트 > 클래스 추가를 선택합니다. 새 항목 추가 대화 상자가 열립니다.
    • 새 항목 추가 대화 상자에서 클래스 파일의 이름을 입력한 다음 추가를 클릭합니다. (Media Transport Controls 샘플에서 클래스 이름은 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 를 설정합니다. 사용자 지정 클래스가 local:CustomMediaTransportControls의 TargetType을 가진 스타일을 사용하도록 지시합니다.
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. 컨트롤 템플릿에서 이름이 인 MediaControlsCommandBarCommandBar 요소를 찾습니다.
  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. 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.MediaPlayerMediaOpened 이벤트 처리기의 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;
  }
}