Imports System.ComponentModel
Imports System.Globalization

Module TextBlockUtils

   Public ReadOnly AutoTooltipProperty As DependencyProperty = DependencyProperty.RegisterAttached("AutoTooltip", GetType(Boolean), GetType(TextBlockUtils), New FrameworkPropertyMetadata(False, New PropertyChangedCallback(AddressOf OnAutoTooltipPropertyChanged)))

   Sub SetAutoTooltip(ByVal d As DependencyObject, ByVal value As Boolean)
      d.SetValue(AutoTooltipProperty, value)
   End Sub

   Function GetAutoTooltip(ByVal d As DependencyObject) As Boolean
      Return CBool(d.GetValue(AutoTooltipProperty))
   End Function

   Private Sub OnAutoTooltipPropertyChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
      Dim tb As TextBlock = TryCast(d, TextBlock)

      If tb IsNot Nothing Then
         Dim newValue As Boolean = CBool(e.NewValue)

         If newValue Then
            tb.TextTrimming = TextTrimming.WordEllipsis
            SetTooltipBasedOnTrimmingState(tb)
            AddHandler tb.SizeChanged, AddressOf OnTextBlockSizeChanged
         Else
            RemoveHandler tb.SizeChanged, AddressOf OnTextBlockSizeChanged
         End If
      End If
   End Sub

   Private Sub OnTextBlockSizeChanged(ByVal sender As Object, ByVal e As SizeChangedEventArgs)
      Dim tb = TryCast(sender, TextBlock)

      If tb IsNot Nothing Then
         SetTooltipBasedOnTrimmingState(tb)
      End If
   End Sub

   Private Sub SetTooltipBasedOnTrimmingState(ByVal tb As TextBlock)
      Dim textBlock As FrameworkElement = CType(tb, FrameworkElement)
      textBlock.Measure(New System.Windows.Size(Double.PositiveInfinity, Double.PositiveInfinity))
      'textBlock.UpdateLayout()
      Dim width = tb.DesiredSize.Width
      ToolTipService.SetToolTip(tb, If((CType(tb, FrameworkElement)).ActualWidth < (CType(tb, FrameworkElement)).DesiredSize.Width, tb.Text, Nothing))
   End Sub

End Module

Public Class TrimmedTextBlockVisibilityConverter
   Implements IValueConverter

   Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert
      If value Is Nothing Then Return Visibility.Collapsed
      Dim textBlock As FrameworkElement = CType(value, FrameworkElement)
      textBlock.Measure(New System.Windows.Size(Double.PositiveInfinity, Double.PositiveInfinity))

      If (CType(value, FrameworkElement)).ActualWidth < (CType(value, FrameworkElement)).DesiredSize.Width Then
         Return Visibility.Visible
      Else
         Return Visibility.Collapsed
      End If
   End Function

   Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
      Throw New NotImplementedException()
   End Function

End Class
