Using Live Visual Tree and Live Property Explorer to customize the Media Player (XAML, C#)

In this series of tutorials on how to customize your MediaPlayer, we have seen how to customize a button in part I. Now we will see how we can use Live Visual Tree and Live Property to make our lives easier when we are trying to design our MediaPlayer element.

All of the code can be found on Github here

Before we had no way to edit elements on the fly, we had to imagine what would happen when we changed a property like Margin, Height, Color, BrushThickness etc. Web developers have tons of tools like Firebug for Firefox, Chrome Tools for Chrome and Developer Tools for Edge and IE that allow them to do this, so why not us? The developing gods (Microsoft in our case) have answered our call and have given us the Live Visual Tree and Live Property Explorer tools which address exactly these issues. I will talk about these two elements and how they can help us develop better and faster.

In this tutorial we will implement and design a custom control that will be shown when the video has finished playing. The user will be able to rate the video using this control and we will also move the PlayPauseButton to the bottom left using Live Visual Tree and Live Property Explorer.

This tutorial will cover:

  1. What the Live Visual Tree and Live Property Explorer components are, how to use them, and why they are great tools
  2. How to use these tools to speed up your development
  3. How to add a control to the MediaPlayer that users can interact with
  4. How to move an element in the MediaPlayer control

The final version of our player will have:

  • A custom element in which users can rate the video. This element will have three different buttons (like, neutral, dislike), which will be shown at the end of the video.
  • These three buttons will have different actions (rate the video).
  • A PlayPauseButton that have been moved and re-sized.

or in other words:
Final player

Let's get started, I will assume that you have:

  1. Windows OS ;)
  2. Visual Studio 2015 (here) installed
  3. Media Player Framework vsix installed.
  4. Setting (downloading and referencing) a theme to the MediaPlayer, in this example I will be using Entertainment.xaml template theme.

Live Visual Tree and Live Property Explorer

This new tool will speed up your development as you no longer not need to reload the application every time you change something, thanks to Live Property Explorer. You can find Live Visual Tree under: DEBUG -> WINDOWS -> Live Visual Tree and Live property Explorer under the same path.

Like you can see here:
http://i.imgur.com/n3KxZea.png

Live Visual Tree on the right and the Live Property Explorer on the left:
http://i.imgur.com/hIbMjwy.png

You can see that Live Visual Tree provides information about the number of XAML elements inside each container (here we can see that we have a Grid, a StackPanel and more). Live Visual Tree will show only visible elements, and when an element changes from one state to another you can see that Live Visual Tree is changing at runtime which is very helpful (and AWESOME).

Live Property Explorer shows default values for properties, values which were inherited from other controls and the local values of control properties. You can modify local values, here for example we could choose to change the StackPanel HorizontalAlignment=center to Left and we could change VerticalAlignment="Top" to Bottom and the effects would be taken into account without having to reload the app.

As you can see here:
http://i.imgur.com/syJnaBx.png

Live Visual Tree and Live Property Explorer are two great tools that will help you speed up your development time since you will no longer need to recompile your application every time you wish to try a new design or version of a design.

Creating a custom control that will be implemented in the media player element.

(In this part I will not go over how to copy the theme template into the player, for more information on this please read part I).

First we will create a Windows 10 application with the MvvmLight Framework:
MvvmLight

If you don't have MvvmLight, I can only highly recommend it to you download here.

Now that we have created a Windows 10 application, we will need to create the custom control, for this example I will create a folder called Contrls and add a UserControl called RateMyVideoControl. (We deliberately do not name the folder Controls, to avoid namespace clashes).

Now we create a Grid element with 3 columns in which we will have 3 images: up vote, neutral vote and down vote. These 3 buttons will be linked to a Command property which will show a different message to the user depending on which button is clicked.

Here is the code for the UserControl :

  <StackPanel>
    <TextBlock 
        FontSize="32"
        Margin="10"
        Text="Did you like this video?"/>

    <Grid Height="70">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.3*" />
            <ColumnDefinition Width="0.3*" />
            <ColumnDefinition Width="0.3*" />
        </Grid.ColumnDefinitions>


        <Button Grid.Column="0" 
            Command="{Binding UpVoteCommand}"
            VerticalAlignment="Center"
            HorizontalAlignment="Center"
            >
            <Image Source="/Assets/up.png"></Image>
        </Button>

        <Button Grid.Column="1" 
             VerticalAlignment="Center"
            HorizontalAlignment="Center"
            Command="{Binding NeutralVoteCommand}"
            >
            <Image Source="/Assets/Neutral.png"></Image>
        </Button>

        <Button Grid.Column="2" 
             VerticalAlignment="Center"
            HorizontalAlignment="Center"
            Command="{Binding DownVoteCommand}"
            >
            <Image Source="/Assets/down.png"></Image>
        </Button>
    </Grid>
</StackPanel>  

Next we add these RelayCommands to our MainViewModel file so that the binding can happen:

 public RelayCommand UpVoteCommand
{
    get
    {
        return new RelayCommand(async () =>
        {
            var dialog = ServiceLocator.Current.GetInstance<IDialogService>();
            await dialog.ShowMessage("Custom Player", "Up Voted.");

            //TODO: add more logic here
        });
    }
}

public RelayCommand NeutralVoteCommand  
{
    get
    {
        return new RelayCommand(async () =>
        {
            var dialog = ServiceLocator.Current.GetInstance<IDialogService>();
            await dialog.ShowMessage("Custom Player", "Neutral Voted.");

            //TODO: add more logic here
        });
    }
}

public RelayCommand DownVoteCommand  
{
    get
    {
        return new RelayCommand(async () =>
        {
            var dialog = ServiceLocator.Current.GetInstance<IDialogService>();
            await dialog.ShowMessage("Custom Player", "Down Voted.");

            //TODO: add more logic here
        });
    }
}

In your IDE you should have a control that looks like this:
Video with rate me

Now using Live Visual Tree we will look into the MediaPlayer to see where we can place this component so that the user can see it once the video has ended.
LVT We can see that in the InteractivityContainer element we have a Border element that holds all of the controls for the player. This looks like a good place to set our own control. We will then insert our control and will also add a binding to the Visibility property so that we can show and hide our control using a boolean.

So looking with Live Visual Tree we now will have:
LVT

Our XAML Code in the MediaPlayer:

 <contrls:RateMyVideoControl Visibility="{Binding IsRateMyVideoVisible , Converter={StaticResource BTVConverter},  FallbackValue=Collapsed}" />

C# code for the IsRateMyVideoVisible property:

private bool _isRateMyVideoVisible = false;

public bool IsRateMyVideoVisible  
{
    get
    {
        return _isRateMyVideoVisible;
    }
    set
    {
        Set(ref _isRateMyVideoVisible, value);
    }
}

And lastly in our MainPage we use the MediaEnded event on the MediaPlayer. This will tell us when to show the control to the user so that we only show it when the user has finished watching the video.

public MainViewModel Vm => (MainViewModel)DataContext;

public MainPage()  
{
    InitializeComponent();

    Loaded += (s, e) =>
    {
        //When player is ending show the Control
        player.MediaEnded += Player_MediaEnded;
    };
}

private void Player_MediaEnded(object sender, Microsoft.PlayerFramework.MediaPlayerActionEventArgs e)  
{
    Vm.IsRateMyVideoVisible = true;
}

When the video has finished playing we now have this:Video with rate me

which is not great... On we go to fix this issue!

Moving elements using Live Visual Tree and Live Property Explorer

As we saw previously we have a custom control that is shown when the video has ended, however, our play/pause button is hiding it!

Again using Live Visual Tree we have:

Video with rate me From what we see here we are going to need to search in our player theme for the element named PlayPauseButton. We'll take a copy of it and then comment it out (just in case we want to go back again), and then paste the copy into the element called TimelineContainer.

So in our PlayerTheme.xaml resource file, around the Grid named TimelineContainer we will now have:

<Grid x:Name="TimelineContainer" Grid.Row="1" Background="{StaticResource TransportBackgroundBrush}">  
                                    <AppBarButton x:Name="PlayPauseButton" Margin="25,0,25,0" Width="140" Height="140" Style="{TemplateBinding PrimaryButtonStyle}" Visibility="{Binding IsPlayPauseButtonVisible, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource VisibleIfConverter}}">
                                        <local:MediaControls.Behavior>
                                            <local:PlayPauseButtonBehavior ViewModel="{Binding ViewModel, RelativeSource={RelativeSource TemplatedParent}}"/>
                                        </local:MediaControls.Behavior>
                                    </AppBarButton>
    <Grid Margin="30,4,30,7">
The rest of the code.....  

Your player should look like this ugly thing now, it's normal: Ugly player

Again using Live Visual Tree and looking for the PlayPauseButton, we can see that it has a Height and Width of 140. We are going to change its Height and Width properties using the Live Property Explorer. You can change the properties Height and Width to 40px and all the sudden it looks a bit better, and if we add more left margin 90px to the Grid which had a left margin of only 30px to start with, we are even better =).

Visual tree to fix player

Once we have modified these properties, our player should look as follows:
Final player

And there you have it, you have customized your MediaPlayer again and seen how Live Visual Tree and Live Property Explorer can allow you to gain a lot of time when you are trying to position different elements in your app!

Happy Coding =).

All of the code can be found on Github here