Developing application with WPF and Windows 7 (Part II)
August 31st, 2009
In my previous post I talked about how to integrate some of the Windows 7 features (specifically Overlay Images and Taskbar Progress) in a WPF application we created for a screencast (in Spanish). In this post I will go over the remaining features I have yet to cover. These are:
- How to: Show a thumbnail of the application
- How to: Use Thumbnail Toolbar buttons
- How to: Open a new application with the Jumplist
Last time we ended up with this application, so you might be interested in downloading it, since all changes shown in this post will be done to it.
How to: Show a thumbnail of the application
One of the cool features in Windows 7, is that you can show a clipped thumbnail preview of your application instead of one for the entire window. We thought our application was identified by snowboards, so we decided to show the selected snowboard in the taskbar preview.
To set the custom preview, we are going to need the Window’s handle. However, as WPF Windows do not have a handle, we are going to add the following code in the Shell.xaml codebehind:
private IntPtr handle; public IntPtr Handle { get { if (this.handle == IntPtr.Zero) { WindowInteropHelper interopHelper = new WindowInteropHelper(this); this.handle = interopHelper.Handle; } return this.handle; } }
After that, we can add code like this in the Shell Load to clip our window and show the desired part of it:
private void Shell_OnLoad(object sender, RoutedEventArgs e) { this.InitializeConnectionMonitor(); this.InitializeRequestManager(); this.InitializeServiceAgent(); Rectangle clippingRect = new Rectangle( new System.Drawing.Point(552, 89), new System.Drawing.Size(210, 310)); Taskbar.TabbedThumbnail.SetThumbnailClip(this.Handle, clippingRect); }
As you can see, we hardcoded the values to clip the rectangle. However, you can simply calculate to obtain code that will work in any display.
If you run the application you should be able to see a small preview of the board when hovering over the application in the taskbar.
| Note: The thumbnail custom preview might not be visible in all versions of Windows 7. Running in VPC environment it also does not work. |
How to: Use Thumbnail Toolbar buttons
Thumbnail buttons are a really useful feature, because they allow you to execute different operations in your application without even having to open it. For the snowshop scenario we decided to add two buttons, one that would pick the next snowboard and another one for the previous.
We first need to define both buttons for the entire scope of the Shell.xaml class:
private readonly ThumbnailButton buttonPrevious; private readonly ThumbnailButton buttonNext;
In the Shell’s constructor we create the buttons and assign their respective icons:
public Shell() { this.InitializeComponent(); this.buttonNext = new ThumbnailButton(new Icon(“images\\nextArrow.ico”), “Next Image”); this.buttonPrevious = new ThumbnailButton(new Icon(“images\\prevArrow.ico”), “Previous Image”); }
Now we have to handle the click event of the buttons and add them. We placed this code in the Shell Load handler:
private void Shell_OnLoad(object sender, RoutedEventArgs e) { this.InitializeConnectionMonitor(); this.InitializeRequestManager(); this.InitializeServiceAgent(); Rectangle clippingRect = new Rectangle( new System.Drawing.Point(552, 89), new System.Drawing.Size(210, 310)); Taskbar.TabbedThumbnail.SetThumbnailClip(this.Handle, clippingRect); this.buttonNext.Click += this.ButtonNext_Click; this.buttonPrevious.Click += this.ButtonPrevious_Click; Taskbar.ThumbnailToolbars.AddButtons(this.Handle, this.buttonPrevious, this.buttonNext); }
As you might have noticed, the handlers for the events are yet to be written, so let’s get to it:
private void ButtonPrevious_Click(object sender, EventArgs e) { int newIndex = BoardList.SelectedIndex - 1; if (newIndex > -1) { this.BoardList.SelectedIndex = newIndex; } } private void ButtonNext_Click(object sender, EventArgs e) { int newIndex = BoardList.SelectedIndex + 1; if (newIndex < BoardList.Items.Count) { this.BoardList.SelectedIndex = newIndex; } }
But we also want to disable the Previous button when standing in the first board, and disable the Next button when the last board is selected. This can be easiliy achieved by adding the event handler declaration in XAML:
<ListBox x:Name=”BoardList” ItemsSource=”{Binding Source={StaticResource SnowboardTables}}” IsSynchronizedWithCurrentItem=”True” Style=”{StaticResource BoardListStyle}” SelectionChanged=”BoardList_SelectionChanged”/>
And writing code like this for the handler:
private void BoardList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) { this.buttonPrevious.Enabled = this.BoardList.SelectedIndex > 0; this.buttonNext.Enabled = this.BoardList.SelectedIndex < BoardList.Items.Count - 1; }
As you can see adding code to interact with your applcation via Thumbnail Toolbar buttons is really straightforward, and if you press F5, you should be able to see the Snowboard in the Thumbnail preview spinning as your press the different thumbnail buttons to change the boards.
You can see an image below with the outcome of the application after both additions (Thumbnail Toolbar Buttons and Thumbnail image).

How to: Open a new application with the Jumplist
As you might have noticed the application allows you to sell more than one board at the same time, but it does not provide the total price of the purchase. That is why a feature that might come in handy is having the windows calculator launched from the application’s Jumplist . The Jumplist is like the application’s start menu, and many useful features can be implemented with it.
To use the Windows 7 Jumplist in your application, you first have to set the application’s ID, which is the unique identifier of your application (it is a string). The following code, which should be placed in the App.xaml file, will add a link to the calculator in the SnowShop’s jumplist:
protected override void OnStartup(System.Windows.StartupEventArgs e) { Taskbar.AppId = Settings.Default.AppID; JumpList jumpList = Taskbar.JumpList; CustomCategory helperCategory = new CustomCategory(“Shop Helpers”); jumpList.CustomCategories.Add(helperCategory); JumpListLink taskBarLink = new JumpListLink(); taskBarLink.Title = “Run Calculator”; taskBarLink.Path = @”%windir%\system32\calc.exe”; helperCategory.JumpListItems.Add(taskBarLink); jumpList.RefreshTaskbarList(); base.OnStartup(e); }
Outcome
You can download the code for the entire demo (including all the modifications explained in this post) from the link below.
Disclaimer
This code is provided “AS IS” with no warranties, and confers no rights.
Download
You can get source code here: SnowShopW7.zip.
I hope this couple of posts were useful for you when developing with WPF and Windows 7.
Developing applications with WPF and Windows 7 (Part I)
August 11th, 2009
Last week with Matias Woloski and Ezequiel Jadib we created a demo for a screencast (in Spanish) that shows how to take advantage of some Windows 7 features in a WPF application, improving the user experience (after all that is one of the main goals of WPF). You can find the code for the clean application (without Windows 7 functionality) here, and the fully functional application over here. In this and future posts I will go over the relevant additions to the application, so you can see how easy it is to take advantage of Windows 7 features in your existing application. At the end of each post I will provide the outcome solution.
Demo Scenario
The application shows a Snow Board Shop that allows to Ship Orders of different Snow Boards. It also provides support for temporarily connected scenarios using the Disconnected Service Agent Application Block from the Smart Client Software Factory.

The demo shows the following interaction with Windows 7:
- How to: Show connectivity status in the Windows 7 Taskbar [in this post]
- How to: Show progress while shipping orders [in this post]
- How to: Show a thumbnail of the application [coming soon]
- How to: Use Thumbnail buttons [coming soon]
- How to: Open a new application with the Jumplist [coming soon]
Implementation Details
- The demo leverages Windows 7 functionalities through the Microsoft.WindowsAPICodePack.dll and Microsoft.WindowsAPICodePack.Shell.dll. Downloaded from here (WindowsAPICodePack).
How to: Show connectivity status in the Taskbar
What we wanted to do is show whether the application is connected to the internet (which would in turn enable it to ship orders), without having the window open. What we decided to do is show an icon in the application’s taskbar that reflect the connectivity status. To do this, we must first add a reference to System.Drawing.dll and to both assemblies mentioned above (located in the Lib folder). Then, update the UpdateConnectionStatus method to change the icon based on the status:
private void UpdateConnectionStatus(bool isConnected) { string status; Icon icon; if (isConnected) { status = “Online”; icon = new Icon(“images\\Available.ico”); StatusLabel.Style = (Style)FindResource(“StatusLabelOnline”); StatusLabel.Content = status; } else { status = “Offline”; icon = new Icon(“images\\Offline.ico”); StatusLabel.Style = (Style)FindResource(“StatusLabelOffline”); StatusLabel.Content = status; } Taskbar.OverlayImage.Icon = icon; Taskbar.OverlayImage.Text = status; }
If you run the application now and connect/disconnect from the Internet, you will notice the icon in the Taskbar changing.
How to: Show progress while shipping orders
Now that we are able to show connectivity, and are working in a scenario with Offline capabilities it would be good to show the progress of the orders being dispatched without having the application’s window open. That’s when the Windows 7 taskbar comes to the rescue. Our goal is to show progress, by increasing the progress value as less orders are pending to dispatch. All we have to do is update the handlers of the RequestDispatched and RequestEnqueued events with code like this:
private delegate void OnRequestEnqueuedDelegate(object sender, RequestEnqueuedEventArgs e); private void OnRequestEnqueued(object sender, RequestEnqueuedEventArgs e) { this.UpdateRequestQueue(); if (Dispatcher.Thread != System.Threading.Thread.CurrentThread) { Dispatcher.Invoke(new OnRequestEnqueuedDelegate(OnRequestEnqueued), sender, e); } else { //Start showing progress when the first request is enqueued if (manager.RequestQueue.GetCount() == 1) Taskbar.ProgressBar.State = TaskbarButtonProgressState.Indeterminate; Taskbar.ProgressBar.MaxValue = manager.RequestQueue.GetCount(); Taskbar.ProgressBar.CurrentValue = 0; } } private delegate void OnRequestDispatchedDelegate(object sender, RequestDispatchedEventArgs e); private void OnRequestDispatched(object sender, RequestDispatchedEventArgs e) { this.UpdateRequestQueue(); if (Dispatcher.Thread != System.Threading.Thread.CurrentThread) { Dispatcher.Invoke(new OnRequestDispatchedDelegate(OnRequestDispatched), sender, e); } else { //Stop showing progress when there are no more requests if (manager.RequestQueue.GetCount() == 0) { Taskbar.ProgressBar.State = TaskbarButtonProgressState.NoProgress; } else { Taskbar.ProgressBar.State = TaskbarButtonProgressState.Normal; Taskbar.ProgressBar.CurrentValue += 1; } } }
To be able to see how this works, I would recommend disconnecting from the Internet (so no orders are dispatched) and enqueuing about 20 orders. Then connect, and you will be able to see the progress bar increasing as orders are dispatched.
Outcome
Disclaimer
This code is provided “AS IS” with no warranties, and confers no rights.
Download
You can get source code here: SnowShopPart1.zip.
Stay tuned because I will blog about all the other features soon
.
EDIT August 31st 2009: Blogged part 2.
Características del Disconnected Service Agent (DSA) Application Block
September 6th, 2008
Este post resume las principales características del Disconnected Service Agent Application Block de la Smart Client Software Factory, para trabajar en escenarios conectados de manera temporal.
El DSA Application Block permite simplificar la gestión de Requests para este tipo de escenarios. Las dos principales características del DSA Application Block que le permiten hacer esto son:
Request Manager
El Request Manager es un “subsistema” de clases que trabajan en conjunto para gestionar el envío de los Web Service Requests.
Los datos de la Request Queue pueden ser guardados de diferentes formas (MemoryRequestQueue/DataBaseRequestQueue). Cuando el Connection Monitor Application Block avisa al Request Manager que hay una nueva conexión online, el Request Manager recupera los Request de la RequestQueue y los envía usando el RequestDispatcher.
Cada Request tiene la siguiente información:
- OfflineBehavior
- Nombre del endpoint donde se encuentra el servicio, el cual es obtenido desde el Endpoint Catalog Application Block
- RequestID
- WebService arguments (parametros[])
Request Dispatcher
El Request Dispatcher envía los Requests cuando el estado de conexión es activo (Connection Monitor Application Block) y cuando la dirección del Endpoint esta verificada (Endpoint Application Block). Una clase llamada ConnectionMonitorAdapter (basado en el Connection Monitor Application Block) permite verificar fácilmente los atributos de conexión.
El siguiente diagrama (obtenido de la documentación de SCSF) muestra la relación entre las principales clases del DSA.
Para mas información sobre el Disconnected Service Agent Application Block (en inglés):
- How to: Create a Disconnected Service Agent
- How to: Consume a Disconnected Service Agent
- How to: Update a Disconnected Service Agent
- Design of the Disconnected Service Agent Application Block
- Working with the Disconnected Service Agent Application Block
- Enabling WCF Duplex Channel in DSA solution by Sebastian Iacomuzzi
Espero que el resumen sea útil.
Etiquetas de Technorati: Smart Client Software Factory,SCSF,Patterns & Practices,p&p,DSA,Disconnected Service Agent
DSA Application Block Overview
August 4th, 2008
The following post summarizes the main features of the DSA Application Block provided by the Smart Client Software Factory to work under temporary disconnected scenarios.
The DSA Application Block provides feature to simplify the management of requests on occasionally connected smart client applications.
There are two main features of the DSA Application Block that serve this purpose:
Request Manager
The request manager is a subsystem of classes which work together to manage the dispatching of Web Service Requests.
The request queue data persists in different ways(MemoryRequestQueue/DataBaseRequestQueue). When the Connection Monitor Application Block notifies the Request Manager class that the connection is online, it retrieves the Requests from the RequestQueues and send them using the RequestDispatcher.
Each request has the following information:
- OfflineBehavior
- Name of the endpoint where the service is, to retrieve from the Endpoint Catalog Application Block.
- RequestID
- WebService arguments (parameters [])
Request Dispatcher
The Request Dispatcher sends the requests when connectivity is online (Connection Monitor Application Block) and the Endpoint address is good (Endpoint Application Block). A ConnectionMonitorAdapter (”inspired” by the Connection Monitor Application Block) class allows the easy checking of the Connection attributes.
The following diagram (obtained from the SCSF documentation) shows the relationship between the main classes of the DSA.
For more information about the DSA you can check:
- How to: Create a Disconnected Service Agent
- How to: Consume a Disconnected Service Agent
- How to: Update a Disconnected Service Agent
- Design of the Disconnected Service Agent Application Block
- Working with the Disconnected Service Agent Application Block
- Enabling WCF Duplex Channel in DSA solution by Sebastian Iacomuzzi


