Archive

Archive for the ‘WPF Controls’ Category

WPF NotifyIcon 1.0.1 – Minor Improvements, Major Tutorial

May 15th, 2009

I just posted an upgrade to my WPF NotifyIcon, which adds some minor improvements to the control. The most important one is probably the simplified data binding support for context menus (thanks to Nic Pillinger for the hint), but I also managed to add some polish in a few other areas.

 

image

 

Apart from the updated control itself, I completely revamped the sample project. It’s no longer just a showcase but contains various standalone samples which cover all aspects of the control. And last but not least, I published a complementary tutorial on the CodeProject. One could say I was quite busy ;)

 

Further information and download on the project page:
http://www.hardcodet.net/projects/wpf-notifyicon

Using Attached Events to Trigger Animations in WPF

May 8th, 2009

This is a pattern I applied when implementing the WPF NotifyIcon component in order to provide animation support for popups, tooltips, and balloon messages. The problem I had to solve was the loose coupling between the NotifyIcon and displayed controls:

 

image

Accordingly, I didn’t know anything about these controls at runtime. Nonetheless, I wanted to provide a communication channel to inform that UIElement that it is being displayed. And I wanted to do it declaratively.

Attached Events to the Rescue

Enter attached events. Just like the better known attached properties, they can be declared in a static class and attached to arbitrary dependency objects. Accordingly, a control X does not need to declare an event itself in order to raise it.

If you are working with Expression Blend, chances are high that you are already using attached events quite often. As an example, the Mouse.MouseDown attached event that lets you trigger an animation if the user clicks on an arbitrary control. And nothing stops you from defining your own custom events :-)

Creating a Sample Application

Let’s create a simple sample. The scenario is the following:

  • Sometimes, some kind of critical event occurs (simulated through a button click).
  • Every time this happens, we want a “status control” to show an alarm.

We will implement this status control purely in XAML – an attached event will trigger an animation that displays a warning sign:

image

 

Read more…

WPF NotifyIcon Released

May 4th, 2009

I’m happy to announce the public release of my WPF NotifyIcon control :-)

This is an implementation of a NotifyIcon (aka system tray icon or taskbar icon) for the WPF platform. It does not just rely on the existing Windows Forms component, but is a purely independent control which leverages several features of the WPF framework in order to display rich ToolTips, Popups, context menus, and balloon messages.

 

image

 

I’m planning on doing an introductory article on CodeProject (well, somewhere along the way…) but you’ll probably get along just fine – the control comes with a sample application that shows off most of the control’s features.

 

Further information and download on the project page:
http://www.hardcodet.net/projects/wpf-notifyicon

 

kick it on DotNetKicks.com

Tags: ,

Quick and Dirty (but nice!) ToolTips via Markup Extensions

April 19th, 2009

NetDrives does not rely on styles when it comes to displaying ToolTips, but uses a simple markup extension, that provides the following functionality:

  • Displays a nice looking ToolTip rather than just plain text.
  • Optional lookup of strings in a resource dictionary to simplify localization.
  • Optional title text.
  • Very simple declaration.

Here’s what the XAML looks like:

<Image
  Source="..\Shared\Images\HelpSmall.png"
  ToolTip="{ext:Info Title=ShareNameTitleToolTip, Body=ShareNameInfoToolTip}"
  />

 

…and this is the output:

image

Creating the Popup Control

The first step is to create a simple control that contains the ToolTip. Basically, this is a simple UserControl with the following features:

  • A grid with two rows. The first row contains just the title and is auto-sized to make sure it collapses if the title is not used at all.
  • Two TextBlocks for title and body text.
  • An image (I didn’t make that one bindable, I always use the same one).
  • Two dependency properties that provide binding capabilities for header and body text.

Here’s what the control looks like in Blend:

image

Of course, you can easily use this user control through styles and/or directly declared in XAML whenever you need:

<Image Source="..\Shared\Images\HelpSmall.png">
  <Image.ToolTip>
    <MyToolTipControl Header="My Title" Body="This is a ToolTip" />
  </Image.ToolTip>
</Image>

However, this would still take a style to hide the tooltip border and you are lacking resource file lookups. The markup extension makes this way easier…

Implementing the Markup Extension

MarkupExtension is one of the lesser known stars in WPF - it requires a little coding, but once in place, it greatly simplify things for you. A simple yet brilliant example is Dr. WPF’s ValueConverter extension, and I already blogged a few times about other applications.

This Info markup extension basically provides the following:

  • Two properties (Title and Body)
  • Resource lookup with fallback mechanism (string is used directly if it’s not a resource key)
  • ToolTip creation

 

/// <summary>
/// A markup extension that returns a
/// <see cref="InfoPopup"/> control preconfigured
/// with header and text information according to the
/// <see cref="Title"/> and <see cref="Body"/>
/// properties.
/// </summary>
public class Info : MarkupExtension
{
  /// <summary>
  /// Either a title text or a resource key that can be used
  /// to look up the title.
  /// </summary>
  public string Title { get; set; }

  /// <summary>
  /// Either a tooltips' main text or a resource key that can be used
  /// to look up the text.
  /// </summary>
  public string Body { get; set; }

  /// <summary>
  /// Empty default constructor.
  /// </summary>
  public Info()
  {
  }

  /// <summary>
  /// Inits the <see cref="Info"/> markup extension
  /// with the title and body.
  /// </summary>
  public Info(string title, string body)
  {
    Title = title;
    Body = body;
  }

  /// <summary>
  /// Performs a lookup for the defined <see cref="Title"/> and
  /// <see cref="Info"/> and creates the tooltip control.
  /// </summary>
  /// <returns>
  /// A tooltip control.
  /// </returns>
  public override object ProvideValue(IServiceProvider serviceProvider)
  {
    //create the user control that 
    InfoPopup popup = new InfoPopup();

    if (!String.IsNullOrEmpty(Title))
    {
      //look up title - if the string is not a
      //resource key, use it directly
      var result = Resources.ResourceManager.GetObject(Title) ?? Title;
      popup.HeaderText = (string)result;
    }

    if (!String.IsNullOrEmpty(Body))
    {
      //look up body text - if the string is not a
      //resource key, use it directly
      var result = Resources.ResourceManager.GetObject(Body) ?? Body;
      popup.BodyText = (string)result;
    }

    //create tooltip and make sure only the content is visible
    ToolTip tt = new ToolTip();
    tt.HasDropShadow = false;
    tt.BorderThickness = new Thickness(0);
    tt.Background = Brushes.Transparent;
    tt.Content = popup;

    return tt;
  }
}

Conclusion and Sample

This is only one of several ways to tackle the problem, but I really like that it only takes a single line to have a rich ToolTip in place. The implementation provided here may not completely suit your requirements, but it can easily be tailored to your needs.

The link below points to a sample project that contains both the markup extension and ToolTip control. Enjoy :-)

tooltip-extension.zip

 

kick it on DotNetKicks.com

WPF Ribbon: RibbonCommands Can Cause Memory Leaks

April 15th, 2009

I stumbled over an issue when dealing with Microsoft’s WPF ribbon today. Apparently, the control that heavily relies on RibbonCommands rather than arbitrary ICommand instances may cause severe memory leaks. Have a look at this simple Window:

 

<Window ...>
  <Grid>
    <Grid.Resources>
      <r:RibbonCommand
        x:Key="MyCommand"
        Executed="OnRibbonClicked"
        LabelTitle="Click Me" />
    </Grid.Resources>

    <!-- a ribbon that only displays a command in the quick access toolbar -->
    <r:Ribbon>
      <r:Ribbon.QuickAccessToolBar>
        <r:RibbonQuickAccessToolBar>
          <r:RibbonButton
            Command="{StaticResource MyCommand}"
            r:RibbonQuickAccessToolBar.Placement="InToolBar" />
        </r:RibbonQuickAccessToolBar>
      </r:Ribbon.QuickAccessToolBar>
    </r:Ribbon>
  </Grid>
</Window>

 

…and here’s the event listener that was declared for the RibbonCommand:

private void OnRibbonClicked(object sender, ExecutedRoutedEventArgs e)
{
  MessageBox.Show("Ribbon command executing.");
}

 

Once opened and closed, this window will not be garbage collected until the application shuts down. The reason is the OnRibbonClicked event handler that doesn’t get deregistered.

There are signs that Microsoft will dump RibbonCommand completely once the ribbon goes live. However: This probably won’t happen too fast, so you will have to solve the issue on your own. On the bright side: It forces a cleaner design on you.

I prefer custom commands anyway, so the natural way to go was to simply implement my own class that derives from RibbonCommand:

 

///<summary>
/// Base class for custom <see cref="RibbonCommand"/>
/// implementations.
///</summary>
public abstract class RibbonCommandBase : RibbonCommand
{
  /// <summary>
  /// Creates the command and registers weak event listeners.
  /// </summary>
  protected RibbonCommandBase()
  {
    Executed += OnExecute;
    CanExecute += OnCanExecute;
  }

  /// <summary>
  /// Determines whether the command can be executed or not.
  /// The default implementation always allows that.
  /// </summary>
  protected virtual void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
  {
    e.CanExecute = true;
  }

  /// <summary>
  /// Command implementation - executes command logic.
  /// </summary>
  protected abstract void OnExecute(object sender, ExecutedRoutedEventArgs e);
}

 

The noteworthy thing here is that this abstract base class registers event listeners for its own events - one virtual, one abstract. Accordingly, a deriving command implementation only has to provide its own OnExecute and OnCanExecute (optional) methods to get going:

 

public class MessageCommand : RibbonCommandBase
{
  protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
  {
    MessageBox.Show("Ribbon command executing.");
  }
}

 

The last thing to correct is the command declaration in XAML - rather than declaring a RibbonCommand with a code-behind event listener, you declare your custom command (MessageCommand in the sample below). As you can see, there is no longer a listener for the Executed event - the command takes care of this on its own. Accordingly, this command can be declared in a resource dictionary without a code-behind file.

<!-- Custom command - can be declared in a resource dictionary -->
<cmd:MessageCommand x:Key="MyCommand"
                    LabelTitle="Click Me"
                    SmallImageSource="About.png"
/>

 

Sample Project

The attached sample project shows the two variants and the missing garbage collection of the standard ribbon commands.

I wasn’t sure about licensing restrictions, therefore I did not include the WPF ribbon assembly in the downloadable sample - you’ll have to add the reference yourself before compiling. Sorry for the inconvenience :/

Download: ribbon-commands.zip

 

 image

 

kick it on DotNetKicks.com

Tags: ,

WPF NotifyIcon - Release Candidate

April 1st, 2009

This is an implementation of a NotifyIcon (aka system tray icon or taskbar icon) for the WPF platform.

image

Update:

The control has now its own project page. Please go to

http://www.hardcodet.net/projects/wpf-notifyicon