Layer Attributes
LayerAttributesDockWindow.vb
' Copyright 2010 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 System.Collections.Generic
Imports System.ComponentModel
Imports System.Drawing
Imports System.Data
Imports System.Linq
Imports System.Text
Imports System.Windows.Forms
Imports System.Collections
Imports System.Collections.ObjectModel

Imports ESRI.ArcGISExplorer
Imports ESRI.ArcGISExplorer.Application
Imports ESRI.ArcGISExplorer.Mapping
Imports ESRI.ArcGISExplorer.Geometry
Imports ESRI.ArcGISExplorer.Data
Imports ESRI.ArcGISExplorer.Threading

Public Partial Class LayerAttributesDockWindow
  Inherits ESRI.ArcGISExplorer.Application.DockWindow
  ' <summary>
  ' The current Map.  Note that this variable will be reset in the Application_DocumentOpened
  ' when a new map is opened.
  ' </summary>
  Private _map As Map = Nothing

  ' <summary>
  ' A List of all the open LayerAttributesForm forms.
  ' </summary>
  Private _openForms As New List(Of LayerAttributesForm)()

  ' <summary>
  ' Initializes a new instance of the LayerAttributesDockWindow class.
  ' </summary>
  Public Sub New()
    InitializeComponent()
  End Sub

  ' <summary>
  ' Handles the Load event of the AttributesDockWindow control by settting up events which
  ' a required for maintaining business logic within the addin.
  ' </summary>
  Private Sub AttributesDockWindow_Load(ByVal sender As Object, ByVal e As EventArgs)
    AddHandler ESRI.ArcGISExplorer.Application.Application.DocumentOpened, New EventHandler(AddressOf Application_DocumentOpened)
    AddHandler ESRI.ArcGISExplorer.Application.Application.MapItemChanged, New EventHandler(Of MapItemEventArgs)(AddressOf Application_MapItemChanged)

    'won't fire first time so call it manually
    Application_DocumentOpened(Nothing, Nothing)
  End Sub

  ' <summary>
  ' Handles the double-click event of the lstFLayer Listbox by Opening a form displaying 
  ' the attributes of the selected feature layer.
  ' </summary>
  Private Sub lstFLayers_DoubleClick(ByVal sender As Object, ByVal e As EventArgs)
    Try

      'Check whether an item has been selected 
      If lstFLayers.SelectedItem IsNot Nothing Then
        'Check whether a LayerAttributesForm for this feature layer is already open
        If IsAttributeWindowOpenForLayer(DirectCast(lstFLayers.SelectedItem, FeatureLayer)) Then
          'just give the form focus
          Dim attForm As LayerAttributesForm = GetOpenAttributesForm(DirectCast(lstFLayers.SelectedItem, FeatureLayer))
          If attForm IsNot Nothing Then
            attForm.Focus()
          End If
        Else
          '***********************************************************************
          'Important Code - Create a new form to display the attribute information
          '***********************************************************************
          ShowAttributesForm()
        End If
      End If
    Catch ex As Exception
      MessageBox.Show("An error has occurred while showing the form: " & ex.Message, "Error", MessageBoxButtons.OK)
    End Try

  End Sub

  ' <summary>
  ' Handles the DocumentOpened event by initializing the map variable and setting up the DocWindow display.
  ' </summary>
  Private Sub Application_DocumentOpened(ByVal sender As Object, ByVal e As EventArgs)

    _map = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay.Map

    SetupDisplayFeatureLayerAttributesUsage()

    'add the names of all the feature layers in the current map to the listbox
    Dim layers As ReadOnlyCollection(Of FeatureLayer) = _map.GetMapItems(Of FeatureLayer)()

    lstFLayers.Items.Clear()

    For Each fl As FeatureLayer In layers
      lstFLayers.Items.Add(fl)
    Next
  End Sub

  ' <summary>
  ' Handles the MapItemChanged event to keep the DocWindow listbox content sychronized 
  ' with the application's table of contents window.
  ' </summary>
  ' <param name="sender">The source of the event.</param>
  ' <param name="e">A MapItemEventArgs object containing the event data which includes notifications
  ' for when layers are added or removed.</param> 
  Private Sub Application_MapItemChanged(ByVal sender As Object, ByVal e As MapItemEventArgs)

    'only check map item changes invloving feature layers
    If TypeOf e.MapItem Is FeatureLayer Then

      Dim fLayer As FeatureLayer = DirectCast(e.MapItem, FeatureLayer)

      If e.Status = MapItemChangeStatus.Added Then

        'a new feature layer has been added, so add it to the listbox as well
        lstFLayers.Items.Add(fLayer)

      ElseIf e.Status = MapItemChangeStatus.Removing Or e.Status = MapItemChangeStatus.RemovingChild Then

        'A feature layer is being removed from the table of contents so close the 
        'LayerAttributesForm for this feature layer if it is open 

        'create a temporary list of forms to remove
        Dim formsToRemoveFromOpenFormsList As New List(Of LayerAttributesForm)()

        'add forms to the temporary list
        For Each attForm As LayerAttributesForm In _openForms
          Dim fl As FeatureLayer = attForm.FeatureLayer

          If fLayer Is fl Then
            formsToRemoveFromOpenFormsList.Add(attForm)
          End If
        Next

        'now iterate list of forms to close;
        For Each attform As LayerAttributesForm In formsToRemoveFromOpenFormsList
          attform.Close()  'this will cause the form_FormClosing event to fire
        Next

        'remove it from the listbox.
        For Each listboxItem As FeatureLayer In lstFLayers.Items
          If TypeOf listboxItem Is FeatureLayer Then
            lstFLayers.Items.Remove(listboxItem)
            Exit For
          End If
        Next

      End If

      'refresh the list box labels if required
      SetupDisplayFeatureLayerAttributesUsage()
    End If
  End Sub

  ' <summary>
  ' Handles the FormClosing event by simply removing a reference to the form from the _openForms ArrayList
  ' </summary>
  Private Sub form_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs)
    Dim attributesForm As LayerAttributesForm = DirectCast(sender, LayerAttributesForm)

    For Each foundForm As LayerAttributesForm In _openForms
      If attributesForm Is foundForm Then
        _openForms.Remove(attributesForm)
        Exit For
      End If
    Next
  End Sub

#Region "private methods"

  ' <summary>
  ' Creates a new LayerAttributesForm for the specified feature layer, then displays it.
  ' </summary>
  Private Sub ShowAttributesForm()
    Dim form As New LayerAttributesForm(DirectCast(lstFLayers.SelectedItem, FeatureLayer))

    AddHandler form.FormClosing, New FormClosingEventHandler(AddressOf form_FormClosing)
    'display the form
    form.Show(ESRI.ArcGISExplorer.Application.Application.Window)

    'add form to list of open forms
    _openForms.Add(form)

  End Sub

  ' <summary>
  ' Sets up the labels and listbox status for the doc window.
  ' </summary>
  Private Sub SetupDisplayFeatureLayerAttributesUsage()
    If _map.GetMapItems(Of FeatureLayer)().Count = 0 Then
      label1.Text = "No feature layers in map"
      label2.Text = ""
      lstFLayers.Enabled = False
    Else
      label1.Text = "View the attributes of a feature layer"
      label2.Text = "in the map by double clicking on the item."
      lstFLayers.Enabled = True
    End If
  End Sub

  ' <summary>
  ' Checks to see whether a LayerAttributesForm object already exists for this feature layer.
  ' </summary>
  ' <param name="item">A FeatureLayer</param>
  ' <returns>true if the form is found, otherwise false.</returns>
  Private Function IsAttributeWindowOpenForLayer(ByVal item As FeatureLayer) As Boolean
    Dim foundAttributesForm As Boolean = False

    For Each form As LayerAttributesForm In _openForms
      Dim fl As FeatureLayer = form.FeatureLayer

      If item Is fl Then
        foundAttributesForm = True
        Exit For
      End If
    Next

    Return foundAttributesForm
  End Function

  ' <summary>
  ' Returns the attributes form for a particular feature layer.
  ' </summary>
  ' <param name="item">A FeatureLayer</param>
  ' <returns>A LayerAttributesForm object which is used to display the attribute data. 
  ' Returns null if a corresponding form is not found.</returns>
  Private Function GetOpenAttributesForm(ByVal item As FeatureLayer) As LayerAttributesForm
    Dim openForm As LayerAttributesForm = Nothing

    For Each form As LayerAttributesForm In _openForms
      Dim fl As FeatureLayer = form.FeatureLayer

      If item Is fl Then
        openForm = form
        Exit For
      End If
    Next
    Return openForm
  End Function

  ' <summary>
  ' Closes all open attribute forms
  ' </summary>
  Private Sub CloseAllOpenAttributeForms()
    For Each foundForm As LayerAttributesForm In _openForms
      foundForm.Close()
      'then closing event should fire to tidy up resources
      Exit For
    Next
  End Sub
#End Region

End Class