Question

This is my working XAML code for a tooltip:

 <DataTrigger Binding="{Binding Visibility,ElementName=txtParent}" Value="Visible">
       <Setter Property="StackPanel.ToolTip" Value="{Binding Text,ElementName=txtParent}" TargetName="PanelTitle">
       </Setter>   
 </DataTrigger>

Now I want a tool tip which has maximum width as well as text wrapping. I tried using the following code but it didnt work:

 <DataTrigger Binding="{Binding Visibility,ElementName=txtParent}" Value="Visible"> 
     <Setter Property="StackPanel.ToolTip" TargetName="PanelTitle">
           <Setter.Value>
                <ControlTemplate TargetType="{x:Type ToolTip}">
                <StackPanel Margin="7,1">                                               
                   <TextBlock Text="{Binding Text,ElementName=txtParent}"  Margin="1" HorizontalAlignment="Center"                          Width="200"                         TextWrapping='Wrap' VerticalAlignment="Top" />                                               
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
     </Setter>
 </DataTrigger>
Was it helpful?

Solution

A ToolTip does not exist in the visual tree in the way you might expect. It does not participate in the inheritance context or the "owner" element's name scope at runtime. I would guess that your binding is unable to resolve txtParent at runtime because it doesn't know where to look.

You could try replacing ElementName=txtParent in your binding with Source={x:Reference txtParent}, which forces the name to resolve during the parsing stage, when the name will still be in scope. It may work, and it may not, but either way it will likely break the XAML designer.

Also, you are setting the value of the ToolTip to a ControlTemplate, which doesn't make much sense. You should probably be setting it to a ToolTip instance (or some other content type):

<Setter.Value>
  <ToolTip>
    <StackPanel Margin="7,1" >                                               
      <TextBlock Text="{Binding Text,Source={x:Reference txtParent}}"
                 Margin="1"
                 HorizontalAlignment="Center"
                 Width="200"
                 TextWrapping="Wrap"
                 VerticalAlignment="Top" />
    </StackPanel>
  </ToolTip>
</Setter.Value>

Another hack which might work is to store the ToolTip as a resource somewhere in scope and have your Setter assign it with a StaticResource reference. Generally, using UI elements as shared resources is error prone and considered bad practice, but seeing as only one ToolTip should ever be loaded at any given time in your application, it may work:

<FrameworkElement.Resources>
  <ToolTip x:Key="MyToolTip">
    <StackPanel Margin="7,1" >                                               
      <TextBlock Text="{Binding Text,Source={x:Reference txtParent}}"
                 Margin="1"
                 HorizontalAlignment="Center"
                 Width="200"
                 TextWrapping="Wrap"
                 VerticalAlignment="Top" />
    </StackPanel>
  </ToolTip>
</FrameworkElement.Resources>

<!-- ... -->

<DataTrigger Binding="{Binding Visibility, ElementName=txtParent}"
             Value="Visible">
  <Setter Property="StackPanel.ToolTip"
          Value="{StaticResource MyToolTip}"
          TargetName="PanelTitle" />
</DataTrigger>

If you are using MVVM, though, the easiest (and probably best) thing to do would be to bind txtParent.Text to a property on your view model; then you could use the technique from this other answer to bind to the same property for your ToolTip.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top