Show WPF tooltip on disabled item only

dant picture dant · May 23, 2010 · Viewed 13.6k times · Source

Just wondering if it is possible to show a WPF on a disabled item ONLY (and not when the item is enabled).

I would like to give the user a tooltip explaining why an item is currently disabled.

I have an IValueConverter to invert the boolean IsEnabled property binding. But it doesn't seem to work in this situation. The ToolTip is show both when the item is enabled and disabled.

So is is possible to bind a ToolTip.IsEnabled property exclusively to an item's own !IsEnabled?

Pretty straightforward question I guess, but code example here anyway:

public class BoolToOppositeBoolConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        if (targetType != typeof(bool))
            throw new InvalidOperationException("The target must be a boolean");

        return !(bool)value;
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        if (targetType != typeof(bool))
            throw new InvalidOperationException("The target must be a boolean");

        return !(bool)value;
    }

    #endregion
}

And the binding:

<TabItem Header="Tab 2" Name="tabItem2" ToolTip="Not enabled in this situation." ToolTipService.ShowOnDisabled="True" ToolTipService.IsEnabled="{Binding Path=IsEnabled, ElementName=tabItem2, Converter={StaticResource oppositeConverter}}">
    <Label Content="Item content goes here" />
</TabItem>

Thanks folks.

Answer

dant picture dant · May 25, 2010

JustABill's suggestion worked. I also needed to define the string as a resource to avoid problems with quotation marks. And you still need to set ToolTipService.ShowOnDisabled="True".

So, here is the working code which shows how to display a tooltip in WPF only when an item is disabled.

In the top container, include the system namespace (see sys below). I also have a Resources namespace, which I called "Res".

    <Window x:Class="MyProjectName.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:Res="clr-namespace:MyProjectName.Resources"
    >

Then you need

<Window.Resources>
    <Res:FalseToStringConverter x:Key="falseToStringConv" />
    <sys:String x:Key="stringToShowInTooltip">This item is disabled because...</sys:String>
</Window.Resources>

In my case, it was a tab item that I was interested in. It could be any UI element though...

<TabItem Name="tabItem2" ToolTipService.ShowOnDisabled="True" ToolTip="{Binding Path=IsEnabled, ElementName=tabItem2, Converter={StaticResource falseToStringConv}, ConverterParameter={StaticResource stringToShowInTooltip}}">
            <Label Content="A label in the tab" />
</TabItem>

And the converter in code behind (or wherever you want to put it). Note, mine went into the a namespace called Resources, which was declared earlier.

public class FalseToStringConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value is bool && parameter is string)
        {
            if ((bool)value == false)
                return parameter.ToString();
            else return null;
        }
        else
            throw new InvalidOperationException("The value must be a boolean and parameter must be a string");
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
    #endregion
}