I originally started this post with a title of “WPF ToolTip Child Element Visibility Based on the Parent of the ToolTip IsEnabled Property… and you are not it with a dirty dirty dish rag on your toe reading behind a dirty magazine”, but I decided that in the best interest of my sanity (read: “what sanity”) that I would make it a little more descriptive to what my goal for creating this functionality was and a lot less wordy (read: less words than the number of pieces of bubble gum in a dish that you wished for). Don’t ask.
After writing my last post about the advanced tooltip functionality in .NET 2.0 using the VisualTips component, I realized that WPF (Windows Presentation Foundation) lacked a way OOTB to create two distinctive tooltips on an element that could be displayed based on whether or not the control was disabled or enabled. VisualTips provides this functionality. This helps users to better understand what step they need to take before a control will become enabled and why the heck they can’t click on it. For instance, in MuvAudio, the “Record” button is disabled until an item has been added to the playlist. When they move their mouse over the button, as of right now, they get no message whatsoever. They don’t even get the regular tooltip telling them what it would do if it were enabled. (I’m in the process of implementing the VisualTips so the next version of MuvAudio will have the functionality I’m about to explain). It would make sense to do the following:
- Make the Record button, in the disabled state, display a message that says: “To being recording you must first add at least one audio file to the playlist. You can do this by double-clicking anywhere in the playlist area or by clicking on “Playlist”, “Add File(s)” and selecting the audio files that you would like to record.”
- Make the Record button in the enabled state display: “Starts the recording process.”
To do this in WPF I had look at the problem from a different perspective. Now, I’m not the greatest programmer in the world and I am definitely am open to suggestion, so please leave me comments, but this is what I came up with:
To add a ToolTip that displays different text based on the enabled/disabled of a button (this can be replaced with any element) that it is the child of:
[source:xml]
[/source]
The important parts are as follows:
[source:xml]
Visibility=”{Binding Path=IsEnabled, Converter={StaticResource ToolTipElementVisibilityConverter}, ConverterParameter=VisibleOnDisabled}”
Visibility=”{Binding Path=IsEnabled, Converter={StaticResource ToolTipElementVisibilityConverter}, ConverterParameter=VisibleOnEnabled}”
[/source]
- In the declaration of the Element that will contain the tooltip, you need to make sure you have ToolTipService.ShowOnDisabled=”True”
because this allows the tooltip to still be displayed when the element is disabled. - You need to set the DataContext of the tooltip as follows: DataContext=”{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}”; this allows us to set the binding of the IsEnabled property in the elements of the tooltip.
- Finally, you need to set the Visibility using a binding with a Converter and a ConverterParameter based on when you want the items to be displayed. In the above example we only want one of the textblocks to be displayed in either state so we have the parameter set to the opposite of each other:
- The Path is bound to the IsEnabled property of the element that is the parent of this tooltip (as described above).
- The Converter is a converter that we created that returns back the Visibility we want (Visible or Collapsed) based on the IsEnabled property and the ConvertParameter.
- The ConverterParameter is a string that we use to tell the item to be visible when the item is enabled or when the item is disabled. The two choices are VisibleOnDisabled and VisibleOnEnabled.
The actual converter is contained in the sample project.
As a side, I looked into using enums for the parameter instead of strings but they just added extra code that doesn’t get taken advantage of (Visual Studio 2008 Beta 2 doesn’t display auto completion for enums in xaml). An example would look like this: “ConverterParameter={x:Static local:ToolTipElementVisibility.VisibleOnDisabled}”, where “local” is a xml namespace you would add to the window declaration.
The other pieces of the puzzle are as follows:
- Add an xml namespace declaration for the converter class to reference the converter (I prefer to add this to the window.xaml the tooltip will be used on): xmlns:cvrt=”clr-namespace:MuvEnum.ToolTipElementVisibility.Converters”
- Add the converter as a resource in the same window.xaml you used in #1: <Window.Resources> <cvrt:ToolTipElementVisibilityConverter x:Key=”ToolTipElementVisibilityConverter” /> </Window.Resources>
A full sample is attached and has a compiled executable.
You’re free to use this code in any project you like. A reference to this post would be appreciated but is not required.
After I finished this code, which I’ll definitely be using in a soon to be finished WPF product, I realized that this goes above and beyond what the VisualTips for .NET can do by allowing a user to create distinctively different tooltips based on the enabled and/or disabled state of the element they are a child of thanks to the ability of tooltips to host any WPF element.
I assume this idea can be used to bind to other Boolean properties of elements and not just the IsEnabled. One of the most exciting things about WPF is the ability to create things that even those that created WPF didn’t even foresee. Now that deserves a post of its own.