ThinkGeo.com    |     Documentation    |     Premium Support

Feature Tooltip or hover text while over feature(line, multiline, poly, etc.)

What is the easiest way to programatically add a tooltip like effect to a feature?  For instance I have a lineshape that I want to display a tooltip when the user hovers over the line.  Same goes for polygons and multilineshapes...e.g., I was thinking of something like this:


 



Dim multilineShape As MultilineShape = CType(BaseShape.CreateShapeFromWellKnownData(mLineTxt), MultilineShape)   
'Would like to do something like this:
multilineShape.Tooltip = _myTooltipText
Dim feature As New Feature(multilineShape) 

'Or...Would like to do something like this: 
feature.Tooltip = _myTooltipText  
Dim MyinMemoryFeatureLayer As New InMemoryFeatureLayer
MyinMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(clr, lineWidth, False)
MyinMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20  
MyinMemoryFeatureLayer.InternalFeatures.Add(feature)  
LinesOverlay.Layers.Add("SF_LineLayer_" & i.ToString, MyinMemoryFeatureLayer)



Hello Michael, 



Thank you for your post and idea, but sorry to say, we only allow to set tooltip to a feature in 2.x version, for now popup or tooltip is not allowed to add to a feature. This feature is supposed to be added to a layer overlay (be added to a layer first and then add the layer to a layer overlay). 



But there is a sample that can show you how to add tooltip to a layer, I hope it can help you. 



Any more questions please let us know. 



Regards, 



Gary



MapToolTipSample.zip (13.9 KB)

Thanks Gary… this looks like it will help, but I will have to convert it to a WPF version when I get some time.

Here is what I did to get it to work:


First, I created a label in XAML:



<Label Visibility="Hidden" Content="Label" Height="28" HorizontalAlignment="Left" Margin="452,524,0,0" Name="lblMouseOver" VerticalAlignment="Top" />

The margin is arbitrary, but I stuck the label in the middle of the map for now.


Then in the mousemove:



    Private Sub WpfMap1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Input.MouseEventArgs) Handles WpfMap1.MouseMove
        Dim worldPointShape As PointShape = ExtentHelper.ToWorldCoordinate(WpfMap1.CurrentExtent, New ScreenPointF(e.GetPosition(WpfMap1).X, e.GetPosition(WpfMap1).Y), WpfMap1.ActualWidth, WpfMap1.ActualHeight)
        Dim MyOverlay As LayerOverlay = DirectCast(WpfMap1.Overlays("MyOverlay"), LayerOverlay)
        Dim showTooltipTolerance As Double = 0.1
        For j = 0 To MyOverlay.Layers.Count - 1
            Dim MouseChkBox As New RectangleShape(worldPointShape.X - showTooltipTolerance, _
                                                       worldPointShape.Y + showTooltipTolerance, _
                                                       worldPointShape.X + showTooltipTolerance, _
                                                       worldPointShape.Y - showTooltipTolerance)
            Dim bitmapLayer As InMemoryFeatureLayer = MyOverlay.Layers(j)
            Dim crossed As Boolean = False
            For i As Integer = 0 To bitmapLayer.InternalFeatures.Count - 1
                If MouseChkBox.GetDistanceTo(bitmapLayer.InternalFeatures(i), GeographyUnit.DecimalDegree, DistanceUnit.Mile) <= showTooltipTolerance Then crossed = True
            Next
            If crossed Then
                lblMouseOver.Margin = New Thickness(Border2.Margin.Left + e.GetPosition(WpfMap1).X _
                                                    , Border2.Margin.Top + e.GetPosition(WpfMap1).Y _
                                                    , Border2.Margin.Right - e.GetPosition(WpfMap1).X _
                                                    , Border2.Margin.Bottom - e.GetPosition(WpfMap1).Y)
                lblMouseOver.Content = "some content"
                lblMouseOver.Visibility = Visibility.Visible
            Else
                lblMouseOver.Visibility = Visibility.Hidden
            End If
        Next
    End Sub

Then I did not need the tooltip class and the performance seem great.  I had the map inside a border (border2) with no margin between the map and the border:



        <Border BorderBrush="Silver" BorderThickness="1" Height="582" HorizontalAlignment="Center" Margin="328,36,-1,263" Name="Border2" VerticalAlignment="Center" Width="1046">
            <my:WpfMap Name="WpfMap1" BorderThickness="1" BorderBrush="#FFBA3939" />
        </Border>



Hello Michael, 
  
 I’m glad you made it and thank you very much to post it, that will help others need this. 
  
 Regards, 
  
 Gary

Hi, 
  
 I was looking through the forum to find how to put in tooltips and thankfully found this example. 
  
 Is there any plan to integrate this functionality into WpfMap natively? 
  
 Personally, I think that it is a fundamental service that needs to be there and I would rather not write it in myself if it is planned to be integrated in some release. 
  
 Kris

Hi Kris
 
Thanks for your post, sorry to say that we don’t support “feature tooltip” for now. You can vote this enhancement to helpdesk.thinkgeo.com/EnhancementTracker. This captures the enhancement request and provides visibility to the customer letting them know that the enhancement is on a list somewhere and that popularity of the enhancement helps set the priority of when the enhancement would be added to the product. This option doesn’t carry any cost for you.
 
Or if you need this function immediately, your account rep can contact you for a professional services. 
 
Another thing is that there is an elevation place in Micheal’s solution.
In Wpf_MouseMove() we could add a timer, and move the code to the timer and let the timer to do the work, that way we don’t need to do the work every time the mouse moves.
 
Regards,
Edgar

As I use the above code for a large number of polygons (20k +), I was getting impacted by performance due to iteration.  So I modified the code to:


Private Sub WpfMap1_MouseMove(ByVal sender As ObjectByVal As System.Windows.Input.MouseEventArgs) Handles wpfMap1.MouseMove
    Dim imfLayer As InMemoryFeatureLayer = CType(wpfMap1.FindFeatureLayer(“MyIMFL”), InMemoryFeatureLayer)
    If imfLayer Is Nothing Then Exit Sub 'No layer exists so exit
    'Define bounary in pixels aroun poygon to trigger tooltip
    Dim screenBuffer As Integer = 5
    'Maintain buffer at any zoom level
    Dim currentPointF As New ScreenPointF(e.GetPosition(wpfMap1).X, e.GetPosition(wpfMap1).Y)
    Dim bufferPointF As New ScreenPointF(currentPointF.X + screenBuffer, currentPointF.Y)
    Dim distanceBuffer As Double = ExtentHelper.GetWorldDistanceBetweenTwoScreenPoints(wpfMap1.CurrentExtent, currentPointF, bufferPointF, wpfMap1.ActualWidth, wpfMap1.ActualHeight, wpfMap1.MapUnit, DistanceUnit.Meter)
    'Make sure there are features
    If imfLayer.InternalFeatures.Count > 0 Then
        'ToWorldCoordinate requires a column name, so just use a dummy or a real name if there is one
        Dim columnNames As New List(Of String)()
        columnNames.Add(“dummy”)
 
        Dim features As Collections.ObjectModel.Collection(Of Feature)
        Dim worldPointShape As PointShape = ExtentHelper.ToWorldCoordinate(wpfMap1.CurrentExtent, New ScreenPointF(e.GetPosition(wpfMap1).X, e.GetPosition(wpfMap1).Y), wpfMap1.ActualWidth, wpfMap1.ActualHeight)
        SyncLock imfLayer   'Lock the layer while opening it
            imfLayer.FeatureSource.Open()
            'Get features within the buffer zone distance
            features = imfLayer.FeatureSource.GetFeaturesNearestTo(worldPointShape, wpfMap1.MapUnit, 1, columnNames, distanceBuffer, DistanceUnit.Meter)
            imfLayer.FeatureSource.Close()
        End SyncLock
        If features.Count > 0 Then      'We got some features
            Dim As Feature = DirectCast(features(0), Feature) 'We are only interested in the first one
            Dim moc As MyOwnClass = DirectCast(f.Tag, MyOwnClass)   'Get the instance of MyOwnClass from the Tag property
            tblMouseOver.Text = moc.TooltipText     'Set the TexBlock text to our tooltip text
 
            'Show tooltip at top right of pointer, offset by 3 pixels
            tblMouseOver.Margin = New Thickness(Border2.Margin.Left + e.GetPosition(wpfMap1).X + 3 _
                                                , Border2.Margin.Top + e.GetPosition(wpfMap1).Y - 3 - tblMouseOver.ActualHeight _
                                                , Border2.Margin.Right - e.GetPosition(wpfMap1).X - 3 _
                                                , Border2.Margin.Bottom - e.GetPosition(wpfMap1).Y + 3 + tblMouseOver.ActualHeight)
            tblMouseOver.Visibility = Visibility.Visible
        Else
            tblMouseOver.Visibility = Visibility.Hidden
        End If
    Else
        tblMouseOver.Visibility = Visibility.Hidden
    End If
End Sub

Using this code appears give very good performance and changing the label to a textblock allows for additional formatting and multiple lines.

I’ve attached a complete working sample that has some very small polygons as a way of testing.

ThinkGeoExampleMouseOverTooltip.zip (1.7 MB)

Hi Micheal, 



Thank you very much for your sharing this, this will be also helpful to other customers who meet similar problem.  And if you have any more question , please feel free to let us know. 



Best Regards 



Summer