Thomas Freudenberg

Confessions of a caffeine addict

Creating Dynamic Windows 7 Taskbar Overlay Icons, the MVVM Way

metrotwitSince Windows 7 the icon of an application can get an overlay bitmap. You can use that to indicate some state of the application, or–like MetroTwit–to show the number of unread items.

Overlay Icon in WPF

In WPF, the API is pretty simple:

<Window.TaskbarItemInfo>
    <TaskbarItemInfo 
        Overlay="{StaticResource ResourceKey=MyOverlayImage}" />
</Window.TaskbarItemInfo>

However, in one of my projects I have to display dynamic text in the overlay, similar to MetroTwit, but above example only shows a static resource.

While searching in the internet I found Pete Brown’s article Creating Dynamic Windows 7 Taskbar Overlay Icons. He uses a WPF DataTemplate to define the content of the overlay, and in his code-behind he takes that template, renders it to a bitmap and assigns it to the TaskbarItemInfo’s Overlay property. See his article for the detailed steps.

Though I think Pete’s solution pretty clever, it lacks the separation of logic and presentation. In my application I don’t want to create images in the code-behind, code-aside, whatever. It follows the MVVM pattern, so the creation of the overlay image shouldn’t be the concern of my viewmodel.

Solution

Extending TaskbarItemInfo doesn’t work because it is sealed. Therefore I took the same route as in my previous post, attaching dependency properties:

public class TaskbarItemOverlay  {
    public static readonly DependencyProperty ContentProperty =
        DependencyProperty.RegisterAttached(
            "Content", 
            typeof(object), 
            typeof(TaskbarItemOverlay), 
            new PropertyMetadata(OnPropertyChanged));

    public static readonly DependencyProperty TemplateProperty =
        DependencyProperty.RegisterAttached(
        "Template", 
        typeof(DataTemplate), 
        typeof(TaskbarItemOverlay), 
        new PropertyMetadata(OnPropertyChanged));


    public static object GetContent(DependencyObject dependencyObject) {
        return dependencyObject.GetValue(ContentProperty);
    }

    public static void SetContent(DependencyObject dependencyObject, object content) {
        dependencyObject.SetValue(ContentProperty, content);
    }

    public static DataTemplate GetTemplate(DependencyObject dependencyObject) {
        return (DataTemplate)dependencyObject.GetValue(TemplateProperty);
    }

    public static void SetTemplate(DependencyObject dependencyObject, DataTemplate template) {
        dependencyObject.SetValue(TemplateProperty, template);
    }

    private static void OnPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) {
        var taskbarItemInfo = (TaskbarItemInfo) dependencyObject;
        var content = GetContent(taskbarItemInfo);
        var template = GetTemplate(taskbarItemInfo);

        if (template == null || content == null) {
            taskbarItemInfo.Overlay = null;
            return;
        }

        const int ICON_WIDTH = 16;
        const int ICON_HEIGHT = 16;

        var bmp =
            new RenderTargetBitmap(ICON_WIDTH, ICON_HEIGHT, 96, 96, PixelFormats.Default);
        var root = new ContentControl {
            ContentTemplate = template, 
            Content = content
        };
        root.Arrange(new Rect(0, 0, ICON_WIDTH, ICON_HEIGHT));
        bmp.Render(root);

        taskbarItemInfo.Overlay = bmp;
    }
}

The first lines a boilerplate code to define the attached properties. There are two of them, Content and Template. The former defines, well, the content we’re going to bind to our model. The latter defines the template used to render the content.

The actual work is done in the method OnPropertyChanged. It takes the template together with the content, renders it, and assigns the resulting bitmap to the Overlay property of the TaskbarItemInfo element.

Usage

I have created a small application to demonstrate the use of the attached properties. The XAML of the window is this:

<Window 
    x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:src="clr-namespace:WpfApplication1" 
    Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate x:Key="OverlayIcon">
            <Grid Width="16" Height="16">
                <Ellipse 
                    Fill="Red" 
                    Stroke="White" 
                    StrokeThickness=".5" />
                <TextBlock 
                    Text="{Binding}" 
                    TextAlignment="Center" 
                    Foreground="White" 
                    FontWeight="Bold" 
                    Height="16" 
                    VerticalAlignment="Center" 
                    FontSize="10"/>
            </Grid>
        </DataTemplate>
    </Window.Resources>
    <Window.TaskbarItemInfo>
        <TaskbarItemInfo 
            src:TaskbarItemOverlay.Content="{Binding Count}" 
            src:TaskbarItemOverlay.Template="{StaticResource OverlayIcon}" />
    </Window.TaskbarItemInfo>
    <Viewbox>
        <TextBlock Text="{Binding Count}" />
    </Viewbox>
</Window>

TaskbarItemOverlayIn the window’s resources we define the template for the overlay. Notice that the Text is bound! Later you can see the TaskbarItemInfo with the attached properties in action: Content binds to the Count property of my viewmodel, and Template references the DataTemplate defined in the resources.

The code-behind is straight forward. I won’t repeat it here, but you can see it at GitHub. Basically it increments the Count property of the viewmodel every seconds in a background thread. You can see the result in the image to the left.

The source code is attached, but also available at GitHub.

Comments

Windows 7 Blog on: Thomas Freudenberg: Creating Dynamic Windows 7 Taskbar Overlay Icons, the MVVM Way | Social Networking & Digital Collaboration news, tips, guides... said:

Pingback from  Windows 7 Blog on: Thomas Freudenberg: Creating Dynamic Windows 7 Taskbar Overlay Icons, the MVVM Way | Social Networking &amp; Digital Collaboration news, tips, guides...

# August 15, 2010 12:36 PM

Phil said:

Great Post! Thanks for sharing.

How would you hide the overlay icon if the count is zero?

# August 18, 2010 7:05 AM

Thomas Freudenberg said:

Phil, just set the bound property in your viewmodel to null. The overlay icon will be removed automatically (see ll.38 in the code above)

# August 18, 2010 7:15 AM

Phil said:

Oh, I see. Using a nullable int for the count property in your sample application works well.

Thank you very much for your support!

# August 18, 2010 8:41 AM

Gally said:

Thanks for the wonderful post! How is it licensed? (Can I use it for non-cmmercial use?)

Thanks again!

# June 28, 2011 1:52 AM

Chris said:

can you do hte same thing for a system tray Icon?

# December 12, 2011 10:34 PM

Henrybqxr3 said:

[url=pandoracharmsmart.blogspot.com]pandora charms discount[/url]Precious jewelry is an excellent gift idea to offer to someone close or even a good friend, and many people purchase jewelry every day. But with the amount of different alternatives offered to choose from, it can be difficult to know which bit of expensive jewelry is of the best good quality so that you get the very best. Thankfully, you can look into the good quality so that you will won't need to stress.

Whenever you obtain precious jewelry that dangles and hangs, make sure to budget a little bit money and time for picking out a great chain. A delicate chain can destroy a valuable bit by splitting at the least opportune second. Have a jeweler's assistance to pick out a sequence that hits a great equilibrium among elegance and sturdiness.

Vintage and heirloom bands, ear-rings, and pendants ought to be protected from warmth, severe cool, abnormal humidity, and dirt. Just about the most protected spots for precious, fine classic expensive jewelry is a soft pot that is certainly placed in a fireproof secure. The surroundings ought to be amazing and dried out to shield each piece from wear and tear.

Precious jewelry represents this type of pricey obtain the smart buyer will shield his or her purchase by extensively examining give back policies before choosing. This is certainly much more crucial with jewelry designed being a gift item, as no person can be completely a number of their gift item will fit the receiver. Acquiring pieces having a return policy can avoid long term regrets more than ill-considered expensive jewelry buys.

When you are buying jewelry, top quality matters. It is best to get your financial budget into account when picking what things to buy. Even so, you need to ensure you do not compromise good quality at the same time. On the whole of thumb, always choose the best piece of jewellery that one could afford to pay for right now.

[url=cheappandoracharmbracelet.blogspot.com]pandora charm bracelet retailers[/url]As you now find out about a number of the differing types and features of jewelry that exist, you may make a well informed selection at the jewelry retail store. Ideally, generating the option of what kind of jewelry to get, might be a stress-cost-free and fun encounter, now that you are very well-well informed and keen to go make the obtain!

# May 28, 2012 4:28 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)