现在的位置: 首页 > 综合 > 正文

实现zoom to the selected feature之三:Follow-up to Extending the QueryAttributes Task: Zooming to selected features

2012年09月17日 ⁄ 综合 ⁄ 共 4808字 ⁄ 字号 评论关闭
文章目录

Follow-up to Extending the QueryAttributes Task: Zooming to selected features

From Bryan Baker, a product engineer working on the .NET SDK: 

I wrote an earlier post that showed how to extend the QueryAttributes task so that all features are immediately highlighted. Several users have asked about also zooming to the selected features. I'll show that here, though keep in mind that the user can also zoom to the selected features by right-clicking on the node for the layer (Cities in the graphic at the top of the earlier post) and choosing to zoom to selected features.

It turns out that it's a little more difficult to zoom to the features than I originally thought, because the FullExtent property of the graphics layer is null for queries like this. Instead, we have to construct our own envelope around all the features by looping through them. This isn't that difficult, though of course it does require more processing.

I’ve included code below that does the zooming. This code should be added to near the bottom of the existing code in the earlier post. If for some reason you didn’t want to highlight all the features, you could omit or comment out the line in the loop that sets the selectedCol to true.

The code below first creates an envelope to use, then in the existing loop that selects each feature, it widens the envelope to surround each feature. Once it has the envelope, it gets a reference to the Map control so it can set the Map’s extent. This takes some work, since the task itself has no reference to the Map. We have to get the ID of the Map and then search the page’s control tree. Since the Map control could be nested within another control, such as in a FloatingPanel, we search for it recursively using a custom function (found at the bottom of this listing).

One more thing before we zoom the map: the task could be querying a point layer, and if only one point is found, the “envelope” around all features is a point. We can’t zoom to a point, so instead we set the envelope to a percentage of the full extent of the Map (five percent—this value is hard-coded here, and you can change it depending on tightly you want to zoom in this one-point case).

Finally, we’ve got an envelope that will work, and we set the Map to this extent, refresh the Map, and copy its CallbackResults to the task’s CallbackResults. This last step is necessary because a callback only works with one control (the task in this case), and we need to tell another control (the Map) to update its contents.

    ' Set up the items to hold the extent of all features

    Dim geom As ESRI.ArcGIS.ADF.Web.Geometry.Geometry

    Dim layerEnv As New _

       ESRI.ArcGIS.ADF.Web.Geometry.Envelope( _

       Double.MaxValue, Double.MaxValue, _

       Double.MinValue, Double.MinValue)

 

    ' Set each feature to selected (this loop is

    ' at the end the code in my previous blog post)

For Each row As DataRow In graphicsLayer.Rows

   row(selectedCol) = True

 

    ' Enlarge the overall envelope to

    ' include the current feature

   geom = graphicsLayer.GeometryFromRow(row)

   layerEnv.Union(geom)

Next

 

    ' If any records found, zoom to them

If graphicsLayer.Rows.Count > 0 Then

 

    ' Get a reference to the Map - have to search the Page since

    '  task itself has no direct reference to the Map

    ' (the task's TaskResults does have the ID of the map)

    Dim mapCtrl As Map = Nothing

   Dim taskResultsId As String =

      Me.TaskResultsContainers(0).Name

    Dim taskResults As TaskResults = _

       CType(FindControlRecursive( _

       Me.Page, taskResultsId), TaskResults)

   If Not TaskResults Is Nothing Then

      mapCtrl = CType(FindControlRecursive( _

         Me.Page, taskResults.Map), Map)

   End If

 

   If Not mapCtrl Is Nothing Then

 

    ' If only one point found, envelope will be a point

    '   -- set to a percentage of the full extent

      If layerEnv.XMin = layerEnv.XMax AndAlso _

         layerEnv.YMin = layerEnv.YMax AndAlso _

         Not IsNothing(mapCtrl) Then

 

    ' Percentage of the full extent to use when zooming to point

    Dim zoomToPointPercentage As Integer = 5

 

    Dim NewWidth As Double = mapCtrl.GetFullExtent().Width _

       * (zoomToPointPercentage / 100)

    Dim NewHeight As Double = mapCtrl.GetFullExtent().Height _

       * (zoomToPointPercentage / 100)

         layerEnv.XMin -= NewWidth / 2

         layerEnv.XMax += NewWidth / 2

         layerEnv.YMin -= NewHeight / 2

         layerEnv.YMax += NewHeight / 2

      End If

 

    ' Now we can zoom the map to the extent of the features

      mapCtrl.Extent = layerEnv

      mapCtrl.Refresh()

 

    ' We have to tell the client to refresh, using CallbackResults

      Me.CallbackResults.CopyFrom(mapCtrl.CallbackResults)

   End If

End If

Below is the function called in the above code. This searches the page and its child controls for the control with the given ID. Put this after the end of the Execute method (End Sub), but inside the Class (before the End Class statement).

    ' Finds the control in the Page's control tree

    Public Function FindControlRecursive(ByVal root As _

       Control, ByVal id As String) As Control

 

        If root.ID = id Then

            Return root

        End If

 

        Dim c As Control

        For Each c In root.Controls

            Dim t As Control = FindControlRecursive(c, id)

            If Not t Is Nothing Then

                Return t

            End If

        Next

 

        Return Nothing

    End Function

If you add the code above to the custom task as outlined in the earlier blog post, it should automatically zoom to the extent of all features found by the task.

 

Published Thursday, May 03, 2007 12:15 PM by Sterling

Filed under: , , ,

Comments

New Comments to this post are disabled

 

抱歉!评论已关闭.