Windows Presentation Foundation 4, the new version currently available in Beta 2 which will be part of .NET Framework 4/VS 2010, offers native integration with Windows 7 without the need of utilizing external components and libraries (at least for most activities). Among available functionalities, multi-touch and task bar integration are the most important.
In this post I'm going to discuss how you can add buttons to the application's icon in the Windows task bar, very similarly to what you can see by running Windows Media Player, which provides button for controlling the media being played, available when the mouse pointer passes over the application icon:

The goal of this post is building, although with limited capabilities, a media player with WPF 4 and Visual Basic 2010. Next we will add three buttons that will be visible in the task bar. After creating the project, let's start by defining the user interface as follows:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="540">
<!--A simple gradient background -->
<Window.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0" />
<GradientStop Color="White" Offset="1" />
</LinearGradientBrush>
</Window.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<!-- The MediaElement is placed in the first row (notice
how the volume is set via data-binding)-->
<MediaElement Name="Media1" Grid.Row="0" LoadedBehavior="Manual"
Volume="{Binding ElementName=VolumeSlider, Path=Value}"
MediaFailed="Media1_MediaFailed" >
</MediaElement>
So we will have some buttons, both on the window and on the task bar. This means that we will have duplicate buttons although in differente places. A good approach is implementing the WPF commanding technique instead of handling Click events. Basically we use some commands that are assigned to controls and that will be executed only when the specified conditions are true. Before going into that, let's complete the code for the Window:
<!-- Some buttons. Notice how predefined commands are assigned to the Command property -->
<StackPanel Orientation="Horizontal" Grid.Row="1">
<Button Name="PlayButton" Width="70" Height="40" Command="MediaCommands.Play"
Margin="5" Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}" />
<Button Name="PauseButton" Width="70" Height="40" Command="MediaCommands.Pause"
Margin="5"
Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"/>
<Button Name="StopButton" Width="70" Height="40"
Margin="5" Command="MediaCommands.Stop"
Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"/>
<Button Name="BrowseButton" Width="40" Height="40"
Margin="5" Content="..."/>
<!-- Setting the volume -->
<Slider Name="VolumeSlider" Width="80" Margin="5"
Minimum="0" Maximum="1" Value="0.5" TickFrequency="0.1"
AutoToolTipPlacement="TopLeft" TickPlacement="BottomRight"/>
</StackPanel>
</Grid>
As you may know, WPF defines some default commands which target different scenarios, so that you do not need to implement custom ones. MediaCommands expose a number of commands that can be used in multimedia situations like this one. So the control's Command property is assigned with the desired command. Since commands also define a localizable text to be shown inside the control, the Content property is bound to the Text property of the command, which returns the localized text. If you run the English version of Windows like me, the localized text will be anyway Play, Stop, Pause. Now let's define the CommandBindings, in order to declare the event handlers that will be executed with regard of commands:
<!-- Assigning event handlers to commands-->
<Window.CommandBindings>
<CommandBinding Command="MediaCommands.Play" x:Name="PlayCommand"
Executed="PlayCommand_Executed"
CanExecute="PlayCommand_CanExecute"/>
<CommandBinding Command="MediaCommands.Stop" x:Name="StopCommand"
Executed="StopCommand_Executed"
CanExecute="StopCommand_CanExecute"/>
<CommandBinding Command="MediaCommands.Pause" x:Name="PauseCommand"
Executed="PauseCommand_Executed"
CanExecute="PauseCommand_CanExecute"/>
</Window.CommandBindings>
Each CommandBinding establishes that the Executed event handler will run the specified action while CanExecute will check if such action is actually executable. This also requires some Visual Basic code that I will show later. Now we can write code for integrating with Windows 7. Look at this:
<Window.TaskbarItemInfo>
<TaskbarItemInfo Description="Control your media" ThumbnailClipMargin="5">
<TaskbarItemInfo.ThumbButtonInfos>
<ThumbButtonInfoCollection>
<ThumbButtonInfo x:Name="ThumbPlayButton" Command="MediaCommands.Play"
DismissWhenClicked="False" CommandTarget="{Binding ElementName=PlayButton}"
Description="Play" ImageSource="/MediaPlayer;component/Images/PlayHS.png" />
<ThumbButtonInfo x:Name="ThumbStopButton" Command="MediaCommands.Stop"
DismissWhenClicked="False" CommandTarget="{Binding ElementName=StopButton}"
Description="Stop" ImageSource="/MediaPlayer;component/Images/StopHS.png" />
<ThumbButtonInfo x:Name="ThumbPauseInfo" Command="MediaCommands.Pause"
DismissWhenClicked="False" CommandTarget="{Binding ElementName=PauseButton}"
Description="Pause" ImageSource="/MediaPlayer;component/Images/PauseHS.png" />
</ThumbButtonInfoCollection>
</TaskbarItemInfo.ThumbButtonInfos>
</TaskbarItemInfo>
</Window.TaskbarItemInfo>
</Window>
The TaskbarItemInfo object gets a reference to the application icon in the task bar. The Description property will show a tooltip when the mouse pointer passes, while ThumbnailClipMargin allows setting a margin. Among the elements that it can store, there are buttons. They are represented by ThumButtonInfo objects (max number is 7) which are contained inside a collection named ThumButtonInfoCollection. Each task bar button works basically like a normal Button control, since it expose a Click event and a Command, which can be assigned with the appropriate command defined in XAML code and that we previously assigned to normal buttons too. Notice that these particular buttons do not show text, because they can just show images so you have to assign the ImageSource property. Remember that such images must be 16 x 16. DismissWhenClicked is used to specify that a button is not available only once. Also notice how the CommandTarget property binds the current button to the related normal one on the window. Now let's switch to the Visual Basic code and write the following: colleghi l'attuale pulsante al corrispondente fratello maggiore sulla finestra. Ora si passa al codice Visual Basic.
Class MainWindow
Private sourceMedia As String = String.Empty
Private Sub BrowseButton_Click(ByVal sender As System.Object,
ByVal e As System.Windows.RoutedEventArgs) Handles BrowseButton.Click
Dim dialog As New Microsoft.Win32.OpenFileDialog
With dialog
.Title = "Select a media file"
.Filter = "Avi & Wmv|*.avi;*.wmv|All files|*.*"
If .ShowDialog = True Then
Me.sourceMedia = .FileName
Me.Media1.Source = New Uri(sourceMedia, UriKind.RelativeOrAbsolute)
End If
End With
End Sub
'In case opening the media file fails
Private Sub Media1_MediaFailed(ByVal sender As System.Object,
ByVal e As System.Windows.ExceptionRoutedEventArgs)
MessageBox.Show(e.ErrorException.Message)
End Sub
'Executing command actions
Private Sub PlayCommand_Executed(ByVal sender As System.Object,
ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
Me.Media1.Play()
End Sub
Private Sub StopCommand_Executed(ByVal sender As System.Object,
ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
Me.Media1.Stop()
End Sub
Private Sub PauseCommand_Executed(ByVal sender As System.Object,
ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)
Me.Media1.Pause()
End Sub
'Setting the condition tha makes commands executable
'if verified as true
Private Sub PlayCommand_CanExecute(ByVal sender As System.Object,
ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
e.CanExecute = Me.Media1.Source IsNot Nothing
End Sub
Private Sub StopCommand_CanExecute(ByVal sender As System.Object,
ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
e.CanExecute = Me.Media1.Source IsNot Nothing
End Sub
Private Sub PauseCommand_CanExecute(ByVal sender As System.Object,
ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)
e.CanExecute = Me.Media1.Source IsNot Nothing
End Sub
End Class
Simply notice how the CanExecute handlers set a condition that will disable controls on the UI unless it is false. Such condition will become True only when you select a media file (and thus controls will be automatically enabled). Now we can run the application and enjoy the magic:

By writing the above code we made our application icon interactive, adding buttons that allow us controlling how the media file is played. This is a very cool feature of WPF 4 for Windows 7.
You can download the code for this blog post from the following address of the MSDN Code Gallery.
Alessandro