Map Content Updates
DockWindow.cs
// 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.
// 

using System;
using System.Linq;
using System.Windows.Forms;

using ESRI.ArcGISExplorer.Geometry;
using ESRI.ArcGISExplorer.Mapping;

namespace MapContentUpdatesCS
{
  public partial class DockWindow : ESRI.ArcGISExplorer.Application.DockWindow
  {
    private MapDisplay m_disp = null;

    public DockWindow()
    {
      InitializeComponent();

      //Listen to the changing of the map items as well as selections in our tree views.
      ESRI.ArcGISExplorer.Application.Application.MapItemChanged += new EventHandler<MapItemEventArgs>(Application_MapItemChanged);
      tvwMapItems.AfterSelect += new TreeViewEventHandler(tvwMapItems_AfterSelect);
      tvwLayerOrder.AfterSelect += new TreeViewEventHandler(tvwLayerOrder_AfterSelect);

      //Initialize the map display variable
      m_disp = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay;
    }

    void tvwLayerOrder_AfterSelect(object sender, TreeViewEventArgs e)
    {
      UpdateLayerOrderButtons();
    }

    void 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 == null)
      {
        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 == null)
        {
          btnUp.Enabled = false;
          btnAllUp.Enabled = false;
        }
        if (tvwLayerOrder.SelectedNode.NextNode == null)
        {
          btnDown.Enabled = false;
          btnAllDown.Enabled = false;
        }
      }
    }

    void tvwMapItems_AfterSelect(object sender, TreeViewEventArgs e)
    {
      //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 == null) btnDelete.Enabled = false;
      else btnDelete.Enabled = true;
    }

    void Application_MapItemChanged(object sender, MapItemEventArgs e)
    {
      //When the map items change, then refresh our list on the dock window
      UpdateMapItems();
    }

    private void UpdateMapItems()
    {
      //When the map items change, then refresh our list of map contents
      tvwMapItems.Nodes.Clear();
      foreach (MapItem item in m_disp.Map.ChildItems)
      {
        if (item is Folder) SearchChildren(item, null);
        else
        {
          TreeNode newNode = tvwMapItems.Nodes.Add(item.Name);
          newNode.Tag = item;
        }
      }

      //Also update the drawing order list for layers
      UpdateLayerOrder();
    }

    private void UpdateLayerOrder()
    {
      //Also update the drawing order list for layers
      tvwLayerOrder.Nodes.Clear();
      foreach (Layer layer in m_disp.Map.LayerDrawingOrder)
      {
        TreeNode newLayer = tvwLayerOrder.Nodes.Add(layer.Name);
        newLayer.Tag = layer;
      }

      //null out the selected node to make sure all buttons with treeview are disabled
      tvwLayerOrder.SelectedNode = null;
      UpdateLayerOrderButtons();
    }

    private void SearchChildren(MapItem inItem, TreeNode folderNode)
    {
      //Routine for drilling into the map contents and reproducing the information in the 
      //treeview on our dockable window.
      Folder fold = (Folder)inItem;
      TreeNode newNode = null;
      if (folderNode == null) newNode = tvwMapItems.Nodes.Add(fold.Name);
      else newNode = folderNode.Nodes.Add(fold.Name);
      newNode.Tag = fold;

      //Loop through the children of the folder passed into the routine
      foreach (MapItem item in fold.ChildItems)
      {
        if (item is Folder) SearchChildren(item, newNode);
        else
        {
          TreeNode newerNode = newNode.Nodes.Add(item.Name);
          newerNode.Tag = item;
        }
      }
    }

    private void btnShapefile_Click(object sender, EventArgs e)
    {
      //Routine for adding shapefile data to the map.  Begin by browsing for the data.
      OpenFileDialog fdlg = 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)
      {
        try
        {
          FeatureLayer fl = FeatureLayer.OpenShapefile(fdlg.FileName);
          fl.Renderer.SetSymbol(CreateSymbol(fl.GeometryType));
          m_disp.Map.ChildItems.Add(fl);
          m_disp.ZoomTo(fl.Extent);
        }
        catch (Exception)
        {
          MessageBox.Show("Failed to add shapefile:" + Environment.NewLine + fdlg.FileName,
            "Error Adding Shapefile", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

      }
    }

    private Symbol CreateSymbol(GeometryType geomType)
    {
      //Create a new symbol for the feature layer data being added based on feature type
      Symbol sym = null;
      switch (geomType)
      {
        case GeometryType.Point:
          sym = Symbol.Marker.Pushpin.LightBlue;
          break;
        case GeometryType.Polygon:
          sym = Symbol.CreateFill(System.Drawing.Color.Aqua, System.Drawing.Color.Black);
          break;
        case GeometryType.Polyline:
          sym = Symbol.Line.Solid.Purple;
          break;
      }

      return sym;
    }

    private void btnKML_Click(object sender, EventArgs e)
    {
      //Routine for adding KML and KMZ data to the map
      //Begin by browsing for the file 
      OpenFileDialog fdlg = 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)
      {
        try
        {
          KmlLayer kml = KmlLayer.Open(fdlg.FileName);
          m_disp.Map.ChildItems.Add(kml);
          m_disp.ZoomTo(kml.Extent);
        }
        catch (Exception)
        {
          MessageBox.Show("Failed to add KML layer:" + Environment.NewLine + fdlg.FileName,
            "Error Adding KML Layer", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

      }
    }

    private void btnShared_Click(object sender, EventArgs e)
    {
      //Routine for adding shared content (layer package files) to the map
      //Begin by browsing for the file
      OpenFileDialog fdlg = 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)
      {
        try
        {
          PackageLayer lpk = PackageLayer.OpenLayerFile(fdlg.FileName);
          m_disp.Map.ChildItems.Add(lpk);
          m_disp.ZoomTo(lpk.Extent);
        }
        catch (Exception)
        {
          MessageBox.Show("Failed to add layer package:" + Environment.NewLine + fdlg.FileName,
            "Error Adding Package", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
      }
    }

    private void btnService_Click(object sender, EventArgs e)
    {
      //Open up a new form for adding server content to the map
      frmServer form = new frmServer();
      form.ShowDialog();
    }

    private void btnContent_Click(object sender, EventArgs e)
    {
      //Routine for adding content from a map contents file into the map.
      //Begin by browsing for the contents file
      OpenFileDialog fdlg = 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)
      {
        //open up the map contents file and make sure it is valid
        ESRI.ArcGISExplorer.Mapping.NmfDocument nmfDoc = NmfDocument.LoadFromFile(fdlg.FileName);
        if (nmfDoc == null) return;
        if (nmfDoc.HasErrors) return;

        //Loop through the contents of the file adding to the map
        foreach (MapItem item 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)
          {
            if (item is FeatureLayer)
            {
              FeatureLayer layer = (FeatureLayer)item;
              if (layer.Extent != null)
                m_disp.ZoomTo(layer.Extent);
            }
            else if (item is ESRI.ArcGISExplorer.Mapping.View)
            {
              ESRI.ArcGISExplorer.Mapping.View vw = (ESRI.ArcGISExplorer.Mapping.View)item;
              m_disp.ZoomTo(vw.Viewpoint);
            }
          }
        }
      }
    }

    private static void ConnectItemAndChildItems(MapItem item)
    {
      //Routine for drilling into folders within the content in the map contents file being added
      if (item is Layer)
        ((Layer)item).Connect();

      //If the selected item is a parent, then drill down further
      if (item is IMapItemParent)
      {
        IMapItemParent parentItem = item as IMapItemParent;
        foreach (MapItem childItem in parentItem.ChildItems)
          ConnectItemAndChildItems(childItem);
      }
    }


    private void btnRaster_Click(object sender, EventArgs e)
    {
      //Open a dialog allowing the user to browse for the raster data to add
      OpenFileDialog fdlg = 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)
      {
        try
        {
          RasterLayer ras = RasterLayer.OpenRasterFile(fdlg.FileName);
          m_disp.Map.ChildItems.Add(ras);
          m_disp.ZoomTo(ras.Extent);
        }
        catch (Exception)
        {
          MessageBox.Show("Failed to add Raster layer:" + Environment.NewLine + fdlg.FileName,
            "Error Adding Raster Layer", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

      }
    }

    private void btnUp_Click(object sender, EventArgs e)
    {
      //Move the selected layer up one spot in the drawing order
      LayerOrderCollection loColl = m_disp.Map.LayerDrawingOrder;
      loColl.MoveUp(tvwLayerOrder.SelectedNode.Tag as Layer);
      UpdateLayerOrder();
    }

    private void btnDown_Click(object sender, EventArgs e)
    {
      //Move the selected layer down one spot in the drawing order
      LayerOrderCollection loColl = m_disp.Map.LayerDrawingOrder;
      loColl.MoveDown(tvwLayerOrder.SelectedNode.Tag as Layer);
      UpdateLayerOrder();
    }

    private void btnAllUp_Click(object sender, EventArgs e)
    {
      //Move selected layer to the top of draw order
      LayerOrderCollection loColl = m_disp.Map.LayerDrawingOrder;
      loColl.MoveToTop(tvwLayerOrder.SelectedNode.Tag as Layer);
      UpdateLayerOrder();
    }

    private void btnAllDown_Click(object sender, EventArgs e)
    {
      //Move selected layer to the bottom of the draw order
      LayerOrderCollection loColl = m_disp.Map.LayerDrawingOrder;
      string key = tvwLayerOrder.SelectedNode.Text;
      loColl.MoveToBottom(tvwLayerOrder.SelectedNode.Tag as Layer);
      UpdateLayerOrder();
    }

    private void btnDelete_Click(object sender, EventArgs e)
    {
      //Remove the selected item from the map and the Map Items list
      if (tvwMapItems.SelectedNode == null) return;

      //Remove the selected node from the map contents collection and the tree view control
      m_disp.Map.ChildItems.Remove(tvwMapItems.SelectedNode.Tag as MapItem);

      //Make sure the map items list is updated
      UpdateMapItems();
      btnDelete.Enabled = false;
    }

    private void btnFileGDB_Click(object sender, EventArgs e)
    {
      //Open up a new form for adding file geodatabase content to the map
      frmFileGDB form = new frmFileGDB();
      form.Show();
    }
  }
}