Click here to Skip to main content
15,860,859 members
Articles / Web Development / ASP.NET

Windows Phone 7 View Model Style Video Player

,
Rate me:
Please Sign up or sign in to vote.
4.95/5 (82 votes)
14 Nov 2010CPOL72 min read 194K   3.9K   91   81
A Designer/Developer collaboration in an example of a Windows Phone 7 View Model Style Video Player

img40.jpg

A Windows Phone 7 "View Model Style" Video Player

In this tutorial, Michael Washington and Alan Beasley team up to demonstrate the creation of a Windows Phone 7 video player that uses the View Model Style pattern.

The View Model Style pattern allows a programmer to create an application that has no UI (user interface). The programmer only creates a ViewModel and a Model. A designer with no programming ability at all, is then able to create the View (UI) in Microsoft Expression Blend 4 (or higher). If you are new to the View Model Style pattern, it is suggested that you read Silverlight View Model: An (Overly) Simplified Explanation for an introduction.

   

Michael Washington: Creating The "View Model" (The Program)

Creating the video player is actually very easy. The only thing that I am doing differently, is that I am not putting in code in the code behind of the View. By doing this, it allows Alan Beasley to alter the View (the UI) any way he wishes.

To create Windows Phone 7 applications, you will need to install the Developer Tools from: http://developer.windowsphone.com.

Image 2

First we create a Silverlight for Windows Phone Application project in Visual Studio.

   

Using MVVM Light For Invoking ICommands in Windows Phone 7

Image 3

When you don't use code behind, you need to use ICommands and invoke them using behaviors. Windows Phone 7, at the time of this writing, does not support invoking ICommands, so we will use Laurent Bugnion's MVVM Light from: http://mvvmlight.codeplex.com/ (and a thank you to Sacha Barber and Laurent Bugnion for reminding me to look at MVVM Light or Cinch when I got stuck).

Image 4

The package contains a number of projects, unzip GalaSoft.MvvmLight.Binaries.V3.zip (or higher) (note: see http://www.galasoft.ch/mvvm/installing/ for more help installing the full package)

Image 5

Next, we select Add Reference...

Image 6

We add the assemblies from: \Program Files\Laurent Bugnion (GalaSoft)\Mvvm Light Toolkit\Binaries\WPF4

  

The Flick Trigger

Gestures are really important to a Windows Phone 7 application, so we next want to download Jocelyn Mae Villaraza's WPBehaviorsLibrary from http://aimeegurl.com/2010/03/18/panoramic-navigation-on-windows-phone-7-with-no-code.

Image 7

We download the Library, open it up, and copy the GestureTriggers.cs and StateBehaviors.cs files, and place them in our project.

  

Other Supporting Files

Image 8

We also create a DelegateCommand.cs file that also supports "commanding". That file is covered in the tutorial at this link.

The Videos.cs file is a simple class to hold the videos:

public class Videos
{
    public string VideoName { get; set; }
    public string VideoURL { get; set; }
}

 

The View Model

Image 9

Technically we only need to create one more file, the View Model (MainViewModel.cs), however, we will also walk through some of the steps to implement a View for the Video Player, so you can get a good idea of exactly how a View is created from the View Model.

We create a file called MainViewModel.cs and enter the following code:

public class MainViewModel : INotifyPropertyChanged
{
    private MediaElement MyMediaElement;
    private DispatcherTimer progressTimer;

    public MainViewModel()
    {
        // Set the command property
        MediaOpenedCommand = new DelegateCommand(MediaOpened, CanMediaOpened);
        PlayVideoCommand = new DelegateCommand(PlayVideo, CanPlayVideo);
        StopVideoCommand = new DelegateCommand(StopVideo, CanStopVideo);
        PauseVideoCommand = new DelegateCommand(PauseVideo, CanPauseVideo);
        SetSeekControlCommand = new DelegateCommand(SetSeekControl, CanSetSeekControl);
        SetVideoCommand = new DelegateCommand(SetVideo, CanSetVideo);

        // Call the Model to get the collection of Videos
        GetListOfVideos();
    }

This sets up some global variables we will need, MyMediaElement, progressTimer, and in the constructor for the class, it sets up some some ICommands that we will need. Finally it calls the GetListOfVideos() method.

The code for the ICommands and the Properties of the View Model was taken directly from: SilverlightMVVMVideoPlay.aspx and: AdvancedMVVMVideo.aspx and is covered in detail in those articles.

For example, the MediaOpenedCommand is where the View will set the MediaElement, and store it in the MyMediaElement global variable, and start a DispatcherTimer that will track the progress of the video and update the progress controls:

#region MediaOpenedCommand
public ICommand MediaOpenedCommand { get; set; }
public void MediaOpened(object param)
{
    // Play Video
    MediaElement parmMediaElement = (MediaElement)param;
    MyMediaElement = parmMediaElement;

    this.progressTimer = new DispatcherTimer();
    this.progressTimer.Interval = TimeSpan.FromSeconds(1);
    this.progressTimer.Tick += new EventHandler(this.ProgressTimer_Tick);

    SetCurrentPosition();

    // Play the video
    PlayVideo(null);
}

private bool CanMediaOpened(object param)
{
    return true;
}
#endregion

The major change from the previous Silverlight Video Player articles, was to remove the web service code and to simply create a collection of videos for the GetListOfVideos() method.:

#region GetListOfVideos
private void GetListOfVideos()
{
    SilverlightVideoList = new ObservableCollection<videos />();
    SilverlightVideoList.Add(new Videos { VideoName = "Introduction", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule1-SL4LOB_01_01_Introduction/Silverlight4-SL4BusinessModule1-SL4LOB_01_01_Introduction_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "RIAServices", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule2-SL4LOB_02_01_RIAServices/Silverlight4-SL4BusinessModule2-SL4LOB_02_01_RIAServices_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Editing Entities", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule2-SL4LOB_02_02_EditingEntities/Silverlight4-SL4BusinessModule2-SL4LOB_02_02_EditingEntities_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Showing Events", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule2-SL4LOB_02_03_ShowingEvents/Silverlight4-SL4BusinessModule2-SL4LOB_02_03_ShowingEvents_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Authentication", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule3-SL4LOB_03_01_Authentication/Silverlight4-SL4BusinessModule3-SL4LOB_03_01_Authentication_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "MVVM", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule3-SL4LOB_03_02_MVVM/Silverlight4-SL4BusinessModule3-SL4LOB_03_02_MVVM_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Validation", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule3-SL4LOB_03_03_Validation/Silverlight4-SL4BusinessModule3-SL4LOB_03_03_Validation_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "ImplicitStyles", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule3-SL4LOB_03_04_ImplicitStyles/Silverlight4-SL4BusinessModule3-SL4LOB_03_04_ImplicitStyles_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "RichTextBox", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule3-SL4LOB_03_05_RichTextBox/Silverlight4-SL4BusinessModule3-SL4LOB_03_05_RichTextBox_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Webcam", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule4-SL4LOB_04_01_Webcam/Silverlight4-SL4BusinessModule4-SL4LOB_04_01_Webcam_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Drop", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule4-SL4LOB_04_02_Drop/Silverlight4-SL4BusinessModule4-SL4LOB_04_02_Drop_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Grouping", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule5-SL4LOB_05_01_Grouping/Silverlight4-SL4BusinessModule5-SL4LOB_05_01_Grouping_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "FluidUI", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule5-SL4LOB_05_02_FluidUI/Silverlight4-SL4BusinessModule5-SL4LOB_05_02_FluidUI_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "RightMouseClick", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule5-SL4LOB_05_03_RightMouseClick/Silverlight4-SL4BusinessModule5-SL4LOB_05_03_RightMouseClick_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Printing", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule6-SL4LOB_06_01_Printing/Silverlight4-SL4BusinessModule6-SL4LOB_06_01_Printing_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "MultipagePrinting", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule6-SL4LOB_06_02_MultipagePrinting/Silverlight4-SL4BusinessModule6-SL4LOB_06_02_MultipagePrinting_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "OOB", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule7-SL4LOB_07_01_OOB/Silverlight4-SL4BusinessModule7-SL4LOB_07_01_OOB_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Toasts", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule7-SL4LOB_07_02_Toasts/Silverlight4-SL4BusinessModule7-SL4LOB_07_02_Toasts_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Window Placement", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule7-SL4LOB_07_03_WindowPlacement/Silverlight4-SL4BusinessModule7-SL4LOB_07_03_WindowPlacement_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Elevated Trust", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule7-SL4LOB_07_04_ElevatedTrust/Silverlight4-SL4BusinessModule7-SL4LOB_07_04_ElevatedTrust_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Custom Chrome", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule8-SL4LOB_08_01_CustomChrome/Silverlight4-SL4BusinessModule8-SL4LOB_08_01_CustomChrome_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Window Closing Event", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule8-SL4LOB_08_02_WindowClosingEvent/Silverlight4-SL4BusinessModule8-SL4LOB_08_02_WindowClosingEvent_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "OOB Silent Install", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule8-SL4LOB_08_03_OOBSilentInstall/Silverlight4-SL4BusinessModule8-SL4LOB_08_03_OOBSilentInstall_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "Xap Signing", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule8-SL4LOB_08_04_XapSigning/Silverlight4-SL4BusinessModule8-SL4LOB_08_04_XapSigning_kit.wmv" });
    SilverlightVideoList.Add(new Videos { VideoName = "MEF", VideoURL = @"http://ecn.channel9.msdn.com/o9/learn/videos/Silverlight4-SL4BusinessModule8-SL4LOB_08_05_MEF/Silverlight4-SL4BusinessModule8-SL4LOB_08_05_MEF_kit.wmv" });

    SetVideo(SilverlightVideoList[0]);
    SelectedVideoInListProperty = 0;
}
#endregion

They are exposed to the View by the SilverlightVideoList collection:

#region SilverlightVideoList
private ObservableCollection<videos /> _SilverlightVideoList;
public ObservableCollection<videos /> SilverlightVideoList
{
    get { return _SilverlightVideoList; }
    private set
    {
        if (SilverlightVideoList == value)
        {
            return;
        }

        _SilverlightVideoList = value;
        this.NotifyPropertyChanged("SilverlightVideoList");
    }
}
#endregion

The View (The Developer Version)

Image 10

I usually create a View so that Alan Beasley can see how the View Model is expecting things to be wired-up. This View will be thrown away so I don't even attempt to make it look presentable. I create MainPage.xaml...

Image 11

I open the project in Expression Blend 4 and I click on the LayoutRoot in the Objects and Timeline window, and in the Properties, I click on the New button next to DataContext...

Image 12

...and I set it to the MainViewModel.

Image 13

Then, when I click on the Data tab, I see all the Properties, Collections, and Commands that the View Model makes available.

I cover wireing-up the controls in: SilverlightMVVMVideoPlay.aspx and: AdvancedMVVMVideo.aspx.

Image 14

However, instead of using the InvokeCommandAction behavior, I used the EventToCommand behavior from the MVVM Light Toolkit.

  

Using Gestures

Image 15

Because this is a Windows Phone 7 application, we wanted to add support for gestures. This is different than simply clicking on something with your finger (when using an actual phone) or your mouse (when using the Windows Phone 7 emulator). A gesture allows you to specify an action when a person moves in a specific direction.

In my sample, I wired-up gestures that will play the video if you press on the video (with your mouse pointer or your finger) and move to the right. It will stop the video if you move to the left.

Here are the steps to wire-up the FlickRight_Play gesture:

Image 16

I grab an EventToCommand behavior, and drop it on the mediaElemnt in the Objects and Timeline window.

Image 17

In the Properties for the behavior, I click the New button next to TriggerType... 

Image 18

I select the FlickGestureTrigger

Image 19

I select a direction in the Direction drop down. 

Image 20 

I click Advanced options next to Command.

Image 21

I then bind the Command to the PlayVideoCommand.

  

Run the Project

Image 22 

After everything is wired-up, you hit F5 to run the project. If you have an actual phone hooked up, select Windows Phone 7 Device, otherwise select the Emulator.

Image 23 

The Emulator will load. 

Image 24 

This application displays in Landscape mode, so you will have to click the rotate button. 

Image 25

The application will start and the first video will play. To change the video, you have to click on the list box, hold down the mouse button and drag up or down, then click on the selection to change the video (this works a lot better when using your finger on a real phone).

You can also click on the video, hold the mouse button down, and slide to the right to play the video, and to the left to stop it. 

  

Superior Designer / Developer Workflow

Michael Washington:

I usually create a View so that Alan Beasley can see how the View Model is expecting things to be hooked up. However, he is free to completely remove everything from the View and start from scratch.

The thing that is amazing, is that he is able to complete the project without any code, and without needing to have me "fix up any issues". The only time the project has to come back to me, is to add new features.

For example, after the first version, he requested that we have a list of videos to choose from. I added collection to the View Model and sent it to him. All he needed to do was replace the View Model in his version of the project. No need to disturb any changes he may have already started making on the View.

Any project is greatly enhanced when each person is able to concentrate on what they do best. My part becomes really easy, I look at the current requirements for the project, and I implement the requirements using only Properties, Collections, and ICommands (and any code needed to support them).

The actual user interface and  "flow" of the application is out of my hands, and I watch in fascination as it goes through sometimes drastic alterations. I sometimes throw out an idea or two but I am a "spectator" on what would normally be "my" project. I have to sometimes remind myself that the only person writing code is me! However, like a writer and director of a movie have to have to accept that the Actors are what the audience is eventually looking at, the UI is what the end users see and care about. No one cares about the code unless is doesn't work.

For years, applications have been held back because the programmers MUST implement certain functionality. This is like a director needing to be a character in each scene of a movie. Some director's are good Actors and this works, but for the average project, the UI is best left to the hands of those who are best at creating UI's.

  

Alan Beasley: Creating The "View" (The User Interface)

Now before anyone starts designing ANYTHING for the Windows 7 Phone, they should read the Windows Phone UI Design & Interaction Guidelines. Microsoft have produced these "Guidelines" in an effort to generate a consistent "Look & Feel" for Windows 7 Phone development. While these are just "Guidelines" and not "Rules", I would suggest you read them, & have a very good reason/argument on why you would want to deviate from them. As Microsoft & the Silverlight community as a whole, would like a successful launch of the Windows 7 Phone. No one in the Silverlight community wants to see an amalgamation of radically different designs, that as a whole, looks like a hotchpotch (jumbled mixture) of different designs. Microsoft have put a lot of effort into their "Metro" styling to generate a consistent style for the Windows 7 Phone. So think twice before you go crazy with lots of "snazzy" graphics!

So what are these UI Design guidelines then? Well the main focus is a consistent "Metro" style covering: Icons, Text styles, Layout, Navigation, Interaction, Colour Schemes, etc... But I'm not going to repeat the whole guidelines, & I strongly suggest you read them for yourselves (At least until you find one spelling mistake, & I assure you there is one). What I will do, is discuss the relevant aspects of the guidelines as I go along in styling Defwebserver's (Michael's) video player. So let us make a start...

Download the un-styled player that Michael has created, & open in Blend 4. You may need to update your installations as follows:

1, Uninstall Expression Blend & re-install (Microsoft Expression Blend® 4 Release Candidate (RC)

2, Install http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=cabcd5ed-7dfc-4731-9d7e-3220603cad14

3, Install Microsoft® Expression Blend® Add-in Preview 2 for Windows® Phone

4, Install Microsoft® Expression Blend® Software Development Kit (SDK) Preview 2 for Windows Phone

Run the application in the Phone Emulator & switch to Landscape mode by clicking on the icon in the image below.

Image 26

Eventually (it takes a while) the Video Player will start & look like the image below.

Image 27

Now this is "functional" but not very pretty, as Michael has only placed the necessary elements on the screen to get the application working. Ready to hand over to a designer to make the application more visually appealing (As we don't have a designer, I'll have to do...LOL)

So what  have we got? A title area with the text "My Video Player", a ListBox showing "Introduction" and a load more videos that are currently hidden, but what really grabs the attention is are the Player Controls in the lower central area of the screen. The Player Controls consist of a Progress Bar, Progress Display, Play, Pause, Stop & a Volume Slider. All that a basic video player needs... Currently it is not possible to have a Fast Forward or Rewind control for the video player, even though Victor Gaudioso shows how to add Fast Forward functionality to the MediaElement in an excellent video tutorial. The reason we cannot add this functionality, is because we cannot set the position of the video stream in the Windows Phone. Why I don't know, as I am not a coder! But I'm sure this issue will be addressed by Microsoft in the very near future. So for the minute we will forget Fast Forward & Rewind & just Style what we have.

The default controls that are available when developing for the Windows 7 Phone in Silverlight, are not the standard controls for developing a normal Silverlight application. Microsoft have developed these controls specifically for the phone, as obviously there will be some differences with a touch screen interface, & a normal mouse interaction interface. The most noticeable are the buttons, & by default these are rectangular & quite large. They also have an overhang area as shown in the image below.

Image 28

The reason the buttons have an overhang, is to do with the "Touch Target" area, & a designer needs to consider user interaction when designing for a touch screen. I.E How fat are the user's fingers? Will the user accidentally touch the wrong button if controls are placed too close together? Microsoft recommend a minimum size of 9mm (34 pixels) for each touch target, & a spacing of 2mm (8 pixels) between touch targets that may be only 7mm (26 pixels) in size. The Z order also plays a part with regards to touch targets, & the higher (closer) the control is in the layout Z order, it will have preference to an overlapping controls "Touch Target" area. We can see in the image above, that the Play button's "touch target", overlaps the Pause button, & these will definitely interfere with each other in a touch screen environment. (Bad developer!!!) But it is not the developers job to consider these aspects, unless they are also the designer! So we need to consider minimum sizes for our interactive controls, & if we need to provide a "TouchTargetOverhang" for these controls. The "TouchTargetOverhang" can be adjusted for the whole application in the App.xaml, & by default is set to 12 pixels on all sides. As shown in the image below.

Image 29

The "PhoneTouchTargetOverhang" is bound to the Margin property of the "ButtonBackground" Border element in the button Control Template. But remember that this "TouchTargetOverhang" is only needed when dealing with the Minimum sizes of interactive controls. So if the button is larger than 9mm (34 pixels) a "Overhang" may not be required. User testing is only the real way of checking if your design layout works, but as none of us have a real phone at present, I suggest we all air on the side of caution regarding the size of the "Touch Target".

So let's go ahead & start styling the Player Controls & see how we get on. Firstly let us examine what Michael has given us to work with in the Objects and Timeline of Expression Blend 4

Image 30

Currently we have a Grid named "PlayerControls" & within this, a TextBlock that shows the ProgressDisplay (time duration) of the video. As well as a Canvas containing the rest of the controls. These being a Slider (volume), & 3 Buttons named Play, Pause & Stop. If you expand the tree further, you will see that Michael has attached Behaviors to the elements, that hook into the code he has written in the "View Model". And you can find out more about this in Michael's section of the article. But for me as the designer, what this means is that I could completely delete everything here, & start with a clean slate. Hooking up to his code using these behaviors (Writing absolutely no code at all!!!). 

Image 31

But to keep this article from getting too long, or repeating Michael's stuff, I will work with what we have here...

 

Modifying the Layout of the Player Controls

Select the Canvas element, right click & choose Change Layout Type > StackPanel.

Image 32

Select the StackPanel, change the Orientation to Horizontal, Reset the Margins & set both the Horizontal & Vertical Alignments to Stretch.

Now select All the contents of the StackPanel, Reset the Margins & set the Horizontal & Vertical Alignments to Stretch.

The StackPanel should now look something like the image below.

Image 33

Now change the order of the StackPanel in the Objects and Timeline to StopButton, PlayButton, PauseButton, Slider. As shown in the image below.

Image 34

The Artboard should now change to show the controls, just like the image below.

Image 35

This is not really any different to what Michael had before in the Canvas, except that it is now dynamic & will update automatically. Making edits to the controls easier...

Now select both the ProgressBar & the ProgressDisplay, & choose Group Into > Grid.

This causes the Artboard to change to something like the image below, but don't fear! We can sort this out...

Image 36

What I want to do now, is divide the PlayerControls into 2 Rows. The top row containing the ProgressBar & ProgressDisplay, & the bottom row containing the Buttons & volume Slider.

So select the Grid element named "PlayerControls" & using the Selection Tool, place a Row Divider as shown in the image below.

Image 37

Next select the Grid containing the ProgressBar & ProgressDisplay, & choose Group Into > Border.

Rename this Border to "ProgressInfo", Reset the Margins so it fits in only the top Row of the PlayerControl Grid & ensure the Horizontal & Vertical Alignment is set to Stretch.

Now select the StackPanel, choose Group Into > Border & rename the Border to "NavigationAndVolume". Reset the Margins so it fits in only the bottom Row of the PlayerControl Grid & ensure the Horizontal & Vertical Alignment is set to Stretch.

All being well, the Artboard should look like the image below.

Image 38

This is starting to look better, & almost at the point where we can think about Styling the Controls. But there is still one more thing we need to look at regarding the ProgressBar & ProgressDisplay. Currently the ProgressDisplay is invisible, & this is because there is nothing to display (no video information at design time) & the ProgressBar has a Margin on the right hand side that stops it overwriting the ProgressDisplay. But this will not work for us at runtime, as we are unable to say for sure how much space the ProgressDisplay will need. As this will depend on the length of each video we play...

So select the Grid containing the ProgressBar & ProgressDisplay, & insert a Column Divider as shown in the image below.

Image 39

Set the ProgressBar to fill only the first Grid Column & the ProgressDisplay to fit only the second Grid Column. Ensure the Margins for both elements are set to 0 (Reset) & the Horizontal & Vertical Alignments are set to Stretch. As shown in the image below.

Image 40

You should notice that the ProgressBar does not fill all of the first Column (Depending on exactly where you put the Column Divider) & the same will be true for the ProgressDisplay. This is because Michael give these elements a fixed Width (Bad developer!!!) But as before, I'm only kidding! So it is not his responsibility, other than to test the functionality of these elements, not to design them...

So select the ProgressBar & set the Width to Auto. Do the same for the ProgressDisplay as well...

You should notice that the ProgressDisplay defaults to a Width of 0 pixels, & this is because it currently has no input to display during design time.

The ProgressBar now fills all of the first Column of the Grid (end to end), as shown in the image below.

Image 41

But to give is some breathing space, we need to set Margins for the Left & Right sides of it. And we could do this on the element, or possibly on the parent Grid element. I will choose to do a combination of the 2, & set a Margin on the Right side of the ProgressBar only. (The reason why will soon become clear...)

So with the ProgressBar selected set a Margin of 10 pixels to the Right side only. As shown in the image below.

Image 42

Now for the clever bit, & too take advantage of the "PhoneTouchTargetOverhang", that is by default applied to the Buttons.

Select the parent Grid element of the ProgressBar & ProgressDisplay, & in the Advanced options select Local Resource > PhoneTouchTargetOverhang.

Image 43

This will place a Margin of 12 pixels on all sides of the ProgressBar & ProgressDisplay Grid, and will update just like the Buttons will if this property is changed. The Artboard probably now looks like the image below.

Image 44

(This is because the Top & Bottom Margins have effectively given the ProgressBar zero height to display in. But don't worry, as this is because the parent Grid named PlayerControls has a fixed Height).

So select the Grid named PlayerControls & set the Height to Auto. This should expand the Height of the PlayerControls enough to reveal the ProgressBar, as shown in the image below.

Image 45

Now that should do for now regarding Layout, & we can tweak the Layout as we Style the elements/components.

  

Styling the Control elements

Border elements

As we worked through the previous section, you may have wondered why I added some Border elements. And now I'm going to show you why!
I've read a few articles regarding Borders & Rectangles & none of them have really discussed or properly shown the difference between them. In simple terms, a Rectangle is more basic than a Border, & the only advantage a Rectangle has over a Border, is that the Corner Radius for the X & Y can be different, that's about it!. But a Border can do a couple of neat things a Rectangle cannot...

Select the Border element named ProgressInfo & set a BorderThickness of 3 on all sides, as shown in the image below.

Image 46

(Setting different edge thicknesses is the first thing a Rectangle cannot do...)

The Artboard has probably not changed, as the Border has no Background or BorderBrush applied to it yet.

So select the BorderBrush & click on Brush resources, as shown in the image below.

Image 47

From the available "Local Brush Resources", choose the PhoneAccentBrush, as shown in the image below.

Image 48

These Local Brush Resources are part of the Windows Phone Theme, & the PhoneAccentBrush is basically one of 4 Theme colours discussed in the guidelines. There are actually 5 Theme colours, but one is reserved for the Phone manufacturer. I'm going to style all my controls using this Blue Theme colour & reference this Resource every time. This way, when the Theme colour is changed, so will my controls...

The Artboard should now look like the image below.

Image 49

(Using F9 hides/toggles the Blend design handles, as I have done for clarity in the image above)

Now I want to put a Radius on the Top 2 corners of the Border, but not on the Bottom 2 corners of the Border.

So with the ProgressInfo Border selected, set the CornerRadius to 20,20,0,0, as shown in the image below.

Image 50

(Specifying a different radius for each corner, is the second thing a Rectangle cannot do...)

So the Artboard now looks like the image below.

Image 51

Now repeat the process for the Border element named NavigationAndVolume, except set the Top BorderThickness to 0, & the CornerRadius to 0,0,20,20.

With a bit of luck you should end up with the same as the image below.

Image 52

And as I said before, you can't do that with a Rectangle!!!

Now to add some more substance to the Player Controls, I want to add a semi-transparent background to the Border elements.

So select the ProgressInfo Border element, & set a Gradient Brush for the Background.

Change both the Gradient Stops to Black, set the Alpha of the first Gradient Stop to 30%, & the second Gradient Stop to 80%.

Repeat this for the Border named NavigationAndVolume, reversing the Gradient so it looks like the image below.

Image 53

(I have temporarily placed a off-white Rectangle behind the Player Controls for the clarity of this image).

  

Styling the ProgressBar & ProgressDisplay

Select the ProgressBar, & give it a height of say 18 pixels to fatten it up a bit. Notice that it has sharp corners, & this doesn't really fit with the radiused corners of the Border elements, so lets look at fixing that now with a bit of Styling.

So with the ProgressBar still selected choose Edit Template > Edit a Copy. Name this new Style to PhoneProgressBarStyle, or something similar & hit OK.

Image 54

The ProgressBar is a fairly complicated control, but we are only interest in the basic components which are the ProgressBarTrack & the DeterminateRoot (And its child ProgressBarIndicator). Which is lucky really, as if I select the Visual State Manager (VSM) & go to the "Indeterminate" State. Expression Blend 4 throws an Exception (Blows up), for what reason I do not know, but this seems to be an issue with the Phone only... (I may cover the ProgressBar in depth, in a future tutorial)

Image 55

So lets look at the ProgressBarTrack first, which is the track that the progress indicator works its way along as the video plays. We currently cannot see it, as it is covered (obscured) by the ProgressBarIndicator. So temporarily hide the ProgressBarIndicator by clicking on the Eye icon next to it, so we can work on the ProgressBarTrack. The ProgressBarTrack is rather faint as the Opacity is only set to 10%, which is probably fine most of the time, but for clarity in this tutorial I want to make it a bit clearer (more obvious). There is also the consideration that we have the video playing behind this. As well as the thought to the environment that a mobile device may be used in, like bright sunshine. So I feel somewhat justified in my reasoning to change the "Default" setting for the ProgressBarTrack, but only real user testing will prove, or disprove this hunch...

With the ProgressBarTrack selected, change the element Opacity to 30%, & set the CornerRadius to 5, so it looks like the image below.

Image 56

(The ProgressBarIndicator is hidden in the image above).

Now this looks OK, but I don't really want all the corners to have a radius. But because this a Border element, I can change each CornerRadius individually. Great, but there is a problem... The ProgressBarIndicator is a Rectangle inside of a Grid! And as I have said before, a Rectangle cannot have each CornerRadius set differently. And as the ProgressBarIndicator tracks along the ProgressBarTrack, it needs to match exactly, or it will look rather silly. So we need to remove the Rectangle & replace it with a Border I hear you say? And yes we can, but pay attention to the fact that the ProgressBarIndicator is a ControlPart of the ProgressBar (Signified by the tiny icon next to it). And hence is mandatory within the Control Template! So we can replace it, but it MUST be named the same as the existing element. So lets get on with it!

  Select the ProgressBarTrack & set the CornerRadius to 8,0,0,0, which should result in the same as the image below.

 Image 57

(The ProgressBarIndicator is hidden in the image above).

Now go to the ProgressBarIndicator Rectangle, make a note of the name & then Delete it.

Insert a Border element in its place & name this to ProgressBarIndicator, and as if by magic, a tiny icon appears next to it to signify it is a ControlPart of the Control Template.

In the Layout properties ensure the Width & Height are set to Auto, the Horizontal Alignment is set to Left & the Vertical Alignment is set to Stretch. Also ensure the Margins are set to 0.

Now remove the BorderBrush & set the Background to Template Binding > Foreground.

Finally set the CornerRadius to 8,0,0,0, (The same as the ProgressBarTrack).

That is it for the ProgressBar, unhide any hidden elements, & come out of the Control Template so we can look at the ProgressDisplay next...

Now we obviously cannot see the content of the ProgressDisplay at design time, so we will design what needs to be done blind & keep our fingers crossed... The ProgressDisplay is just text & will probably not want to be changed along with the Theme of the Phone, but the Theme comes with some predefined Fonts & Font Sizes. So I will Bind to these properties to demonstrate the capability...

Select the ProgressDisplay element & in the Text properties, click on the Advanced options & choose Local Resource > PhoneFontSizeNormal.

Image 58

Now in the Advanced options of the Font Family, choose Local Resource > PhoneFontFamilySemiBold.

Image 59

Finally run the application (F5) and review the results, as shown in the image below.

Image 60

The ProgressBar is looking OK & as expected, but the ProgressDisplay not working properly. As it does not have enough room to display properly... This is because we cannot say how space the ProgressDisplay will need each time it is used, & we need to allocate it a variable size, rather than the "Default" proportional size it currently has within the parent Grid. You may have slightly different results to the current screenshot, as it would have depended where you placed the initial Grid Column Divider.

So select the parent Grid element & change the "Star" size icon, to "Auto" sized by clicking on the "Padlock" icon twice, as shown in the image below.

Image 61

This will not change the position of the Grid Divider in the Artboard, as Blend will place a Minimum Width for this Auto Sized Grid Column.

So go to the XAML & remove/delete the MinWidth declaration (highlighted in Blue in the image below).

Image 62

The Grid Divider should now snap to the right hand end of the Grid, but will automatically grow when it has content to display.

The last thing to do with the ProgressBar & ProgressDisplay, is ensure they are referencing the PhoneAccentBrush, & therefore the Theme.

So select the ProgressBar & set the Foreground colour to the PhoneAccentBrush, & do the same for the ProgressDisplay, as shown in the image below

Image 63

Run the application again (F5), just to check everything went to plan...

Image 64

Looks OK to me, but not perfect! As the ProgressBar is a little taller than the ProgressDisplay text, but let us move on to the Buttons & Slider...

  

Styling the Stop, Play & Pause Buttons

Now the first thing we should do is get all the elements into view, as the volume Slider is partially obscured. This is because the Grid containing all the elements is not auto-sizing properly. The Width of the PlayerControls Grid is set to Stretch, but we have Margins applied to the Left & Right sides that are restraining the Width. Hence we have a fixed size for the PlayerControls, as the overall width of the Phone screen is always going to be 800 pixels. (In Landscape mode at least...)

So select the PlayerControls Grid, change the Horizontal Alignment to Center & Reset the Margins, as shown in the image below.

Image 65

Now set the Vertical Alignment to Bottom & apply a Margin of about 32 to the Bottom only, as shown in the image below.

Image 66

That should size & position the Player Controls as shown in the image below.

Image 67

The volume Slider is now fully visible, even if it is butting up against the edge of the Border, but all in good time... (it is actually only a Refresh issue with Blend 4, & not uncommon - Unfortunately!)

Select the StopButton element & choose Edit Template > Edit a Copy.

Give this new Style a name like "PhoneButtonStyleStop" & hit OK.

Image 68

Now if we look at the Objects and Timeline, as shown in the image below.

Image 69

We can see that this button Control Template, is a little different to a normal Silverlight button. For a start, we have no ContentPresenter & instead have a foregroundContainer, which I can tell you holds the ContentPresenter. The parent Border element (ButtonBackground) of the foregroundContainer, represents the extremities (limits) of the visual elements that make up the button. And the parent Grid represents the whole of the "TouchTarget" that makes up the button. Have a look at the Grid element, & notice that it has a Background Brush applied to it with 0% Alpha. The Grid needs this "transparent" Brush applied to it, so that it is "IsHitTestVisible" & a "TouchTarget" area for user interaction. The ButtonBackground has a Margin applied to it, which is bound to the "TouchTargetOverhang" Resource, & is what is currently providing the spacing/padding between the visual elements of the button & the Border of the Player Controls.

Now I don't want to use Text in the StopButton, as it is a little vulgar, & would require translation for each language. (Stuff that!) So instead I will use the globally accepted symbol/icon for "Stop" with regards to media. A Square! And there are a couple of ways I can do this... Both will use a Rectangle element, but it is the Layout that will differ... The most obvious method, would be to just define a fixed Width & Height for the Rectangle, but this would not Scale with the size of the button. So instead, I will set the Rectangle to be the full size of the visible area of the button (not including the "TouchTargetOverhang") & apply a ScaleTransform to the Rectangle to make it a proportional size of the button. This however, will mean that if I change the proportions of the button, the "Square" may deform to become a "Rectangle", but I can live with that, as I cannot see that I would want to radically change the button proportions, but I am more lightly to maybe change the size of the button.

Firstly, let us get rid of the "ContentPresenter" so to speak, by collapsing the foregroundContainer. I don't want to delete it, as my boss (fictitious) may disagree with my decision to use a symbol/icon & ask for the text back.

So select the foregroundContainer & in the Properties tab, set the Visibility to Collapsed.

Image 70

Now before we go ahead, & insert a Rectangle into the Border element named ButtonBackground. We need to remember that a Border can only have one child element, & this is currently the foregroundContainer. And as I want the Rectangle to Scale in proportion to the ButtonBackground, the Rectangle HAS to be inside the Border element.

So still with the foregroundContainer element selected, choose Group Into > Grid. (Ensure the Margins are Reset & Alignments are set to Stretch)

(Check the Visibility of the Grid is Visible, & the ContentPresenter (foregroundContainer) is still Collapsed).

Select the newly created Grid, insert a Rectangle with 0 Margins, set the Alignments to Stretch & Auto-sized for Width & Height.

Rename the Rectangle to "StopIcon" & set a Scale Transform (RenderTransform) of 0.35 for the X axis, & 0.6 for the Y axis.

Image 71

(Now as the button size is changed (Scaled), so will the StopIcon).

The StopIcon may not be a perfect "Square" but don't worry about this, as we have yet to determine the exact size of the overall button!

Now to ensure the StopIcon always matches the colour of the Border, select the Fill & choose Template Binding > BorderBrush.

Image 72

Remove the Stroke of the StopIcon, & the StopButton should look like the image below.

Image 73

Now select the ButtonBackground & set a CornerRadius of 0,0,0,8, as shown in the image below.

Image 74

Finally (Using the "BreadCrumbBar"), go to the Style of the StopButton.

Image 75

Change the BorderBrush to the Brush Resource named PhoneAccentBrush, as shown in the image below.

Image 76

And as long as everything went OK, you should have the same as the image below.

Image 77

(The StopButton colour is now Bound to the Theme of the Phone).

Next we should consider how large we want our buttons to be, & as I said before, the guidelines recommend a minimum size of 9mm (34 pixels) for a "TouchTarget". But we shouldn't take this size to be the "standard" size, it is a "minimum" size! And this should probably only be relevant when space is at a premium, due to having a lot of "TouchTargets" all on the screen at once. I.E When displaying a keyboard interface. Consideration should also be give to the audience in terms of accessibility, and who will be able to use this interface. I am lucky enough to be able bodied (sort of), but would not ever want to unnecessarily exclude a group of users from using a product or interface. For this reason, I believe the controls (buttons) should be as large as possible without compromising the design, look & style of the Player Controls.

So select the StopButton, set the Width to 120 pixels & the Height to 80 pixels.

Repeat the process for the PlayButton & the PauseButton to make them all the same size.

Now go through the process as you did with the StopButton, to Style the Play & Pause buttons. But do not put a radius on any of the corners of the Border element! Alternatively you can download the Buttons Styles from here. (The Play & Pause Icons are also included...)

Image 78

(Image above shows Stop, Play & Pause Buttons all Styled).

   

Styling the Volume Slider

You have probably noticed that the Volume Slider is radically different from the standard Silverlight Slider, & the Thumb component is somewhat larger. This obviously again is because of the "TouchTarget" considerations for the Phone, so that the Thumb is large enough to be easily controlled. So while we can make it any size we like, keep in mind that the interaction is of major importance when designing for the Phone.

Right click & choose Group Into > Border, as shown in the image below.

Image 79

Ensure the Margins of the Slider are Reset, select the Border element & rename it to "VolumeSlider".

Now click on the Advanced options & choose Local Resource > PhoneDefaultBorderThickness.

Image 80

This will set the BorderThickness to 3 on all sides, & automatically update along with the button BorderThicknesses.

(We could have also set the outer Border elements to this Resource, which we can do later, but we may want to try out different thicknesses for these elements yet...)

Set the CornerRadius to 0,0,8,0, as shown in the image below.

Image 81

Now set the BorderBrush to the PhoneAccentBrush Resource, & match the colour of the buttons (& Theme).

Image 82

Next set the Margins to the Local Resource > PhoneTouchTargetOverhang, as shown in the image below.

Image 83

Finally set the Width to 160 pixels & the Height to Auto, as shown in the image below.

Image 84

The Player Controls should now look like the image below.

Image 85

Next to do some work on the Slider itself to bring it in-line with the rest of the Player Controls.

So select the Slider, right click & choose Edit Template > Edit a Copy.

Give this new Style a name like "PhoneSliderStyleVolume" & hit OK.

Image 86

In the Objects and Timeline expand the HorizontalTemplate to show all the elements, as shown in the image below.

Image 87

Select the HorizontalTrack & set the Visibility to Collapsed.

Now select the HorizontalThumb & set the Height to Auto, as shown in the image below.

Image 88

In the Artboard the Thumb should now be the full Height of the parent Border element, & the full Width of the portion it occupies in the parent Sub-Divided Grid.

Image 89

(Notice that the portion of the Sub-Divided Grid that the Thumb occupies is Locked. & therefore the Thumb Width is set by the parent Grid).

With the HorizontalThumb still selected, choose Edit Template > Edit Current to access the visual elements of the HorizontalThumb.

 Image 90

Select the ButtonBackground & set a Margin of 8 pixels for the Left & Right sides.

This will make the HorizontalThumb "TouchTarget" smaller & harder to select, which we can fix by setting a Fill/Brush on for the Background of the parent Grid with 0% Alpha.

So we have narrowed down the HorizontalThumb & hopefully made it a little more elegant, but this will mean that the Thumb will not reach the ends of the Slider. Run the application & see for yourself... We also may have some slightly strange behaviour when moving the Slider to 100% (I do). We can fix the problem of the Slider not reaching the ends, by setting Margins of -8 to the Left & Right sides of the Slider within the parent Border, but the strange behaviour still remains... (I can't say for sure, that you will also be experiencing this issue). But there is another way of slimming down the HorizontalThumb that keeps the larger "TouchTarget" area & doesn't result in strange Slider behaviour.   

So remove all the Margins you just applied, & the Background Brush of the Grid element.

Come out of the HorizontalThumb Template & select the HorizontalTemplate Grid, as shown in the image below.

Image 91

Now go to the XAML & change the second Column Width to 18 pixels, as shown in the image below.

Image 92

(The HorizontalThumb is now slimmed down & more elegant, but also harder to select).

So go back into the HorizontalThumb Template, select the Grid element & insert a new Rectangle

Rename this Rectangle to "ThumbTouchTarget" & set the Alignments to Stretch with 0 Margins Top & Bottom, but -8 for Left & Right.

Now remove the Stroke, set a Fill of any colour & make the Alpha 0%.

This will make the "TouchTarget" area of the HorizontalThumb larger, but only on the left hand side of it. As the Z order of the HorizontalTemplate of the Slider Template, is not setup quite as we require.

So come back out of the Thumb Template & in the HorizontalTemplate, select the HorizontalThumb & drag it down below the HorizontalTrackLargeChangeIncreaseRepeatButton, as shown in the image below.

Image 93

This changes the Z order of the HorizontalThumb, so it is effectively on top, & selectable over all other elements in the HorizontalTemplate. This may not be the cleanest of solutions, but slimming down the Thumb, maintaining the "TouchTarget" & while avoiding any strange behaviour, is the best fix I can think of at this current time...

Now go to the Style of the Slider, & set the Foreground Brush to the PhoneAccentBrush. (Just like we have with the other controls).

We are almost finished with the Slider, but now we need to make the Slider a little more obvious that it is to control the Volume. And I plan to do that in 2 way, firstly by placing a semi-transparent layer in the lower section of the Volume Slider, & by introducing a Speaker Icon in this section.

So back in the Slider Control Template select the HorizontalTemplate, & drag out a Rectangle to fill the first portion of the Sub-Divided Grid, as shown in the image below.

Image 94

Ensure the Margins are Reset, the Alignments are set to Stretch & the Stroke is removed.

Then set the Fill to Template Binding > Foreground, as shown in the image below.

Image 95

Now move the Rectangle back in the Z order, by dragging it up & behind the HorizontalTrack, as shown in the image below.

Image 96

Finally change the element Opacity to 50%, making the Artboard look the same as the image below.

Image 97

Now download the Speaker Icon from here & add it to the project.

Open the Speaker.xaml page, select & Copy the Path element & go back to the MainPage.xaml.

Back in the Slider Template with the HorizontalTemplate selected, Paste in the Path element.

Rename the Path to "SpeakerIcon", Reset the Margins & Template Bind the Fill to the Foreground of the Style.

Next in the Advanced options of the Width, Template Bind to the Value of the Slider, as shown in the image below.

Image 98

Do exactly the same for the Height, Template Binding it again to the value of the Slider.

This should set the Width & Height to both 0.5, as shown in the image below.

Image 99

Now to Scale-up the SpeakerIcon by setting a ScaleTransform of 40 for both the X & Y axis.

Image 100

In the Artboard the SpeakerIcon probably looks like the image below, & is not in the correct Sub-Divided portion of the HorizontalTemplate Grid.

Image 101

Firstly move the SpeakerIcon back in the Z order, by placing it in front of the Rectangle, as shown in the image below.

Image 102

(There is no reason other than good housekeeping, for me changing the Z order. I just prefer the selectable/interactive items in-front).

Finally move the SpeakerIcon, so it is in the first Column of the HorizontalTemplate Grid, as shown in the image below.

Image 103

(Ensure the Margins are Reset).

Some experienced programmers amongst you may be saying that I should not have Bound the Width & Height to the Scale of the SpeakerIcon, as this affects the performance of the application. As it will cause a redraw of the Layout every time the Volume is changed. And you may be right, but firstly this is a demo application, & secondly it was the only way I could get it to work. Setting a fixed Width & Height while Binding a Scale Transform to the SpeakerIcon does not work, & neither do my limited attempts to use a Custom Expression.

The last thing I want to do with the Volume Slider is change the initial (Starting) Volume, which is currently set to 0.5 (Half Volume). But we cannot do this in the Volume Slider, as the "Value" of the Slider, is Bound to the Volume property of the MediaElement.

So go to the MediaElement, & in the Media section of the Properties tab, change the Volume to 0.8, as shown in the image below.

 Image 104

Run the application to review the results of our Player Control Styling, as shown in the image below.

 Image 105

Now that looks acceptable & probably OK, as a simple clean interface for the Windows Phone. It is not exactly "in keeping" with the default style of the Windows 7 Phone, but these controls are part of the Video Player, & not the Phone itself. So I feel I have the liberty to style them a little & add a bit of individuality & identity to the Video Player.

  

Styling the Playlist & ListBox

Now to consider how we choose & select a video to be played, as well as navigating between the player & the possible video selections. Microsoft are promoting the use of something called a "Pivot Control" (As well as a "Panorama" application) both for the Web & on the Windows 7 Phone. Basically it as a way of navigating large, or possibly huge amounts of data in a very visual manner. The main navigation on the Phone is intended to utilise the Pivot Control, & allow users to quickly & easily drill down/into the data to find the required information. The operation of a Pivot Control can be visualised as pages on a vertical cylinder & a central Pivot, allowing the user to spin the cylinder to go from page to page. While the number of pages could be almost unlimited, it is recommended that a minimum number should be used (let us say 4 should be your design maximum), & will loop. The user will be able to "Flick" using a touch gesture between the pages, & as such the "Flick gesture" should/must not be overridden in a Pivot Control.

This is a very simple demo application of a video/media player, & I will not be implementing a true fully featured Pivot Control. Rather a "Pivot Control Lite", that will simply change between the Video Player, & the Playlist. Michael has preloaded the ListBox (Playlist) with a selection of videos to choose from, & I'm very happy to use this rather than start from scratch. So let us start looking at the ListBox (Playlist) to see what we have got...

Select the ListBox & drag it out, to enlarge it a little, as shown in the image below.

Image 106

We can see that there is a list of titles (available video streams), & the first thing you may say, if you have read the guidelines... Is that all the titles start with a capital, & the guidelines state that "List titles & items" should not be capitalised. And a full list of what should, & shouldn't be capitalised is available in the guidelines. It is difficult to say what to do, with lists that are generated dynamically from streamed content. As there is no 100% full proof method of parsing these to ensure correct capitalisation (or not), as reformatting them all to lowercase would be wrong when dealing with names & acronyms... So I will leave that ball in Microsoft's court, await direction, & leave the list items as they are.

Now before I start setting up the "Pivot Control", I need to remove/correct a little error with the LayoutRoot Grid.

So select the LayoutRoot element, & with the manipulation handles visible, look in the top left corner. As shown in the image below.

Image 107

There is a Grid Row Divider in the image above, that is set to Auto, & therefore Collapsed.

Select the Row Divider in the Artboard, & drag it down to the bottom of the title area. Or go to the XAML & set a Height of 64, as shown in the image below.

 Image 108

If you dragged the Row Divider down, change the Row from "Auto" to "Fixed" size by clicking on the icon next to it twice. Next in the Advanced properties of the Layout section, change the Height to 64.

Image 109 

(It's definitely easier to edit the XAML directly...)

Now select the Grid named TitleGrid & move it up into the first Row of the LayoutRoot, Reset the Margins & ensure the Alignments are set to Stretch.

Next select the Grid named ContentGrid & Reset the Margins, so it occupies the second Row of the LayoutRoot.      

That should fix the general Layout now, so we can make a start on the Playlist ListBox...

So select the ListBox, rename it to "PlayList" & drag it onto the LayoutRoot. So it looks like the image below.

Image 110

Now position the PlayList ListBox, so it completely fills the second Row of the LayoutRoot, as shown in the image below.

Image 111

Next to think about what we can do to style the PlayList ListBox...

But before we start, I would like to consider how the Phone ListBox differs from the standard ListBox. For a start the ScrollBar is a lot smaller, & not really selectable. And it doesn't need to be, as Microsoft have integrated the "Flick" gesture into the Phone ListBox to scroll Up & Down. Thus saving us the trouble of worrying about adding "Flick" gestures to the ListBox (Thanks Microsoft!). The next thing to consider with a "Touch" interface, is that there is no MouseOver State for this ListBox. And why would there be? The touch screen has no knowledge of a finger hovering over the screen, & this should be remembered why trying to use Behaviors as well. As some Behaviors you may want to use (even just in the emulator) will not work with MouseEnter & MouseLeave as Event Triggers. The Guidelines also state that  "Dynamic elements should avoid using Drop Shadows" & currently I can see that Michael has been playing & added a Drop Shadow to the ListBox items (Bad Developer!) LOL  

But enough boring guidelines stuff, let's start Styling the ListBox and see what we can do to make it a little more appealing. Probably not a lot if we want to stay within the guidelines...

So select the PlayList ListBox, right click & choose Edit Additional Templates > Edit Generated Items > Edit Current.

Image 112

In the Objects and Timeline expand the TextBlock, select the DropShadowEffect & delete it.

Image 113

Now select the TextBlock & in the Text properties, Reset the Font Size. As this is probably the last place to set the Font Size. (Bad Developer!) LOL

Image 114

(Michael was just messing around & setting up a workable Font Size, but it should not really be set here - Basically he was expecting me to start from scratch, & not use his existing test sample).

In the Artboard, the Text Size has now reduced is size, but we will get to this in a moment...

So come out of the Edit Generated Items Template.

Now right click, & choose Edit Additional Templates > Edit Generated Item Container > Edit a Copy.

 Image 115

Give this new Style a name like PhoneListBoxItemStyle, & hit OK.

Image 116

Now we have generated a Style for the ListBox Items, go to the Style of the Item Container Style using the BreadCrumbBar.

Image 117

In the Style go to the Text properties, & set the Font Size to Local Resources > PhoneFontSizeLarge

Image 118

This is where the Text Size should be set & modified. (if needed...)

Now go back into the Generated Item Container Template (ItemContainerStyle).

Select the State Manager to see all the possible States for the ListBox.

Image 119

What you should notice, is that this ListBox has all the States that you would find in a normal ListBox, but as I said earlier. The MouseOver State is not useable on a "Touch" interface, be that the Phone, or possibly a touch interface monitor for Windows itself. So even though, we have certain options available to use, we ALWAYS  need to consider the user, & the intended environment for the application. Key information & interaction should never be used in areas that may not be fully supported by all environments. For example a "Double Tap" Touch gesture may not be supported in all situations (such as here) meaning we are using a singe click to denote selection. This means that "Focused" is not really a valid or useable State, as we cannot have something in "Focus" that is not also "Selected". It is easy to take for granted the interaction we are used too in normal PC situations. As "double click" & keyboard interaction is like second nature to most of us, & it will take us all a while to get used to the different considerations of a "Touch Screen" interface, especially when we currently only have an emulator to work with...    

So the only 2 States we can really work with, are the "Selected" & "Disabled" States which are pretty much already set for us. We shouldn't really play with the "LayoutStates" (Loaded & Unloaded), as this will probably interfere & detract with the "Pivot Control", as well as make this tutorial even longer... So let us do only tiny tweak & move on. (Although I may do more in the finished project download, but only things I have covered in my previous tutorial: ListBox Additional Templates).

In the "Base" State click on the small black circle next to the "Selected" State, to show this State (signified by the Eye icon), but not set any Keyframes.

Image 120

In the Objects and Timeline select the Highlight element & set a Top Margin of 8 to centre the blue "Highlight" band better on the text.

Image 121

That is all I want to do here, & there is obviously more that could be done. But keep in mind what I said before about a consistent "Look & Feel" with regards the "Metro" styling. And this tutorial is definitely long enough, with too much content here...

 

Setting up the Pivot Control & Gestures

To make the Playlist "slide-in" from the Right, & the Player "slide-out" to the Left we will use Visual States.

(So come out of any Templates that you are currently in, ensuring you can see the LayoutRoot & its 3 child elements (TitleGrid, ContentGrid & Playlist)).

Start by rename the ContentGrid to "Player".

Image 122

Now expand the Player Grid to reveal the MediaElement, & the 3 "EventToCommand's" Michael has setup.

Image 123

Now to test the "Flick" gestures that Michael has added in the code "View Model", he has wired them up to control the Play & Stop functions of the Video Player. And to ensure they work on the screen area displaying the video, he has attached them to the MediaElement. Now I don't want these "Flick" gestures to control the video, as this overrides the function of the "Pivot Control" & a big "No No" with regards the Guidelines. So delete the FlickRight_Play & FlickLeft_Stop EventToCommand's, but do not delete the SetMediaOpened EventToCommand, as we still want this one.

It is worth remembering this "Behavior" is something that the designer is able to set, & should be setting. The developer has given you a framework of hooks that you can bind too. And as a designer can do it in Blend, it is their responsibility to use what the developer has provided & link things up using "Point & Click". So if you are a new designer, investigate how the UI elements are "wired" by looking at these Behaviors, as they are the very powerful & the life blood of Blend for a designer. As I edit this Michael has just been telling me about a new powerful Behavior/feature DataStore.

So remember this designers: Your developer will/should, be very happy to help you through the more technical aspects of wiring things up, & the only condition they will/should apply is: Don't ask them the same questions again & again! - LEARN!!! (P.S. To the coders: Be kind to the ignorant, but do what you will with the stupid...(Except me!) LOL)

Now select the LayoutRoot element, go to the Assets tab & select the Behaviors.

Image 124

Next select the "GoToNextState" Behavior & drag it onto the LayoutRoot.

Image 125

While we are here, drag a "GoToPreviousState" Behaviour onto the LayoutRoot as well.

Image 126

By adding these Behaviors to the LayoutRoot, the Behaviors will be Triggered/Fired when the LayoutRoot (Whole Screen) is interacted with. And now we need to set some States for these Behaviors to go between/interacted with...

(A true "Pivot Control" should be able to loop, & not an easy task. So will not be done here, just a basic page switch, & far more like a "Panorama" as discussed in the Guidelines. As I understand it, a "true" predefined "Pivot Control" should hopefully be coming).

So go to the States tab & click on the "Add state group" icon, as shown in the image below.

Image 127

This will add a "VisualStateGroup" to the project, which we will call "ShowOrHidePlayList"

Now click on the "Add state" icon twice to add 2 States to this StateGroup.

Image 128

Rename these 2 new States to "ShowPlayer" & "ShowPlayList", as shown in the image below.

Image 129

Now ensure you are in the "Base" State, & in the Objects and Timeline select the PlayList ListBox.

In the Transform section of the Properties tab, set a Translate of 800 for the X axis.

Image 130

In the Artboard, this will move the PlayList ListBox along the X axis, just like the image below.

Image 131

Now in the States Manager (VSM) with the PlayList ListBox selected, choose the "ShowPlayList" State & change the Transform Translate X axis back to 0.

Image 132

Next select the "Player" Grid in the Objects and Timeline, & set a Transform Translate of -800 on the X axis.

The Artboard should now look like the image below.

 Image 133

Now set a Duration for the Transition on the "ShowOrHidePlayList" State Group of say 1 second, & any EasingFunction you fancy. I have used a "Back InOut", as shown in the image below.

Image 134

Now you can Run (F5) your application, to review the results & hopefully see the Player & PlayList slide in & out using mouse clicks. But we do not want to use mouse clicks for this operation, we want "Flick" gestures to switch between screens/pages.

(Note: We are not actually firing the triggers in a toggle (alternating) manner, just looping round & round - I Think...)

So select the "GoToNextState" Behavior we set on the LayoutRoot, & in the Properties tab find the TriggerType & select "New"

Image 135

In the Popup window, select the "FlickGestureTrigger" & hit OK.

Image 136

Now in the Trigger pane of the Properties tab, change the Direction to "Left", as shown in the image below.

Image 137

Now select the "GoToPreviousState" & repeat the whole process, but this time set the direction to "Right".

When the application is now Run, only a "Flick" Left or Right will change between the Player, or the PlayList. - Sorted!!!

But this is not the whole "Pivot Control" finished, as we need to think about the title area of the Player & PlayList. This should change along with Player & the PlayList, to show which section/page of the "Pivot Control" we are on.

So select the TitleGrid Grid & look at the Background colour. Notice it is a dark Grey & this was set (I presume) by Michael while setting up the general components of the Video Player. While this may be fine, it gives me a chance to discuss another consideration when designing for the Windows 7 Phone. And that is battery life! As obviously displaying anything other than Black will use up precious battery capacity, & using White will obviously/probably be the worst. Also this is a Video Player which will probably chew the battery faster than anything else... So my personal opinion, is to set the Title area to Black to reduce battery consumption, & not to detract from the focus of the application, which is to play videos... (Although I reserve the right to change my mind regarding the background colour!)

So with the TitleGrid still selected, change the Background to the Brush resource PhoneBackgroundBrush. (Ensure you are back in the "Base" State).

Image 138

Now expand the TitleGrid, select the TextBlockListTitle & set the Foreground Brush to PhoneForgroundBrush.

Image 139

Now change the TextBlockListTitle Text to "video player" all lowercase, as the Guidelines state that "Page titles" should be all lowercase. However in our situation it is not as cut & dry as that. As the Guidelines also state that "Application titles" should be all Uppercase. But we don't really have enough room in our Video Player for both an Application title & a Page title. As it would compromise the viewing are of the video display, & this is definitely not what we want to do... So I am making the decision that we will view our "Title text" as "Page titles" & hence all lowercase.

Next go to the Font Size & set this to Local Resource > PhoneFontSizeLarge.  

Image 140

And set the Font to Local Resource > PhoneFontFamilyNormal.

Image 141

The Font is not actually part of the Theme, so changing the Theme will do nothing to the Font, but as long as the Font is tied/bound to the PhoneFontFamily Resource, we can change it all in one place.

Now ensure the TextBlockListTitle is Left & Top Aligned, with a Margin of 20 on the Left side.

Next rename TextBlockListTitle to "TextBlockPlayerTitle", & then duplicate it using Copy & Paste.

Rename the duplicated TextBlock to "TextBlockPlayListTitle" & change the text to "video playlist". (All lowercase).

And in the Base State, set a Translate of 800 on the X axis for the TextBlockPlayListTitle.

In the ShowPlayList State, change the Translate back to 0, select the "TextBlockPlayerTitle" & set a Translate on the X axis of -800.

This will make the page titles change, along with the Player & PlayList. Which is fine, but we can do more... Like showing which Video/Stream is playing while we are in the Player view. As well as providing additional/alternative navigation to the Flick gestures between the Player & Playlist screens/pages. The guidelines show, that it is good idea to provide a hint of the next page, by having the edge of the page visible on the right hand side of the screen (Panorama). But that is not really appropriate on a Video Player, as the whole of the screens should really be devoted to showing/playing the video. Now we could show part of the PlayList title in the top right corner of the Video Player screen/page. But this will be a little messy when changing between screens, & not as clear as alternative methods like showing an icon. So enough chat, let us get on with it...

Now ensuring you are in the Base State, select "TextBlockPlayerTitle" & choose Group Into > StackPanel.

Image 142

Rename the StackPanel to "PlayerTitleAndInfo", change the Orientation to Horizontal & ensure the Margins are 0 except for a Margin of 20 on the Left side. (The Horizontal Alignment should be Left, & the Vertical Alignment should be Stretch).

Expand PlayerTitleAndInfo to reveal TextBlockPlayerTitle & duplicate it using Copy & Paste.

Rename this duplicate to "TextBlockSpacer", & set the Text to " - ". ("space", "minus" sign, "space").

Duplicate this element again, & rename the new element to "TextBlockPlayerInfo", as shown in the image below.

Image 143

The TextBlockPlayerInfo is to show the currently selected video title, & to do this, we need to Data Bind to the SelectedValue of the PlayList ListBox. But in order to do this, we need to convert the format of the SelectedValue of the PlayList ListBox from an Object to a String. Se we need to go cap in hand, back to the developer (Michael) & say: Please Sir, can I have a ValueConverter please? And as long as your Developer is in a good mood, it should take them just a minute to knock one up for you! So download the VideoToVideoTitleConverter & add it to the Project.

Select TextBlockPlayerInfo in the Advanced options of the Text property, choose Data Binding...

Image 144

In the Popup window, choose the Element Property tab, select PlayList, choose the SelectedItem property, then the VideoToVideoTitleConverter, & finally hit OK.

Image 145

Now change the Font to the Local Resource PhoneFontFamilyLight.

Image 146

In the Artboard, the title area should look like the image below.

Image 147

Run the application to review the results, & we have a slight problem when we use the "Flick" gestures to switch between the Player & Playlist pages. The TextBlockPlayerTitle moves, but TextBlockSpacer & TextBlockPlayerInfo do not when we switch pages. So go to the State Manager (VSM) & in the PlayList State delete the RenderTransform in the Objects and Timeline, that is attached to the TextBlockPlayerTitle. Instead select the parent StackPanel (PlayerTitleAndInfo) and set a Translate of -800 on the PlayerTitleAndInfo StackPanel. And that should fix the problem...

So we are now displaying the selected video along the top of the screen, & this works fine with short titles, but we need to consider what will happen with a very long title. And I can tell you that it will spill over onto the PlayList page/screen. So we need to ensure that this doesn't happen, & the easiest way to do this is to set a Fixed size for the parent StackPanel. And this is fine as long as the Video Player is always in Landscape mode, but won't work if the Video Player is later required to work in Portrait mode. (As it will again spill over onto the PlayList page). So instead we will leave the StackPanel as "AutoSized", but set a Margin for the Right side, (as well as the Left side).

So select the PlayerTitleAndInfo StackPanel, change the Horizontal Alignment to Stretch & set a Margin on the Right of 60.

(The reason I want such a large Margin on the Right, is because I want to put a icon in the Top Right corner of the title area). 

But before we do that, I want to tweak the size of the Title area, in comparison to the MediaElement (Video screen). As currently the Title area is a little larger than we need, & this is compromising the size of the MediaElement & the focus of this application.

So select the LayoutRoot element & adjust the Row Divider up a little, to enlarge the MediaElement display area. Alternatively, change the XAML directly so that the first RowDefinition is about 52 pixels, as shown in the image below.

  Image 148

Next download the ArrowIcon from here & add it to the Project.

Copy the ArrowIcon Path into the TitleGrid area of the MainPage, & rename it to "ArrowIconRight".

Now give it a fixed size of 32 for both the Width & Height, & change the Stoke to the PhoneForgroundBrush.

Next go the Fill & change the Alpha to 0%. - Do not remove the Fill "No Brush" as this will make the ArrowIconRight harder to select. Although this will probably not make any difference with a Touch interface, it will however make a difference in the emulator, where it would be possible to click within the circular area of the icon & miss a selectable area with the mouse pointer.

Next set the Horizontal Alignment to Right, & the Vertical Alignment to Stretch.

Finally ensure all the Margins are 0, except for the Right, which should be set to about 10 pixels.

The Artboard should now look like the image below.

Image 149

Now go to the Assets tab, & drag a GoToStateAction Behavior onto the ArrowIconRight.

In the Triggers section of the Action, leave the EventName as it is, & change the StateName to "ShowPlayList", as shown in the image below.

Image 150

This will give the user an alternative method of navigation to the PlayList, but we also need an icon on the Playlist page, to return to the Player page.

So duplicate the ArrowIconRight, & rename it to "ArrowIconLeft".

In the Transform section, Flip ArrowIconLeft along the X axis, as shown in the image below.

Image 151

Now select the "GoToStateAction" of the of the ArrowIconLeft.

Image 152

And in the Trigger section, change the StateName to "ShowPlayer"

Image 153

Select ArrowIconLeft again, & in the Base State, set a Translate of 800 along the X axis.

Now go to the PlayList State, & set the Translate back to 0 for the X axis.

And then while still in the PlayList State, select the ArrowIconRight & set a Translate of -800 on the X axis.

Hopefully when you run the application, it all works fine!

  

Video Player Controls

Now to look at the controls that we styled earlier, so that they can be hidden when not in use. And consideration should be given to the best possible user interaction. For example, we want to show the controls when the Video Player is started, but not require the user to do anything to remove/hide them & enjoy the video/movie. (So we effectively need to put them on a timer when the video is started). We also need to consider that the user may not want to wait for the controls to "fade" out of view on the timer. So we also need a mechanism that will allow this, as well as a mechanism to display the controls when the user wants to use them. We also need to ensure that while making the controls appear, the user doesn't accidently select any of the controls. As a users patience will wear thin. Especially if they accidently cause the video to go back to the beginning, while they were only wanting to pause the movie or adjust the volume. User interaction & user experience can only really be gauged & improved from user feedback, but we should try our best to give the user the best product as possible as the starting point.

All I have stated above, are based on assumptions & my own personal experiences. These may be right, or they may be wrong. But until we have a real phone, & put it in the hands of a user, my assumptions are all I have. The other limiting factor here, is that I will be doing everything without any code, & while Blend is great, it may require some custom manipulation & code to get the best user experience for the Video Player user interaction. So while I am not 100% happy with what I'm about to do, it will be good enough to gauge user feedback to make improvements to the user experience. And user experience is all that really matters...

We could use Visual States to manipulate the showing & hiding of the player controls. But we are already using Visual States to navigate between the Player & Playlist screens/pages. And as this navigation already uses Behaviors that "GoToNextState" & "GoToPreviousState", it could interfere with any other States we add. So instead I will use Storyboards to manipulate the player controls, and Storyboards have the additional advantage of easily allowing a duration/timer to be set at any point of the Storyboard.

As you would expect, we are going to use 2 Storyboards. (One to show the player controls, & one to hide the player controls). The Storyboard that will show the player controls, will do so on a timer, & after a set duration, will hide the player controls. So lets make a start...

But before we start adding Storyboards, we first need a couple of elements to use as Triggers for the Storyboards. These will be transparent Rectangles (A Fill with 0% Alpha). The reason we will need 2 of them, is to create a Toggle arrangement for the show/hide behaviour of the player controls. It is not possible to attach 2 different Behaviors/Triggers to a element/object in Blend & expect them to be fired in an alternating manner. So what we will do is attach one Behaviour/Trigger to each, & when the Trigger for the front Rectangle is fired, we will start our Storyboard, & at the same time shrink/move this Rectangle to reveal the second Rectangle Behind. When the user clicks again, the Trigger on the second Rectangle will be fired & while we start our second Storyboard, we will reinstate the first Rectangle. Thus generating a Toggle type of arrangement for the mouse click, or user "Touch" gesture. Simple! 

So in the Objects and Timeline select the Player element, & insert 2 Rectangles naming them "ShowPlayerControls" & "HidePlayerControls"

Image 154

Remove the Stroke on both Rectangles, & set the Fill to Black with 0% Alpha for both Rectangles.

Now set the Horizontal Alignment to Stretch & Vertical Alignment to Bottom. As well as the Width to Auto & the Height to 180 pixels.

Image 155

Next select the Player element again & insert a TextBlock containing the text "Click in shaded area to show/hide player controls" & rename the TextBlock to "TextBlockShowAndHideControls".

Set the Horizontal Alignment to Center & the Vertical Alignment to Bottom, with a Margin of about 100 pixels on the Bottom, & 50 pixels for the Left & Right sided.

(The reason I am setting Margins for the Left & Right sides, is because I want to consider what would happen if the Video Player later supports Portrait mode. As without Margins, the text would lap over the edges of the screen. And we also need to consider how the text would Wrap if we supported Portrait mode).

 So go to the advanced properties of the Text properties, & set the Text Alignment to "Center" & and ensure the TextWrapping is set to "Wrap".

Image 156

Now set the Foreground colour to the Resource PhoneForegroundBrush, & the Font Size to Local Resource > PhoneFontSizeLarge.

 Finally in the Object and Timeline, arrange the items in the Player Grid as: MediaElement, ShowPlayerControls, TextBlockShowAndHideControls, HidePlayerControls, PlayerControls, as shown in the image below.

 Image 157

Hopefully the Artboard should look like the image below.

Image 158

(In the image above, I have one of the transparent Rectangles selected, just to show it's positioning).

Select TextBlockShowAndHideControls & change the element Opacity to 0% to make it invisible.

Now go to the Objects and Timeline & click on the + icon to add a new Storyboard to the Project.

Image 159 

In the Popup window give the Storyboard a name like "ShowPlayerControlsOnTimer" & hit OK.  

  Image 160

This will open the Storyboard timeline, & hit F6 to change the view in Blend to the "Animation Workspace"  

At 0.1 seconds on the Timeline, select the HidePlayerControls element & set a Keyframe, as shown in the image below.

Image 161

Now select the PlayerControls & also set a Keyframe at 0.1 seconds by changing the element Opacity to 0%.

(Modifying an element while in a Storyboard will automatically generate a Keyframe for that element).

At 0.0 seconds on the Timeline select the PlayerControls element, change the Opacity to 0% & in the Transform section, set a Translate in the Y axis of 200 pixels.

Image 162

This will move the PlayerControls off the bottom of the screen, & therefore not selectable while they are hidden (invisible).

Now select the HidePlayerControls element, & in the Transform section, set the Scale to 0 for the Y axis.

Image 163

And the Center Point to 1 for the Y axis.

Image 164

(This will start the Storyboard with the front Rectangle "Collapsed" at the bottom of the screen, and the back Rectangle (ShowPlayerControls) able to accept mouse clicks or "Touch". It may not actually be needed, but the animation is easier to follow with the Rectangle starting the animation "Collapsed").

Now move the Timeline to 0.5 seconds & with the PlayerControls selected, change the element Opacity back to 100%.

Image 165

Now move the Timeline to 12.0 seconds & with the PlayerControls still selected, set another Keyframe.

Next move to 12.5 seconds on the Timeline, & change the element Opacity of PlayerControls to 0%.

Select the HidePlayerControls element & also record/set a Keyframe at 12.5 seconds.

Image 166

Now with HidePlayerControls still selected, go to 12.6 seconds on the Timeline & change the Scale to 0 for the Y axis, & the Center Point to 1 in the Y axis.

Next select the PlayerControls again & in the Transform section, set a Translate of 200 pixels for the Y axis.

Image 167

This completes the basic animation we need to display the Video Player controls when a video is first loaded. From fading them in, to displaying on a timer, & fading them out again. We have also set up the actions we need to move the front Rectangle (HidePlayerControls) out of the way, to reveal the back Rectangle (ShowPlayerControls) that will generate our Toggle behaviour. Now we just need to provide a visual clue to the user on how to operate the Video Player controls...

So change the Timeline to 13 seconds, select the ShowPlayerControls element & set a Keyframe.

Next select TextBlockShowAndHideControls & also set a Keyframe at 13 seconds.

Move the Timeline to 13.5 seconds, & still with TextBlockShowAndHideControls selected, change the element Opacity to 100%.

Select ShowPlayerControls & also at 13.5 seconds on the Timeline, change the Alpha of the Fill to 30%

Image 168

The Artboard should look like the image below, at 13.5 seconds of the "ShowPlayerControlsOnTimer" Storyboard.

Image 169

Move the Timeline to 16.0 seconds & set a Keyframe for both the ShowPlayerControls, & the TextBlockShowAndHideControls elements.

Next move the Timeline to 16.5 seconds, & change the element Opacity of TextBlockShowAndHideControls to 0%.

Finally select the ShowPlayerControls element, & change the Alpha of the Fill back to 0%.

Image 170

And that is that for this Storyboard, so close it using the X icon, as shown in the image below.

Image 171

The next Storyboard is thankfully simpler, and this one is simply to hide/fade out the Video Player controls, and finish off the Toggle behaviour of the Rectangles.

So create another Storyboard using the + icon as we did before, name this Storyboard to "HidePlayerControls" & hit OK.

Image 172

At 0.0 seconds on the Timeline, select HidePlayerControls & set a Keyframe. And do the same for PlayerControls.

 Next with HidePlayerControls selected, go to 0.1 seconds on the Timeline & change the Scale to 0 for the Y axis, & change the Center Point to 1 for the Y axis.

Next go to 0.5 seconds on the Timeline, & change the element Opacity of PlayerControls to 0%

Move the Timeline to 0.6 seconds & set a Translate in the Y axis of 200 pixels.

The Timeline should look like the image below.

Image 173

Close the Storyboard using the X icon, just like we did before.

So now we have the Storyboards, we need to attach the Behaviors/Triggers that will fire & control the Storyboards. And we will need 3 in total: One to start the "ShowPlayerOnTimer" when a video is loaded, one to hide the PlayerControls, & finally, one to show the PlayerControls.

So go the Assets tab, & drag a "ControlStoryboardAction" onto the MediaElement, as shown in the image below.

Image 174

In the Triggers section, change the EventName to "MediaOpened", & set the Storyboard that will be played to ShowPlayerControlsOnTimer.

Image 175

Next drag another "ControlStoryboardAction" onto ShowPlayerControls.

Image 176

In the Triggers section, leave everything as it is, except for setting the Storyboard to ShowPlayerControlsOnTimer.

Image 177

Finally drag another "ControlStoryboardAction" onto HidePlayerControls.

Image 178

In the Triggers section, leave everything as it is, except for setting the Storyboard to HidePlayerControls.

Image 179

Run your application to review the results!

We should have all the basic interaction needed, although some fine tuning could be done. For example when a movie is selected in the Playlist ListBox, it is opened by the MediaElement & played. Now image that you do not return to the player screen for a little while, & by then, the Video Player controls have faded out on its timer. And it's hard to say if this is a good thing, or a bad thing... As a user may feel this is wrong while they are getting used to using the Video Player, but at the same time it may become annoying to the user, if the controls automatically become visible every time the media is changed. Only testing will tell. But for this demo application, I think it is best to leave things as they are, not I'm not say it is right or wrong...

 

Final Tweaks

That is about it for this demo Video Player application, & remember that this is a demo! Not a hard & fast set of rules when designing for the Windows 7 Phone. I also don't believe that Microsoft have finalised the guidelines, & these may very well change in time...

Looking back at this demo application I can see a few things that I'm not quite happy with. The most obvious of these is the Playlist ListBox. As the page title looks almost the same as the list itself! So I will make a quick edit to this, so that it is easier to differentiate between the page title & the list itself. The most obvious way to do this is to change the background of either the page title, or the ListBox. If I change the title area background, I would also really need to change the background of the player to make it consistent. And as I said before about battery consumption, this is probably not the best idea, although a dark grey may not be too bad regarding power consumption. It is probably better to change the background of the ListBox, as the ListBox is probably not be in view very often, & therefore power consumption considerations are not really an issue. As we are currently using Black as the background of the ListBox, I will obviously need to lighten the ListBox background. And I can do this in 2 ways, either by using a Grey (or semi-transparent White). Or by using a colour or semi-transparent colour... Now we have already discussed that there are 4 Theme colours (5 if you include the reserved manufactures colour). So I need to consider how any colour I apply will work when the Theme is changed. And the obvious answer is to use the current Theme colour, or a hint of the current Theme colour.

So go to the PlayList ListBox & choose Edit Additional Templates > Edit Generated Item Container > Edit Current.

Image 180

 Duplicate the Highlight element, rename this to "BackgroundHint" & place it behind the Highlight element.

Image 181

Change the Visibility to Visible, & set the element Opacity to 10%.

Image 182

In the Artboard, the PlayList ListBox should look like the image below.

 Image 183 

This is not the most elegant of solutions, but this is more an exercise on reinforcing the considerations required for Themes & battery life.

I may try & make this screen a little more elegant in the downloadable demo version, but that will do for this tutorial.

The other think I want to tweak is the area that is selectable, & able to hide or show the Video Player controls. As it stands, only the area around the Video Player controls are clickable/touchable. Yet the top half of the Vide Player controls (ProgressBar & ProgressDisplay) currently have no interaction available to them. But because they have "IsHitTestVisible" turned on by default, they interfere with anything behind (in the Z order) from being clicked or "Touched" on. The same is true for the TextBlockShowAndHideControls, which while invisible most of the time, still prevents the ShowPlayerControls Rectangle behind from being clicked or "Touched".

So in the Objects and Timeline, select ProgressInfo & in the advanced properties of Common Properties turn off (Uncheck) the IsHitTestVisible check box.

Image 184

 We do not need to worry about turning off the IsHitTestVisible on all the child elements, as they will inherit this property from the parent ProgressInfo element 

Now repeat the step for TextBlockShowAndHideControls, turning off IsHitTestVisible.

You may now be wondering why the "Flick" gestures still work, as they are behind (in the Z order) of all the other elements. And the honest answer is because I don't know for sure, but my guess is that because they monitor motion, as well as the click or "Touch" interaction, & hence work in a completely different way to most Triggers.

 Next I want to tweak the Storyboards a little, as the show/hide isn't working quite properly. As currently the "ShowPlayerControlsOnTimer" Storyboard continues to play, even though the "HidePlayerControls" Storyboard has been started when the user wants to hide the player controls.

Now the most obvious thing to do, is to attach another "ControlStoryboardAction" to the HidePlayerControls Rectangle.

So do this, & set the ControlStoryboardOption to "Stop" & the Storyboard to "ShowPlayerControlsOnTimer".

Image 185

Next open the ShowPlayerControlsOnTimer Storyboard, & drag the end Keyframes for the HidePlayerControls Rectangle to the end of the whole Storyboard, as shown in the image below.

Image 186

(This will prevent the ShowPlayerControls from being selectable, until the ShowPlayerControlsOnTimer has ended).

Finally go to the HidePlayerControls Storyboard & set Keyframes at 0.0 seconds for the ShowPlayerControls & TextBlockShowAndHideControls elements.

Image 187

This will ensure that these elements are set to the correct state when the animation is started. As they are modified in the ShowPlayerControlsOnTimer Storyboard, & may not be in there correct state otherwise.

And that is just about it for this demo & tutorial.

img40.jpg

Hope it was useful... & please Vote!

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) http://ADefWebserver.com
United States United States
Michael Washington is a Microsoft MVP. He is a ASP.NET and
C# programmer.
He is the founder of
AiHelpWebsite.com,
LightSwitchHelpWebsite.com, and
HoloLensHelpWebsite.com.

He has a son, Zachary and resides in Los Angeles with his wife Valerie.

He is the Author of:

Written By
User Interface Analyst
United Kingdom United Kingdom
I've been playing with computers since my first Acorn Electron, & after blowing up a few ZX Spectrums. I moved on to the C64 & Amiga, & eventually reluctantly on to the PC.

I have learnt a wide set of skills during my 38 years of existence, living in the UK, on the sunny south coast.

My main area of expertise is Graphic/Visual Design, Usability & UI Design. I am not a programmer, but am fairly technically minded due to studying Mechanical Engineering at Uni.

I have work both Freelance & for IBM as a Graphic Designer, & am skilled in the usual graphics packages like, PhotoShop, CorelDraw or Illustrator, Premier, Dreamweaver, Flash etc.
But I originally started with Lightwave & 3D animation.

Comments and Discussions

 
QuestionTouch Target overhang Pin
Kelso Sharp23-Mar-13 13:36
Kelso Sharp23-Mar-13 13:36 
AnswerRe: Touch Target overhang Pin
defwebserver23-Mar-13 18:39
defwebserver23-Mar-13 18:39 
GeneralMy vote of 5 Pin
Rahul Rajat Singh12-Dec-12 20:21
professionalRahul Rajat Singh12-Dec-12 20:21 
GeneralRe: My vote of 5 Pin
defwebserver16-Dec-12 13:34
defwebserver16-Dec-12 13:34 
QuestionUpgraded WP 8 version rocks as well Pin
Member 165621412-Dec-12 8:36
Member 165621412-Dec-12 8:36 
AnswerRe: Upgraded WP 8 version rocks as well Pin
defwebserver12-Dec-12 13:09
defwebserver12-Dec-12 13:09 
GeneralMy vote of 5 Pin
Abinash Bishoyi27-Aug-12 3:11
Abinash Bishoyi27-Aug-12 3:11 
GeneralMy vote of 5 Pin
Florian Rappl22-Feb-12 5:55
professionalFlorian Rappl22-Feb-12 5:55 
Just delightful!
QuestionMy vote of 5 Pin
Akram El Assas14-Jan-12 0:11
Akram El Assas14-Jan-12 0:11 
GeneralMy vote of 5 Pin
Filip D'haene20-Nov-11 5:13
Filip D'haene20-Nov-11 5:13 
GeneralRe: My vote of 5 Pin
defwebserver20-Nov-11 5:17
defwebserver20-Nov-11 5:17 
Questionone question about the file played Pin
Sparkling_ouc5-Sep-11 17:22
Sparkling_ouc5-Sep-11 17:22 
AnswerRe: one question about the file played Pin
defwebserver5-Sep-11 18:28
defwebserver5-Sep-11 18:28 
GeneralRe: one question about the file played Pin
Sparkling_ouc5-Sep-11 21:40
Sparkling_ouc5-Sep-11 21:40 
GeneralRe: one question about the file played Pin
defwebserver6-Sep-11 2:36
defwebserver6-Sep-11 2:36 
GeneralMy vote of 5 Pin
decyclone24-Feb-11 20:09
decyclone24-Feb-11 20:09 
GeneralMy vote of 5 Pin
Kanasz Robert12-Jan-11 1:47
professionalKanasz Robert12-Jan-11 1:47 
GeneralGreat work Pin
thatraja8-Jan-11 4:43
professionalthatraja8-Jan-11 4:43 
GeneralRe: Great work Pin
defwebserver8-Jan-11 4:48
defwebserver8-Jan-11 4:48 
GeneralGood work Pin
PavanPareta5-Jan-11 23:57
PavanPareta5-Jan-11 23:57 
GeneralRe: Good work Pin
defwebserver6-Jan-11 2:14
defwebserver6-Jan-11 2:14 
GeneralMy vote of 5 Pin
Shahriar Iqbal Chowdhury/Galib16-Nov-10 23:32
professionalShahriar Iqbal Chowdhury/Galib16-Nov-10 23:32 
GeneralRe: My vote of 5 Pin
defwebserver6-Jan-11 2:14
defwebserver6-Jan-11 2:14 
GeneralMy vote of 5 Pin
raju melveetilpurayil16-Nov-10 11:12
professionalraju melveetilpurayil16-Nov-10 11:12 
GeneralRe: My vote of 5 Pin
defwebserver6-Jan-11 2:15
defwebserver6-Jan-11 2:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.