Ram
Ram

Reputation: 563

WPF tooltip conditional

I have a Textblock within a Grid and has a ToolTip which should display the "tooltip" binding but if it is Null or Empty it should display "name" binding.

How can I achieve this in the XAML?

<TextBlock Margin="3" TextAlignment="Left" VerticalAlignment="Center" FontSize="12" Foreground="Black" HorizontalAlignment="Left" ToolTip="{Binding Tooltip}" Text="{Binding Name}"/>

Upvotes: 5

Views: 3209

Answers (4)

Ram
Ram

Reputation: 563

I achieved this by using by using TooltipOpening as follows:-

<TextBlock Margin="3" TextAlignment="Left" VerticalAlignment="Center" FontSize="12" Foreground="Black" HorizontalAlignment="Left" ToolTip="" ToolTipOpening="TextBlock_ToolTipOpening"  Text="{Binding Name}" TextWrapping="Wrap" MaxWidth="470" />

Then in the "TextBlock_ToolTipOpening" method I applied my check as follows:-

    if (!String.IsNullOrEmpty(stf.Tooltip))
    {
       t.ToolTip = stf.Tooltip;
    }
    else
    {
        t.ToolTip = stf.Name;
    }

It works as expected - thanks to all for your contributions...wouldn't have worked this out without your help.

Upvotes: 1

tabby
tabby

Reputation: 1918

If the String is NULL

Create MultiValueConverter and declare as a static Resources:

<local:MyConverter x:Key="MyConverter"/>

Your Converter Class should look like this:

public class MyConverter: IMultiValueConverter
{
   public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
   {
        string tooltip = values.ElementAtOrDefault(0) as string,
           name = values.ElementAtOrDefault(1) as string;
        if(!String.IsNullOrEmpty(tooltip))            
            return tooltip;            
        else            
            return name;                        
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
 }

And Your TextBlock:

<TextBlock FontSize="12" Foreground="Red" Text="{Binding MyName}">
      <TextBlock.ToolTip>
           <MultiBinding Converter="{StaticResource NameConverter}">
               <Binding Path="Tooltip" IsAsync="True"/>
               <Binding Path="MyName"/>
           </MultiBinding>
      </TextBlock.ToolTip>
</TextBlock>

Upvotes: 2

mm8
mm8

Reputation: 169200

You could use a Style with one or two DataTriggers that binds the ToolTip property to the Name source property only if the Tooltip source property returns null or an emtpy string:

<TextBlock Margin="3" TextAlignment="Left" VerticalAlignment="Center" FontSize="12" Foreground="Black" HorizontalAlignment="Left" 
                   Text="{Binding Name}">
    <TextBlock.Style>
        <Style TargetType="TextBlock">
            <Setter Property="ToolTip" Value="{Binding Tooltip}" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding Tooltip}" Value="{x:Null}">
                    <Setter Property="ToolTip" Value="{Binding Name}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Tooltip}" Value="">
                    <Setter Property="ToolTip" Value="{Binding Name}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBlock.Style>
</TextBlock>

Upvotes: 4

MikeT
MikeT

Reputation: 5500

from MSDN

PriorityBinding in Windows Presentation Foundation (WPF) works by specifying a list of bindings. The list of bindings is ordered from highest priority to lowest priority. If the highest priority binding returns a value successfully when it is processed then there is never a need to process the other bindings in the list. It could be the case that the highest priority binding takes a long time to be evaluated, the next highest priority that returns a value successfully will be used until a binding of a higher priority returns a value successfully.

an example would look like this

<StackPanel>
    <ToggleButton IsChecked="{Binding ShowTooltip, Mode=TwoWay}" >toggle</ToggleButton>
    <TextBlock>
        <TextBlock.ToolTip>
            <PriorityBinding>
                <Binding Path="ToolTipSometimes" Mode="OneWay"/>
                <Binding Path="Name" Mode="OneWay"/>
            </PriorityBinding>
        </TextBlock.ToolTip>
    </TextBlock>
</StackPanel>

where A binding returns a value successfully if:

  • The path to the binding source resolves successfully.

  • The value converter, if any, is able to convert the resulting value.

  • The resulting value is valid for the target property.

Using a MultiBinding it could be done like this

<TextBlock >
    <TextBlock.ToolTip>
        <MultiBinding>
            <MultiBinding.Converter>
                <local:NullCleanup/>
            </MultiBinding.Converter>
            <Binding Path="ToolTip" Mode="OneWay"/>
            <Binding Path="Text" Mode="OneWay" />
        </MultiBinding>
    </TextBlock.ToolTip>
</TextBlock>

with this as the converter

public class NullCleanup : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return values.Aggregate((r, o) => r ?? o);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

However you can just put the logic in your VM

    private string _Tooltip;

    public string Tooltip;
    {
        get { return _Tooltip; }
        set { SetProperty(ref _Tooltip, value,()=>RaisePropertyChanged(nameof(ToolTipCleaned))); }
    }

    public string ToolTipCleaned => Tooltip ?? Name;

Upvotes: 2

Related Questions