Map Content Updates
DockWindow.vb
' Copyright 2011 ESRI
' 
' All rights reserved under the copyright laws of the United States
' and applicable international laws, treaties, and conventions.
' 
' You may freely redistribute and use this sample code, with or
' without modification, provided you include the original copyright
' notice and use restrictions.
' 
' See the use restrictions.
' 

Imports Microsoft.VisualBasic
Imports System
Imports System.Linq
Imports System.Windows.Forms

Imports ESRI.ArcGISExplorer.Geometry
Imports ESRI.ArcGISExplorer.Mapping

Public Class DockWindow
  Inherits ESRI.ArcGISExplorer.Application.DockWindow
  Private m_disp As MapDisplay = Nothing

  Public Sub New()
    InitializeComponent()

    'Listen to the changing of the map items as well as selections in our tree views.
    AddHandler ESRI.ArcGISExplorer.Application.Application.MapItemChanged, AddressOf Application_MapItemChanged
    AddHandler tvwMapItems.AfterSelect, AddressOf tvwMapItems_AfterSelect
    AddHandler tvwLayerOrder.AfterSelect, AddressOf tvwLayerOrder_AfterSelect

    'Initialize the map display variable
    m_disp = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay
  End Sub

  Private Sub tvwLayerOrder_AfterSelect(ByVal sender As Object, ByVal e As TreeViewEventArgs) Handles tvwLayerOrder.AfterSelect
    UpdateLayerOrderButtons()
  End Sub

  Private Sub UpdateLayerOrderButtons()
    'Routine called when a selection is made in our layer drawing order treeview.
    'Enable the up and down buttons appropriately depending on what was selected.
    If tvwLayerOrder.SelectedNode Is Nothing Then
      btnUp.Enabled = False
      btnDown.Enabled = False
      btnAllDown.Enabled = False
      btnAllUp.Enabled = False
    Else
      btnUp.Enabled = True
      btnDown.Enabled = True
      btnAllDown.Enabled = True
      btnAllUp.Enabled = True
      If tvwLayerOrder.SelectedNode.PrevNode Is Nothing Then
        btnUp.Enabled = False
        btnAllUp.Enabled = False
      End If
      If tvwLayerOrder.SelectedNode.NextNode Is Nothing Then
        btnDown.Enabled = False
        btnAllDown.Enabled = False
      End If
    End If
  End Sub

  Private Sub tvwMapItems_AfterSelect(ByVal sender As Object, ByVal e As TreeViewEventArgs) Handles tvwMapItems.AfterSelect
    'Routine called when a selection is made from our map items tree view.
    'If there is a valid selection, then an enable the delete/remove button.
    If e.Node Is Nothing Then
      btnDelete.Enabled = False
    Else
      btnDelete.Enabled = True
    End If
  End Sub

  Private Sub Application_MapItemChanged(ByVal sender As Object, ByVal e As MapItemEventArgs)
    'When the map items change, then refresh our list on the dock window
    UpdateMapItems()
  End Sub

  Private Sub UpdateMapItems()
    'When the map items change, then refresh our list of map contents
    tvwMapItems.Nodes.Clear()
    For Each item As MapItem In m_disp.Map.ChildItems
      If TypeOf item Is Folder Then
        SearchChildren(item, Nothing)
      Else
        Dim newNode As TreeNode = tvwMapItems.Nodes.Add(item.Name)
        newNode.Tag = item
      End If
    Next item

    'Also update the drawing order list for layers
    UpdateLayerOrder()
  End Sub

  Private Sub UpdateLayerOrder()
    'Also update the drawing order list for layers
    tvwLayerOrder.Nodes.Clear()
    For Each layer As Layer In m_disp.Map.LayerDrawingOrder
      Dim newLayer As TreeNode = tvwLayerOrder.Nodes.Add(layer.Name)
      newLayer.Tag = layer
    Next layer

    'null out the selected node to make sure all buttons with treeview are disabled
    tvwLayerOrder.SelectedNode = Nothing
    UpdateLayerOrderButtons()
  End Sub

  Private Sub SearchChildren(ByVal inItem As MapItem, ByVal folderNode As TreeNode)
    'Routine for drilling into the map contents and reproducing the information in the 
    'treeview on our dockable window.
    Dim fold As Folder = CType(inItem, Folder)
    Dim newNode As TreeNode = Nothing
    If folderNode Is Nothing Then
      newNode = tvwMapItems.Nodes.Add(fold.Name)
    Else
      newNode = folderNode.Nodes.Add(fold.Name)
    End If
    newNode.Tag = fold

    'Loop through the children of the folder passed into the routine
    For Each item As MapItem In fold.ChildItems
      If TypeOf item Is Folder Then
        SearchChildren(item, newNode)
      Else
        Dim newerNode As TreeNode = newNode.Nodes.Add(item.Name)
        newerNode.Tag = item
      End If
    Next item
  End Sub

  Private Sub btnShapefile_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnShapefile.Click
    'Routine for adding shapefile data to the map.  Begin by browsing for the data.
    Dim fdlg As OpenFileDialog = New OpenFileDialog()
    fdlg.Title = "Add Shapefile"
    fdlg.InitialDirectory = "C:\ "
    fdlg.Filter = "Shapefiles (*.shp)|*.shp"
    fdlg.FilterIndex = 2
    fdlg.RestoreDirectory = True

    'If a shapefile is found, then create a FeatureLayer based on it, add symbology,
    'add the data to the map, and then zoom in.
    If fdlg.ShowDialog() = DialogResult.OK Then
      Try
        Dim fl As FeatureLayer = FeatureLayer.OpenShapefile(fdlg.FileName)
        fl.Renderer.SetSymbol(CreateSymbol(fl.GeometryType))
        m_disp.Map.ChildItems.Add(fl)
        m_disp.ZoomTo(fl.Extent)

      Catch ex As Exception
        MessageBox.Show("Failed to add shapefile:" & Environment.NewLine & fdlg.FileName, _
         "Error Adding Shapefile", MessageBoxButtons.OK, MessageBoxIcon.Error)

      End Try
    End If
  End Sub

  Private Function CreateSymbol(ByVal geomType As GeometryType) As Symbol
    'Create a new symbol for the feature layer data being added based on feature type
    Dim sym As Symbol = Nothing
    Select Case geomType
      Case GeometryType.Point
        sym = Symbol.Marker.Pushpin.LightBlue
      Case GeometryType.Polygon
        sym = Symbol.CreateFill(System.Drawing.Color.Aqua, System.Drawing.Color.Black)
      Case GeometryType.Polyline
        sym = Symbol.Line.Solid.Purple
    End Select

    Return sym
  End Function

  Private Sub btnKML_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnKML.Click
    'Routine for adding KML and KMZ data to the map
    'Begin by browsing for the file 
    Dim fdlg As OpenFileDialog = New OpenFileDialog()
    fdlg.Title = "Add KML or KMZ based data"
    fdlg.InitialDirectory = "C:\ "
    fdlg.Filter = "KML Files (*.kml, *.kmz)|*.kml;*.kmz"
    fdlg.FilterIndex = 2
    fdlg.RestoreDirectory = True

    'If a file was located, then add the contents to the map and zoom in
    If fdlg.ShowDialog() = DialogResult.OK Then
      Try
        Dim kml As KmlLayer = KmlLayer.Open(fdlg.FileName)
        m_disp.Map.ChildItems.Add(kml)
        m_disp.ZoomTo(kml.Extent)

      Catch ex As Exception
        MessageBox.Show("Failed to add KML:" & Environment.NewLine & fdlg.FileName, _
        "Error Adding KML", MessageBoxButtons.OK, MessageBoxIcon.Error)

      End Try
    End If
  End Sub

  Private Sub btnShared_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnShared.Click
    'Routine for adding shared content (layer package files) to the map
    'Begin by browsing for the file
    Dim fdlg As OpenFileDialog = New OpenFileDialog()
    fdlg.Title = "Add shared content"
    fdlg.InitialDirectory = "C:\ "
    fdlg.Filter = "Shared content (*.lpk)|*.lpk"
    fdlg.FilterIndex = 2
    fdlg.RestoreDirectory = True

    'If a file was found, then add the contents to the map and zoom in
    If fdlg.ShowDialog() = DialogResult.OK Then
      Try
        Dim lpk As PackageLayer = PackageLayer.OpenLayerFile(fdlg.FileName)
        m_disp.Map.ChildItems.Add(lpk)
        m_disp.ZoomTo(lpk.Extent)

      Catch ex As Exception
        MessageBox.Show("Failed to add layer package:" & Environment.NewLine & fdlg.FileName, _
        "Error Adding Package", MessageBoxButtons.OK, MessageBoxIcon.Error)

      End Try
    End If
  End Sub

  Private Sub btnService_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnService.Click
    'Open up a new form for adding server content to the map
    Dim form As frmServer = New frmServer()
    form.ShowDialog()
  End Sub

  Private Sub btnContent_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnContent.Click
    'Routine for adding content from a map contents file into the map.
    'Begin by browsing for the contents file
    Dim fdlg As OpenFileDialog = New OpenFileDialog()
    fdlg.Title = "Add content file"
    fdlg.InitialDirectory = "C:\ "
    fdlg.Filter = "Content file (*.nmc)|*.nmc"
    fdlg.FilterIndex = 2
    fdlg.RestoreDirectory = True
    If fdlg.ShowDialog() = DialogResult.OK Then
      'open up the map contents file and make sure it is valid
      Dim nmfDoc As ESRI.ArcGISExplorer.Mapping.NmfDocument = NmfDocument.LoadFromFile(fdlg.FileName)
      If nmfDoc Is Nothing Then
        Return
      End If
      If nmfDoc.HasErrors Then
        Return
      End If

      'Loop through the contents of the file adding to the map
      For Each item As MapItem In nmfDoc.ChildItems
        'Check to see if the item has children, then add it to the map
        ConnectItemAndChildItems(item)
        m_disp.Map.ChildItems.Add(item)

        'If we are only bring in one item, then zoom to it if appropriate
        If nmfDoc.ChildItems.Count = 1 Then
          If TypeOf item Is FeatureLayer Then
            Dim layer As FeatureLayer = CType(item, FeatureLayer)
            If Not layer.Extent Is Nothing Then
              m_disp.ZoomTo(layer.Extent)
            End If
          ElseIf TypeOf item Is ESRI.ArcGISExplorer.Mapping.View Then
            Dim vw As ESRI.ArcGISExplorer.Mapping.View = CType(item, ESRI.ArcGISExplorer.Mapping.View)
            m_disp.ZoomTo(vw.Viewpoint)
          End If
        End If
      Next item
    End If
  End Sub

  Private Shared Sub ConnectItemAndChildItems(ByVal item As MapItem)
    'Routine for drilling into folders within the content in the map contents file being added
    If TypeOf item Is Layer Then
      CType(item, Layer).Connect()
    End If

    'If the selected item is a parent, then drill down further
    If TypeOf item Is IMapItemParent Then
      Dim parentItem As IMapItemParent = TryCast(item, IMapItemParent)
      For Each childItem As MapItem In parentItem.ChildItems
        ConnectItemAndChildItems(childItem)
      Next childItem
    End If
  End Sub


  Private Sub btnRaster_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnRaster.Click
    'Open a dialog allowing the user to browse for the raster data to add
    Dim fdlg As OpenFileDialog = New OpenFileDialog()
    fdlg.Title = "Raster data"
    fdlg.InitialDirectory = "C:\ "
    fdlg.Filter = "Raster Files (*.png, *.sid, *.tif)|*.png;*.sid;*.tif"
    fdlg.FilterIndex = 2
    fdlg.RestoreDirectory = True
    'If a raster was selected, then add that to the map
    If fdlg.ShowDialog() = DialogResult.OK Then
      Try
        Dim ras As RasterLayer = RasterLayer.OpenRasterFile(fdlg.FileName)
        m_disp.Map.ChildItems.Add(ras)
        m_disp.ZoomTo(ras.Extent)

      Catch ex As Exception
        MessageBox.Show("Failed to add raster:" & Environment.NewLine & fdlg.FileName, _
        "Error Adding Raster", MessageBoxButtons.OK, MessageBoxIcon.Error)

      End Try
    End If
  End Sub

  Private Sub btnUp_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnUp.Click
    'Move the selected layer up one spot in the drawing order
    Dim loColl As LayerOrderCollection = m_disp.Map.LayerDrawingOrder
    loColl.MoveUp(TryCast(tvwLayerOrder.SelectedNode.Tag, Layer))
    UpdateLayerOrder()
  End Sub

  Private Sub btnDown_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnDown.Click
    'Move the selected layer down one spot in the drawing order
    Dim loColl As LayerOrderCollection = m_disp.Map.LayerDrawingOrder
    loColl.MoveDown(TryCast(tvwLayerOrder.SelectedNode.Tag, Layer))
    UpdateLayerOrder()
  End Sub

  Private Sub btnAllUp_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnAllUp.Click
    'Move selected layer to the top of draw order
    Dim loColl As LayerOrderCollection = m_disp.Map.LayerDrawingOrder
    loColl.MoveToTop(TryCast(tvwLayerOrder.SelectedNode.Tag, Layer))
    UpdateLayerOrder()
  End Sub

  Private Sub btnAllDown_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnAllDown.Click
    'Move selected layer to the bottom of the draw order
    Dim loColl As LayerOrderCollection = m_disp.Map.LayerDrawingOrder
    Dim key As String = tvwLayerOrder.SelectedNode.Text
    loColl.MoveToBottom(TryCast(tvwLayerOrder.SelectedNode.Tag, Layer))
    UpdateLayerOrder()
  End Sub

  Private Sub btnDelete_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnDelete.Click
    'Remove the selected item from the map and the Map Items list
    If tvwMapItems.SelectedNode Is Nothing Then
      Return
    End If

    'Remove the selected node from the map contents collection and the tree view control
    m_disp.Map.ChildItems.Remove(TryCast(tvwMapItems.SelectedNode.Tag, MapItem))

    'Make sure the map items list is updated
    UpdateMapItems()
    btnDelete.Enabled = False
  End Sub

  Private Sub btnFileGDB_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnFileGDB.Click
    'Open up a new form for adding file geodatabase content to the map
    Dim form As frmFileGDB = New frmFileGDB()
    form.Show()
  End Sub
End Class