WPF Sample Series – Data Binding In ToolTip

This is the next sample in the WPF Sample Applications Series. The purpose of the Sample Series is to provide concise code solutions for specific programming tasks. This sample provides a brief description of the problem, the solution and full source code with a test bench program.

In a previous sample it was stated that, “One of the most powerful features in the WPF platform is its rich data binding.”  In this sample we will see how data binding can be used to display data bound values in a ToolTip.

ToolTips are really just little read-only popup windows that display some context sensitive information related to the object that the ToolTip belongs to.  With WPF’s very rich content rendering and control styling capabilities, ToolTips are not longer limited to a plain text.  Developers can very easily add images, 3D objects, paths, visuals, text, grids or just about anything to a ToolTip.  You can also make a ToolTip an irregular shaped window!  OK, just because we can, does not mean we should.  Oh well, I did this and have included a very cool Vista TaskBar application preview style ToolTip. 

ToolTips are controlled by a ToolTipService.  You can set ToolTipService attached properties on your ToolTips to control them.  The ToolTipService Class article covers the properties exposed by the ToolTipService Class and examples on using it to control the position of the ToolTip.  In fact, this sample uses the ToolTipService.SetHasDropShadow method to turn off the default drop shadow so that our cool Vista TaskBar ToolTip can use a different method for rendering its outer glow, just like Vista does.

 There are four methods that I know of that developers can use to code their ToolTips.  This sample demonstrates all four methods.

  • Entering a string in the ToolTip property of an object
  • Code the ToolTip in the controls XAML mark-up.
  • Code the ToolTip using XAML in a resource and apply that resource to one or more controls
  • Code the ToolTip in the code behind file, VB.NET or C#.

This sample will also cover using data binding in the 2nd and 3rd methods and how to use a VisualBrush in the 4th method.

 Sample Application

 application

When you first open the application, it looks like the above image.  I have entered my name and secret password.

Name ToolTip

textbox

At last, a ToolTip in a ToolTip article!  I have hovered my mouse over the Name TextBox and the cool data bound ToolTip pops up.  This is a very vanilla ToolTip from a design perspective but is rich in data binding.  Two properties Text and ActualWidth, from the TextBox control are data bound and rendered in the ToolTip.  You can data bind whatever properties your application needs to display.

Let’s have a look at the XAML mark-up resource that was used to render this ToolTip.  The blue lines of code will be commented on below.

<Window.Resources>
<ToolTip x:Key=”toolTipTextBoxBinding”
         DataContext=”{Binding Path=PlacementTarget,
           RelativeSource={x:Static RelativeSource.Self}}”>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width=”Auto”/>
            <ColumnDefinition Width=”*”/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height=”Auto”/>
            <RowDefinition Height=”Auto”/>
            <RowDefinition Height=”Auto”/>
        </Grid.RowDefinitions>
        <Border HorizontalAlignment=”Stretch”
                BorderThickness=”0,0,0,1″ BorderBrush=”Black”
                Margin=”5″  Grid.Column=”0″
                Grid.Row=”0″ Grid.ColumnSpan=”2″>
            <TextBlock FontSize=”14″>
                 Two TextBox Data Bound Properties</TextBlock>
        </Border>
        <TextBlock Grid.Column=”0″ Grid.Row=”1″
                   Margin=”10,0,5,0″>TextBox.Text is:</TextBlock>
        <TextBlock Grid.Column=”1″ Grid.Row=”1″
                   FontWeight=”Bold” Text=”{Binding Path=Text}”/>
        <TextBlock Grid.Column=”0″ Grid.Row=”2″
                   Margin=”10,0,5,0″>TextBox.ActualWidth is:</TextBlock>
        <TextBlock Grid.Column=”1″ Grid.Row=”2″
                   FontWeight=”Bold” Text=”{Binding Path=ActualWidth}”/>
    </Grid>
</ToolTip>       
</Window.Resources>

The key piece of code is the DataContext property.  It’s here that the ToolTip’s DataContext is established, allowing child controls of the ToolTip to data bind to properties in the DataContext.  In the DataContext data binding code, PlacementTarget Property refers to the TextBox that opened the ToolTip.  The RelativeSource is set to the ToolTip.  So the ToolTip’s DataContext is itself, with the data binding Path being the TextBox that this ToolTip is associated with.  If you don’t have to reread this several times, you’re way smarter than me.

The second piece of code that makes this work, is located in the two TextBlocks with their Text properties data bound to properties on the TextBox control.  In this example we are data binding to the Text and ActualWidth properties.

So you can see how simple this really is.  The remained of the XAML mark-up is straightforward.  Check out how I used the border control to provide an underline that created a heading section for the ToolTip.  I could have used underlined text in the heading area, but this looks better.

Password ToolTip

password

This simple ToolTip using data binding to bind two properties Password and ActualWidth, from the PasswordBox control are data bound and rendered in the ToolTip.  Sometimes it is nice to be able to see what you are typing when the computer keeps telling you the passwords do not match.  Here the ToolTip exposes the value of the PasswordBox.Password property to the user.

Let’s have a look at the XAML mark-up that was used to render this ToolTip.  This XAML is not located in a resource, but is in-line with the PasswordBox control XAML.  The blue lines of code will be commented on below.

<PasswordBox x:Name=”txtPassword”
             VerticalAlignment=”Top”
             Grid.Column=”1″ Grid.Row=”2″
             d:LayoutOverrides=”VerticalAlignment”
             Margin=”0,0,0,10″ Grid.RowSpan=”1″>
   
  <PasswordBox.ToolTip>
    <ToolTip DataContext=”{Binding Path=PlacementTarget,
             RelativeSource={x:Static RelativeSource.Self}}”>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width=”Auto”/>
                <ColumnDefinition Width=”*”/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height=”Auto”/>
                <RowDefinition Height=”Auto”/>
                <RowDefinition Height=”Auto”/>
            </Grid.RowDefinitions>
           
            <Border HorizontalAlignment=”Stretch”
                    BorderThickness=”0,0,0,1″
                    BorderBrush=”Black” Margin=”5″ 
                    Grid.Column=”0″ Grid.Row=”0″
                    Grid.ColumnSpan=”2″>
                <TextBlock FontSize=”14″>
                    Two Password Data Bound Properties</TextBlock>
            </Border>
           
            <TextBlock Grid.Column=”0″
                       Grid.Row=”1″
                       Margin=”10,0,5,0″>
                PasswordBox.Password is:</TextBlock>
           
            <TextBlock Grid.Column=”1″
                       Grid.Row=”1″
                       FontWeight=”Bold”
                       Text=”{Binding Path=Password}”/>
           
            <TextBlock Grid.Column=”0″
                       Grid.Row=”2″
                       Margin=”10,0,5,0″>
                PasswordBox.ActualWidth is:</TextBlock>
           
            <TextBlock Grid.Column=”1″
                       Grid.Row=”2″
                       FontWeight=”Bold”
                       Text=”{Binding Path=ActualWidth}”/>
        </Grid>
    </ToolTip>
  </PasswordBox.ToolTip>
</PasswordBox>

This code is the same code used in the previous example with a few outer container changes.  You will typically see most fancy ToolTips coded as resources to promote code reuse.  However, you may find situations were placing the ToolTip XAML in with the control’s mark-up makes the most sense.

VisualBrush ToolTip Demo (The Big Kahuna)

open tooltip two

Now it’s time for some fun.  Use your mouse and resize the application and make it taller.  Notice how the image size grows and shrinks as you resize the form.  You have probably already seen it, but go ahead and place you mouse over the Window and you’ll see the cool ToolTip popup.  I wrote this ToolTip for my applications that use the TabControl that allows the user to have many screens open at once.  I wanted the ToolTip to resemble the ToolTip that the Vista TaskBar displays.  This is more for show, but it does look cool in a production business application.

What is going on here, is a rectangle is painted with a VisualBrush that is the visual from the Window Grid contents.  That rectangle is then surrounded with a border and a TextBox is placed above the border.  It took me about an hour of playing around with all the settings to get it to look like this.

This ToolTip is create in code.  The code is in the Window1.xaml.vb file.  You can simply copy the CreateToolTipForTabItem function right into your own code and use it.  I have marked several TODO’s in the code and provided suggestions for using this in your own code.  Here is how that function is called and the ToolTip created:

Me.ToolTip = CreateToolTipForTabItem(New VisualBrush(CType(Me.layoutRoot, UIElement)), “Vista Taskbar Style ToolTip For Window”)

This code snippet shows how to assign a ToolTip created in code to an objects ToolTip property.  In this case, it is the Window.  We create a New VisualBrush by down casting the Grid as a UIElement and pass this into the VisualBrush’s constructor.  The second parameter is the title string that appears above the ToolTip visual.

Now, go ahead and resize the Window again and cause the ToolTip to reopen again.  Um.  Make the Window small, open the ToolTip, now make is large and open the ToolTip.  What is going on here, is the visual from the Grid contents is painted on a 300 x 225 rectangle.  When the Window is small, the contents are scaled to fill the ToolTip.  For most business applications this scaling is not an issue since the forms are typically larger than 300 x 225.  You can also adjust anything about this solution to suit your needs.

This example ToolTip is a good example of what it takes to create a small form in code as opposed to XAML.  By the way, this ToolTip can also be created in XAML, I just wanted to demonstrate several methods for creating ToolTips.

Resources:  I am the original author for all this code.

Source Code: After downloading the source code you MUST change the file extension from .zip.DOC to .zip. This is a requirment of WordPress.com.

Download Source Code 32KB

Hope you can learn just a little bit more about WPF from this article and the Sample Series.

Just a grain of sand on the worlds beaches.

8 Responses to WPF Sample Series – Data Binding In ToolTip

  1. wducklow says:

    Thanks, great example. I implemented the resource based one and bound in XAML to my controls.

  2. mahpet says:

    Great, thanks.

    I was banging my head against a brick wall trying to solve a problem with displaying a tooltip for my validation errors and styling it differently from other tooltips. Foolishly I went down the “define different tooltip styles route” but found that <Element ToolTip="Blah" etc. and <Element.ToolTip Style="BlahBlah" etc. are two entirely different beasts and I had no way to bind the text to display in the tooltip (the Content) to a parent property because the Element.ToolTip doesn't have a parent. So I was thinking I was stuck with either having a data bound text string but no way to style it differently to other tooltips, or a tooltip I could style but having to use fixed predefined text.

    I can now set the Tag on the Element to which the Tooltip applies to be bound to the appropriate validation text and use the PlacementTarget DataContext approach to reference the Tag property.

    • The validation error message is typically consumed from the attached property.

      check out this link: http://msdn.microsoft.com/en-us/library/system.windows.controls.validation.errortemplate.aspx

      Cheers,

      Karl

      • mahpet says:

        True, but this is a bit of a pants solution (unless I’m doing something else wrong) because:

        1. It changes the tooltip of the underlying input control so the genuine “help the user complete the input” tooltip is replaced. Now my validation error ought to help the user more, but I’d rather have both.
        2. After the validation error no longer exists I’ve found that the tooltip does not revert to the original. I’ve never looked into this in great detail because of 1.

        • Download my BBQ Shack code. Open Applicaiton.xaml and search for validationTemplate. This style provides a VERY simple solution for your problem.

          I noticed this very same issue you are bringing up years ago and wrote the validationTemplate to address it.

          Cheers,

          Karl

  3. mahpet says:

    Very neat. Illustrates thinking outside the box by putting the Path into the box :-)

Follow

Get every new post delivered to your Inbox.

Join 245 other followers