2. Visual State Manager
The Visual State Manager (VSM)
is a tool available within Expression Blend. It allows the developer /
designer to visually define Visual State Groups that represent UI state
for controls in that state, represented as a Storyboard. The best way to learn how to work with the VSM is by demonstration, most of which will be in Expression Blend.
2.1. Orientation Aware
A Grid containing a MediaElement control named mediaPlayer is added to the ContentPanel Grid. Below the Grid containing the MediaElement, a ListBox named videosListBox is added and the Application Bar is enabled. The Application Bar is wired up to provide video controls for the mediaPlayer MediaElement.
A Model named Video is added to the Model folder and a collection of Video objects is added to the MainViewModel class. Finally three videos are added to a folder named Content and added to the project. Figure 4 shows the VSMVideoPlayer project in Expression Blend with the states tab opened.
The videosListBox is data bound to the Videos collection on the MainViewModel. The Grid containing the MediaElement is data bound to the SelectedItem of the videosListBox. The Source property for the mediaPlayerMediaElement is data bound to the Url property of the SelectedItem Video object. Run the project and when you select a video in the videosListBox it plays in the MediaElement. Listing 3 shows the XAML for the Content Grid and Application Bar from MainPage.xaml.
Example 3. Content Grid and Application Bar Code
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel d:LayoutOverrides="Width">
<Grid Height="213" DataContext="{Binding SelectedItem, ElementName=videosListBox}"> <MediaElement Source="{Binding Url}" Margin="5,9,7,-9" Name="mediaPlayer" MediaFailed="mediaPlayer_MediaFailed" Stretch="UniformToFill" /> </Grid> <ListBox x:Name="videosListBox" ItemsSource="{Binding Main.Videos}" Margin="12,24,0,0" ItemTemplate="{StaticResource VideoDataTemplate}" /> </StackPanel> </Grid> </Grid> <phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton x:Name="rewindAppBarBtn" IconUri="/icons/appbar.transport.rew.rest.jpg" Text="rewind" Click="rewindAppBarBtn_Click"/> <shell:ApplicationBarIconButton x:Name="stopAppBarBtn" IconUri="/icons/appbar.transport.pause.rest.jpg" Text="pause" Click="stopAppBarBtn_Click"/> <shell:ApplicationBarIconButton x:Name="playAppBarBtn" IconUri="/icons/appbar.transport.play.rest.jpg" Text="play" Click="playAppBarBtn_Click"/> <shell:ApplicationBarIconButton x:Name="ffAppBarBtn" IconUri="/icons/appbar.transport.ff.rest.jpg" Text="fastforward" Click="ffAppBarBtn_Click"/> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>
|
Listing 4 shows the MainPage.xaml.cs code-behind file where the event handlers control the mediaPlayer MediaElement.
Example 4. MainPage.xaml.cs Code File
using Microsoft.Phone.Controls; using System; using System.Windows;
namespace VSMVideoPlayer { public partial class MainPage : PhoneApplicationPage { // Constructor public MainPage() { InitializeComponent(); }
private void rewindAppBarBtn_Click(object sender, System.EventArgs e) { if (mediaPlayer.CanSeek) { mediaPlayer.Position = mediaPlayer.Position - new TimeSpan(0, 0, 5); mediaPlayer.Play(); } }
private void stopAppBarBtn_Click(object sender, System.EventArgs e) { mediaPlayer.Pause(); }
private void playAppBarBtn_Click(object sender, System.EventArgs e) {
mediaPlayer.Play(); }
private void ffAppBarBtn_Click(object sender, System.EventArgs e) {
if (mediaPlayer.CanSeek) { mediaPlayer.Position = mediaPlayer.Position + new TimeSpan(0, 0, 5); mediaPlayer.Play(); } }
private void mediaPlayer_MediaFailed(object sender, System.Windows.ExceptionRoutedEventArgs e) { MessageBox.Show("Media Failed: " + e.ErrorException.Message); } } }
|
The last item to highlight is that the SupportedOrientations attribute on the PhoneApplicationPage element in XAML is changed from Portrait to PortraitOrLandscape. This allows the page to respond to orientation changes via the PhoneApplicationPage.OrientationChanged event.
Now that everything is
configured properly, let's configure the project to support a
full-screen mode for video playback in Expression Blend. With the States
tab opened in Expression Blend, the Add state group button creates a
Visual State Group that can contain one or more Visual States. The Turn
on transition preview button dynamically shows the changes when
different states are selected at design time.
Click the Add state group
button and name the Visual State Group "Orientations." Next, create an
"Add state" button to create a Visual State for PortraitUp. Create another state named LandscapeRight. The VSM should look like Figure 5.
Figure 5 also defines the UI available in the VSM to create states as well as customize the transitions. EasingFunctions provide for a more realistic animation flow. EasingFunctions are literally functions like quadratic, cubic, bounce, elastic, and so on. In general, EasingFunctions are available in Storyboards. Developers can create custom EasingFunctions
as well. Think of an EasingFunction as altering the animation speed
from a straight line to a curve, where sharp bends represent an increase
in speed so that animations appear to better model real world movement
with acceleration and bounce. Figure 6 shows the EasingFunction selector.
The other buttons shown in Figure 6 are transition duration, which represents how long the animation should take in real time, regardless of EasingFunction, and a button to turn on FluidLayout. FluidLayout
provides an engine that takes a look at the start state, the end state,
and then creates a smooth animation between the states based on the
selected EasingFunction. FluidLayout
can help make animations created by non-designers look great. Now that
we have the Blend functionality covered, let's create our states based
on current orientation for the sample project.
Look at Figure 5, and you see a state at the top called "Base." When working in Blend previously, you may not have been aware, but this is the visual state that you were working in. "Base" represents the default or initial state. All other state modifications are referenced to the Base state.
Be sure to select the Base state if you want to make modifications that apply across all states.
|
|
In Expression Blend, switch to Landscape in the Device tab and then switch back to the States tab. With the LandscapeRight Visual State selected, select the TitlePanel Grid and set Visibility to Collapsed and set Visibility to Collapsed for the videosListBox as well. For the Grid that contains the mediaPlayer MediaElement set the Height
property on the Grid to 480px. The Objects and Timeline window
indicates the changes visually in the timeline keyframe editor as shown
in Figure 7.
When you run the application, it works as expected when flipped to LandscapeRight, as shown in Figure 8.
If you switch the Emulator to LandscapeLeft, the UI remains as the Portrait layout, as shown in Figure 9.
You could build another state manually, but an easier option is to right-click on the LandscapeRight state, select Copy State To, and then select New State. Rename it LandscapeLeft, and that is all that's required to have both Landscape Orientation values display correctly.
The Visual State Manager
provides a powerful tool to customize transitions and animations via a
state-based mechanism. The next section covers the Microsoft Advertising
SDK, which supports advertising revenue for both Silverlight and XNA
Framework applications.