Crear controles de transporte personalizados

La clase MediaPlayerElement tiene controles de transporte de XAML personalizables para administrar el control del contenido de audio y vídeo dentro de una aplicación de Windows. Aquí te mostramos cómo personalizar la platilla MediaTransportControls. Le mostraremos cómo trabajar con el menú de desbordamiento, agregar un botón personalizado y modificar el control deslizante.

API importantes: MediaPlayerElement, MediaPlayerElement.AreTransportControlsEnabled, MediaTransportControls

Antes de empezar, debes estar familiarizado con las clases MediaPlayerElement y MediaTransportControls. Para obtener más información, consulta la guía de control de MediaPlayerElement.

Sugerencia

Los ejemplos de este tema se basan en la muestra de controles de transporte de contenido multimedia. Puedes descargar la muestra para ver y ejecutar el código completo.

Nota:

MediaPlayerElement solo está disponible en Windows 10, versión 1607 y posteriores. Si vas a desarrollar una aplicación para una versión anterior de Windows 10, tendrás que usar MediaElement en su lugar. Todos los ejemplos de esta página también funcionan con MediaElement.

¿Cuándo deberías personalizar la plantilla?

MediaPlayerElement tiene controles de transporte integrados que se han diseñado para funcionar adecuadamente sin modificaciones con la mayoría de las aplicaciones de reproducción de audio y vídeo. Los proporciona la clase MediaTransportControls e incluyen botones para reproducir, detener y navegar por medios, ajustar el volumen, alternar pantalla completa, convertir a un segundo dispositivo, habilitar subtítulos, cambiar pistas de audio y ajustar la velocidad de reproducción. MediaTransportControls cuenta con propiedades que permiten controlar si cada botón se muestra y se habilita. También puedes establecer la propiedad IsCompact para especificar si los controles se muestran en una o dos filas.

Sin embargo, puede haber escenarios donde tendrás que personalizar aún más personalizar el aspecto del control o cambiar su comportamiento. A continuación, se muestran algunos ejemplos:

  • Cambiar los iconos, el comportamiento de los controles deslizantes y los colores.
  • Mover los botones de comando que se usan con menos frecuencia a un menú de desbordamiento.
  • Cambiar el orden en que los comandos desaparecen cuando el control cambia de tamaño.
  • Proporcione un botón de comando que no esté en el conjunto predeterminado.

Nota:

Los botones que se muestran en la pantalla desaparecerán de los controles de transporte integrados en un orden predefinido si no hay suficiente espacio en la pantalla. Para cambiar este orden o colocar los comandos que no caben en un menú de desbordamiento, tienes que personalizar los controles.

Puedes personalizar el aspecto del control al modificar la plantilla predeterminada. Para modificar el comportamiento del control o agregar comandos nuevos, puedes crear un control personalizado derivado de MediaTransportControls.

Sugerencia

Las plantillas de control personalizables son una característica eficaz de la plataforma XAML, pero también hay consecuencias que deberías tener en cuenta. Al personalizar una plantilla, esta se convierte en un elemento estático de la aplicación y, por tanto, no recibirá ninguna actualización de plataforma que Microsoft realice en la plantilla. Si Microsoft realiza alguna actualización de la plantilla, se debería tomar la nueva plantilla y volver a modificarla para obtener las ventajas de la plantilla actualizada.

Estructura de la plantilla

ControlTemplate forma parte del estilo predeterminado. Puedes copiar este estilo predeterminado en el proyecto para modificarlo. ControlTemplate se divide en secciones similares a otras plantillas de control XAML.

  • La primera sección de la plantilla contiene las definiciones de Style para los distintos componentes de MediaTransportControls.
  • La segunda define los diversos estados visuales que usa MediaTransportControls.
  • En la tercera sección se incluye Grid, que contiene los distintos elementos MediaTransportControls juntos y define la distribución de los componentes.

Nota:

Para más información sobre cómo modificar las plantillas de control, consulta Plantillas de control. Puedes usar un editor de texto o editores similares en el IDE para abrir los archivos XAML en (Archivos de programa)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\(versión del SDK)\Generic. El estilo predeterminado y la plantilla para cada control se definen en el archivo generic.xaml. Puedes encontrar la plantilla MediaTransportControls en generic.xaml si buscas "MediaTransportControls".

En las siguientes secciones se muestra cómo personalizar muchos de los elementos principales de los controles de transporte:

  • Slider: permite que un usuario arrastre a través de sus elementos multimedia y también muestra el progreso.
  • CommandBar: contiene todos los botones. Para obtener más información, consulta la sección de anatomía del tema de referencia MediaTransportControls.

Personalizar los controles de transporte

Si solo quieres modificar la apariencia de MediaTransportControls, también puedes crear una copia del estilo de control predeterminado y la plantilla, y modificarlas. Sin embargo, si también quieres agregar o modificar la funcionalidad del control, debes crear una nueva clase que derive de MediaTransportControls.

Crear una nueva plantilla del control

Para personalizar la plantilla y el estilo predeterminados de MediaTransportControls

  1. Copia el estilo predeterminado de los estilos y plantillas de MediaTransportControls en un ResourceDictionary del proyecto.
  2. Asigna un valor x:Key a Style para identificarlo del modo siguiente.
<Style TargetType="MediaTransportControls" x:Key="myTransportControlsStyle">
    <!-- Style content ... -->
</Style>
  1. Agrega una clase MediaPlayerElement con MediaTransportControls a la interfaz de usuario.
  2. Establece la propiedad Style del elemento MediaTransportControls al recurso personalizado Style, tal como se muestra aquí.
<MediaPlayerElement AreTransportControlsEnabled="True">
    <MediaPlayerElement.TransportControls>
        <MediaTransportControls Style="{StaticResource myTransportControlsStyle}"/>
    </MediaPlayerElement.TransportControls>
</MediaPlayerElement>

Para obtener más información sobre cómo modificar estilos y plantillas, consulta Controles de estilos y Plantillas de control.

Crear un control derivado

Para agregar o modificar la funcionalidad de los controles de transporte, debes crear una nueva clase derivada de MediaTransportControls. Una clase derivada llamada CustomMediaTransportControls se muestra en la muestra de controles de transporte multimedia y los ejemplos restantes en esta página.

Para crear una nueva clase derivada de MediaTransportControls

  1. Agrega un nuevo archivo de clase al proyecto.
    • En Visual Studio, seleccione Project Add Class (Agregar clase).> Se abre el cuadro de diálogo Agregar nuevo elemento.
    • En el cuadro de diálogo Agregar nuevo elemento, escribe un nombre para el archivo de clase y haz clic en Agregar. (En la muestra de controles de transporte multimedia, la clase se denomina CustomMediaTransportControls).
  2. Modifica el código de clase que se debe derivar de la clase MediaTransportControls.
public sealed class CustomMediaTransportControls : MediaTransportControls
{
}
  1. Copia el estilo predeterminado de MediaTransportControls en ResourceDictionary del proyecto. Este es el estilo y la plantilla que modificas. (En la muestra de controles de transporte multimedia, se crea una nueva carpeta denominada "Themes" y se le agrega un archivo ResourceDictionary denominado generic.xaml).
  2. Cambia el TargetType del estilo al nuevo tipo de control personalizado. (En el ejemplo, TargetType se cambia a local:CustomMediaTransportControls).
xmlns:local="using:CustomMediaTransportControls">
...
<Style TargetType="local:CustomMediaTransportControls">
  1. Establece el valor DefaultStyleKey de la clase personalizada. Esto indica a la clase personalizada que debe usar Style con un TargetType de local:CustomMediaTransportControls.
public sealed class CustomMediaTransportControls : MediaTransportControls
{
    public CustomMediaTransportControls()
    {
        this.DefaultStyleKey = typeof(CustomMediaTransportControls);
    }
}
  1. Agrega una clase MediaPlayerElement al marcado XAML y agrégale los controles de transporte personalizados. Algo a tener en cuenta es que las API para ocultar, mostrar, deshabilitar y habilitar los botones predeterminados funcionan con una plantilla personalizada.
<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>

Ahora puedes modificar el estilo y la plantilla de control para actualizar el aspecto del control personalizado y el código de control para actualizar su comportamiento.

Trabajar con el menú de desbordamiento

Puedes mover los botones de comando de MediaTransportControls en un menú de desbordamiento para que los comandos menos usados queden ocultos hasta que el usuario los necesite.

En la plantilla MediaTransportControls, los botones de comando se encuentran en un elemento CommandBar. La barra de comandos tiene el concepto de comandos principales y secundarios. Los comandos principales son los botones que aparecen en el control de manera predeterminada y están siempre visibles (a menos que deshabilites u ocultes el botón o no haya suficiente lugar). Los comandos secundarios se muestran en un menú de desbordamiento que aparece cuando un usuario hace clic en el botón de puntos suspensivos (…). Para obtener más información, consulta el artículo sobre barras de la aplicación y barras de comandos.

Para mover un elemento de los comandos principales de la barra de comandos al menú de desbordamiento, tienes que editar la plantilla de control XAML.

Para mover un comando al menú de desbordamiento:

  1. En la plantilla de control, busca el elemento CommandBar denominado MediaControlsCommandBar.
  2. Agrega una sección SecondaryCommands al código XAML para CommandBar. Colócala después de la etiqueta de cierre 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. Para rellenar el menú con los comandos, corta y pega el código XAML de los objetos AppBarButton deseados de PrimaryCommands a SecondaryCommands. En este ejemplo, movemos el PlaybackRateButton al menú de desbordamiento.

  2. Agrega una etiqueta al botón y quita la información de estilo, tal como se muestra aquí. Dado que el menú de desbordamiento se compone de botones de texto, tienes que agregar una etiqueta de texto al botón y también quitar el estilo que establece el alto y ancho del botón. De lo contrario, no aparecerá correctamente en el menú de desbordamiento.

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

Importante

Aún puedes hacer que el botón sea visible y se pueda habilitar para poder usarlo en el menú de desbordamiento. En este ejemplo, el elemento PlaybackRateButton no está visible en el menú de desbordamiento, a menos que la propiedad IsPlaybackRateButtonVisible sea true. No se habilita, a menos que la propiedad IsPlaybackRateEnabled sea true. El establecimiento de estas propiedades se muestra en la sección anterior.

Agregar un botón personalizado

Una razón por la que quizás quieras personalizar MediaTransportControls es para agregar un comando personalizado al control. Ya sea para agregarlo como un comando principal o secundario, el procedimiento para crear el botón de comando y modificar su comportamiento es el mismo. En la muestra de controles de transporte multimedia, se agrega un botón "rating" a los comandos principales.

Para agregar un botón de comando personalizado

  1. Crea un objeto AppBarButton y agrégalo a CommandBar de la plantilla de control.
<AppBarButton x:Name="LikeButton"
              Icon="Like"
              Style="{StaticResource AppBarButtonStyle}"
              MediaTransportControlsHelper.DropoutOrder="3"
              VerticalAlignment="Center" />

Debes agregarlo a CommandBar en la ubicación adecuada. (Para obtener más información, consulta la sección Trabajar con el menú de desbordamiento). La posición que ocupa en la interfaz de usuario la determina el lugar donde se encuentra el botón en el marcado. Por ejemplo, si quieres que este botón aparezca como el último elemento en los comandos principales, agrégalo al final de la lista de comandos principal.

También puedes personalizar el icono del botón. Para obtener más información, consulta la referencia AppBarButton.

  1. En la invalidación de OnApplyTemplate, obtén el botón a partir de la plantilla y registra un controlador para su evento Click. Este código se coloca en la clase 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. Agrega código al controlador de eventos "Click" para realizar la acción que ocurre cuando se hace clic en el botón. Este es el código completo para la clase.
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);
        }
    }
}

Modificar el control deslizante

Un elemento Slider proporciona el control "seek" de MediaTransportControls. Una manera de personalizarlo es cambiando la granularidad del comportamiento de búsqueda.

El control deslizante de búsqueda predeterminado se divide en 100 partes, por lo que el comportamiento de búsqueda se limita a ese número de secciones. Puedes cambiar la granularidad del control deslizante de búsqueda al obtener el elemento Slider del árbol visual de XAML de tu controlador de eventos MediaOpened en MediaPlayerElement.MediaPlayer. En este ejemplo se muestra cómo usar VisualTreeHelper para obtener una referencia a Slider y luego cambiar la frecuencia de paso predeterminado del control deslizante del 1 % al 0,1 % (1000 pasos) si el contenido multimedia tiene más de 120 minutos. MediaPlayerElement se denomina 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;
  }
}