About the ArcGIS Network Analyst extension Engine application Sample
[C#]
frmMain.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.NetworkAnalyst;
using ESRI.ArcGIS.Geodatabase;
// This is the main form of the application.
namespace NAEngine
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class frmMain : System.Windows.Forms.Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
private System.Windows.Forms.Splitter splitter1;
// Context menu objects for NAWindow's context menu
private System.Windows.Forms.ContextMenu contextMenu1;
private System.Windows.Forms.MenuItem miLoadLocations;
private System.Windows.Forms.MenuItem miClearLocations;
private System.Windows.Forms.MenuItem miAddItem;
// ArcGIS Controls on the form
private ESRI.ArcGIS.Controls.AxMapControl axMapControl1;
private ESRI.ArcGIS.Controls.AxLicenseControl axLicenseControl1;
private ESRI.ArcGIS.Controls.AxToolbarControl axToolbarControl1;
private ESRI.ArcGIS.Controls.AxTOCControl axTOCControl1;
// Listen for context menu on NAWindow
private IEngineNAWindowEventsEx_OnContextMenuEventHandler m_onContextMenu;
private IEngineNetworkAnalystEnvironmentEvents_OnNetworkLayersChangedEventHandler m_OnNetworkLayersChanged;
private IEngineNetworkAnalystEnvironmentEvents_OnCurrentNetworkLayerChangedEventHandler m_OnCurrentNetworkLayerChanged;
// Reference to ArcGIS Network Analyst extension Environment
private IEngineNetworkAnalystEnvironment m_naEnv;
// Reference to NAWindow. Need to hold on to reference for events to work.
private IEngineNAWindow m_naWindow;
// Menu for our commands on the TOC context menu
private IToolbarMenu m_menuLayer;
// incrementor for auto generated names
private static int autogenInt = 0;
public frmMain()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose(bool disposing)
{
ESRI.ArcGIS.ADF.COMSupport.AOUninitialize.Shutdown();
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMain));
this.axMapControl1 = new ESRI.ArcGIS.Controls.AxMapControl();
this.axLicenseControl1 = new ESRI.ArcGIS.Controls.AxLicenseControl();
this.axToolbarControl1 = new ESRI.ArcGIS.Controls.AxToolbarControl();
this.splitter1 = new System.Windows.Forms.Splitter();
this.axTOCControl1 = new ESRI.ArcGIS.Controls.AxTOCControl();
this.contextMenu1 = new System.Windows.Forms.ContextMenu();
this.miLoadLocations = new System.Windows.Forms.MenuItem();
this.miClearLocations = new System.Windows.Forms.MenuItem();
this.miAddItem = new System.Windows.Forms.MenuItem();
((System.ComponentModel.ISupportInitialize)(this.axMapControl1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.axLicenseControl1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.axToolbarControl1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.axTOCControl1)).BeginInit();
this.SuspendLayout();
//
// axMapControl1
//
this.axMapControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.axMapControl1.Location = new System.Drawing.Point(227, 28);
this.axMapControl1.Name = "axMapControl1";
this.axMapControl1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axMapControl1.OcxState")));
this.axMapControl1.Size = new System.Drawing.Size(645, 472);
this.axMapControl1.TabIndex = 2;
//
// axLicenseControl1
//
this.axLicenseControl1.Enabled = true;
this.axLicenseControl1.Location = new System.Drawing.Point(664, 0);
this.axLicenseControl1.Name = "axLicenseControl1";
this.axLicenseControl1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axLicenseControl1.OcxState")));
this.axLicenseControl1.Size = new System.Drawing.Size(32, 32);
this.axLicenseControl1.TabIndex = 1;
//
// axToolbarControl1
//
this.axToolbarControl1.Dock = System.Windows.Forms.DockStyle.Top;
this.axToolbarControl1.Location = new System.Drawing.Point(0, 0);
this.axToolbarControl1.Name = "axToolbarControl1";
this.axToolbarControl1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axToolbarControl1.OcxState")));
this.axToolbarControl1.Size = new System.Drawing.Size(872, 28);
this.axToolbarControl1.TabIndex = 0;
//
// splitter1
//
this.splitter1.Location = new System.Drawing.Point(224, 28);
this.splitter1.Name = "splitter1";
this.splitter1.Size = new System.Drawing.Size(3, 472);
this.splitter1.TabIndex = 4;
this.splitter1.TabStop = false;
//
// axTOCControl1
//
this.axTOCControl1.Dock = System.Windows.Forms.DockStyle.Left;
this.axTOCControl1.Location = new System.Drawing.Point(0, 28);
this.axTOCControl1.Name = "axTOCControl1";
this.axTOCControl1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axTOCControl1.OcxState")));
this.axTOCControl1.Size = new System.Drawing.Size(224, 472);
this.axTOCControl1.TabIndex = 1;
this.axTOCControl1.OnMouseDown += new ESRI.ArcGIS.Controls.ITOCControlEvents_Ax_OnMouseDownEventHandler(this.axTOCControl1_OnMouseDown);
//
// contextMenu1
//
this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.miLoadLocations,
this.miClearLocations});
//
// miLoadLocations
//
this.miLoadLocations.Index = 0;
this.miLoadLocations.Text = "Load Locations...";
this.miLoadLocations.Click += new System.EventHandler(this.miLoadLocations_Click);
//
// miClearLocations
//
this.miClearLocations.Index = 1;
this.miClearLocations.Text = "Clear Locations";
this.miClearLocations.Click += new System.EventHandler(this.miClearLocations_Click);
//
// miAddItem
//
this.miAddItem.Index = -1;
this.miAddItem.Text = "Add Item";
this.miAddItem.Click += new System.EventHandler(this.miAddItem_Click);
//
// frmMain
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(872, 500);
this.Controls.Add(this.axLicenseControl1);
this.Controls.Add(this.axMapControl1);
this.Controls.Add(this.splitter1);
this.Controls.Add(this.axTOCControl1);
this.Controls.Add(this.axToolbarControl1);
this.Name = "frmMain";
this.Text = "Network Analyst Engine Application";
this.Load += new System.EventHandler(this.frmMain_Load);
((System.ComponentModel.ISupportInitialize)(this.axMapControl1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.axLicenseControl1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.axToolbarControl1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.axTOCControl1)).EndInit();
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
bool succeeded = ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.EngineOrDesktop);
if (succeeded)
{
ESRI.ArcGIS.RuntimeInfo activeRunTimeInfo = ESRI.ArcGIS.RuntimeManager.ActiveRuntime;
System.Diagnostics.Debug.Print(activeRunTimeInfo.Product.ToString());
Application.Run(new frmMain());
}
else
System.Windows.Forms.MessageBox.Show("Failed to bind to an active ArcGIS runtime");
}
private void frmMain_Load(object sender, System.EventArgs e)
{
// Add commands to the NALayer context menu
m_menuLayer = new ToolbarMenuClass();
int nItem = -1;
m_menuLayer.AddItem(new cmdLoadLocations(), -1, ++nItem, false, esriCommandStyles.esriCommandStyleTextOnly);
m_menuLayer.AddItem(new cmdRemoveLayer(), -1, ++nItem, false, esriCommandStyles.esriCommandStyleTextOnly);
m_menuLayer.AddItem(new cmdClearAnalysisLayer(), -1, ++nItem, true, esriCommandStyles.esriCommandStyleTextOnly);
m_menuLayer.AddItem(new cmdNALayerProperties(), -1, ++nItem, true, esriCommandStyles.esriCommandStyleTextOnly);
// Since this ToolbarMenu is a standalone popup menu use the SetHook method to
// specify the object that will be sent as a "hook" to the menu commands in their OnCreate methods.
m_menuLayer.SetHook(axMapControl1);
// Add command for ArcGIS Network Analyst extension env properties to end of "Network Analyst" dropdown menu
nItem = -1;
for (int i = 0; i < axToolbarControl1.Count; ++i)
{
IToolbarItem item = axToolbarControl1.GetItem(i);
IToolbarMenu mnu = item.Menu;
if (mnu == null) continue;
IMenuDef mnudef = mnu.GetMenuDef();
string name = mnudef.Name;
// Find the ArcGIS Network Analyst extension solver menu drop down and note the index
if (name == "ControlToolsNetworkAnalyst_SolverMenu")
{
nItem = i;
//break;
}
}
if (nItem >= 0)
{
// Using the index found above, get the solver menu drop down and add the Properties command to the end of it.
IToolbarItem item = axToolbarControl1.GetItem(nItem);
IToolbarMenu mnu = item.Menu;
if (mnu != null)
mnu.AddItem(new cmdNAProperties(), -1, mnu.Count, true, esriCommandStyles.esriCommandStyleTextOnly);
// Since this ToolbarMenu is an item on the ToolbarControl the Hook is shared and initialized by the ToolbarControl.
// Therefore, SetHook is not called here, like it is for the menu above.
}
// Initialize naEnv variables
m_naEnv = CommonFunctions.GetTheEngineNetworkAnalystEnvironment();
if (m_naEnv == null)
{
MessageBox.Show("Error: EngineNetworkAnalystEnvironment is not properly configured");
return;
}
m_naEnv.ZoomToResultAfterSolve = false;
m_naEnv.ShowAnalysisMessagesAfterSolve = (int)(esriEngineNAMessageType.esriEngineNAMessageTypeInformative |
esriEngineNAMessageType.esriEngineNAMessageTypeWarning);
// Set up the buddy control and initialize the NA extension, so we can get to NAWindow to listen to window events.
// This is necessary, as the various controls are not yet set up. They need to be in order to get the NAWindow's events.
axToolbarControl1.SetBuddyControl(axMapControl1);
IExtension ext = m_naEnv as IExtension;
object obj = axToolbarControl1.Object;
ext.Startup(ref obj);
// m_naWindow is set after Startup of the Network Analyst extension
m_naWindow = m_naEnv.NAWindow;
if (m_naWindow == null)
{
MessageBox.Show("Error: Unexpected null NAWindow");
return;
}
m_onContextMenu = new IEngineNAWindowEventsEx_OnContextMenuEventHandler(OnContextMenu);
((IEngineNAWindowEventsEx_Event)m_naWindow).OnContextMenu += m_onContextMenu;
m_OnNetworkLayersChanged = new IEngineNetworkAnalystEnvironmentEvents_OnNetworkLayersChangedEventHandler(OnNetworkLayersChanged);
((IEngineNetworkAnalystEnvironmentEvents_Event)m_naEnv).OnNetworkLayersChanged += m_OnNetworkLayersChanged;
m_OnCurrentNetworkLayerChanged = new IEngineNetworkAnalystEnvironmentEvents_OnCurrentNetworkLayerChangedEventHandler(OnCurrentNetworkLayerChanged);
((IEngineNetworkAnalystEnvironmentEvents_Event)m_naEnv).OnCurrentNetworkLayerChanged += m_OnCurrentNetworkLayerChanged;
}
// Show the TOC context menu when an NALayer is right-clicked on
private void axTOCControl1_OnMouseDown(object sender, ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent e)
{
if (e.button != 2) return;
esriTOCControlItem item = esriTOCControlItem.esriTOCControlItemNone;
IBasicMap map = null;
ILayer layer = null;
object other = null;
object index = null;
//Determine what kind of item has been clicked on
axTOCControl1.HitTest(e.x, e.y, ref item, ref map, ref layer, ref other, ref index);
// Only implemented a context menu for NALayers. Exit if the layer is anything else.
if ((layer as INALayer) == null)
return;
axTOCControl1.SelectItem(layer);
// Set the layer into the CustomProperty.
// This is used by the other commands to know what layer was right-clicked on
// in the table of contents.
axMapControl1.CustomProperty = layer;
//Popup the correct context menu and update the TOC when it's done.
if (item == esriTOCControlItem.esriTOCControlItemLayer)
{
m_menuLayer.PopupMenu(e.x, e.y, axTOCControl1.hWnd);
ITOCControl toc = axTOCControl1.Object as ITOCControl;
toc.Update();
}
}
public void OnNetworkLayersChanged()
{
// The OnNetworkLayersChanged event is fired when a new INetworkLayer object is
// added, removed, or renamed within a map.
// If the INetworkLayer is renamed interactively through the user interface
// OnNetworkLayersChanged is fired. If the INetworkLayer is renamed programmatically
// using the ILayer::Name property OnNetworkLayersChanged is not fired.
}
public void OnCurrentNetworkLayerChanged()
{
// The OnCurrentNetworkLayerChanged event is fired when the user interactively
// changes the NetworkDataset or the IEngineNetworkAnalystEnvironment::CurrentNetworkLayer
// is set programatically.
}
//The OnContextMenu event is fired when a user right clicks within the
// IEngineNetworkAnalystEnvironment::NAWindow and can be used to supply a context menu.
public bool OnContextMenu(int x, int y)
{
System.Drawing.Point pt = this.PointToClient(System.Windows.Forms.Cursor.Position);
// Get the active category
var activeCategory = m_naWindow.ActiveCategory as IEngineNAWindowCategory2;
if (activeCategory == null)
return false;
MenuItem separator = new MenuItem("-");
miLoadLocations.Enabled = false;
miClearLocations.Enabled = false;
// in order for the AddItem choice to appear in the context menu, the class
// should be an input class, and it should not be editable
INAClassDefinition pNAClassDefinition = activeCategory.NAClass.ClassDefinition;
if (pNAClassDefinition.IsInput)
{
miLoadLocations.Enabled = true;
miClearLocations.Enabled = true;
// canEditShape should be false for AddItem to Apply (default is false)
// if it's a StandaloneTable canEditShape is implicitly false (there's no shape to edit)
bool canEditShape = false;
IFields pFields = pNAClassDefinition.Fields;
int nField = -1;
nField = pFields.FindField("Shape");
if (nField >= 0)
{
int naFieldType = 0;
naFieldType = pNAClassDefinition.get_FieldType("Shape");
// determining whether or not the shape field can be edited consists of running a bitwise comparison
// on the FieldType of the shape field. See the online help for a list of the possible field types.
// For our case, we want to verify that the shape field is an input field. If it is an input field,
// then we do NOT want to display the Add Item menu option.
canEditShape = ((naFieldType & (int)esriNAFieldType.esriNAFieldTypeInput) == (int)esriNAFieldType.esriNAFieldTypeInput) ? true : false;
}
if (!canEditShape)
{
contextMenu1.MenuItems.Add(separator);
contextMenu1.MenuItems.Add(miAddItem);
}
}
contextMenu1.Show(this, pt);
// even if the miAddItem menu item has not been added, Remove() won't crash.
contextMenu1.MenuItems.Remove(separator);
contextMenu1.MenuItems.Remove(miAddItem);
return true;
}
private void miLoadLocations_Click(object sender, System.EventArgs e)
{
var mapControl = axMapControl1.Object as IMapControl3;
// Show the Property Page form for ArcGIS Network Analyst extension
var loadLocations = new frmLoadLocations();
if (loadLocations.ShowModal(mapControl, m_naEnv))
{
// notify that the context has changed because we have added locations to a NAClass within it
var contextEdit = m_naEnv.NAWindow.ActiveAnalysis.Context as INAContextEdit;
contextEdit.ContextChanged();
// If loaded locations, refresh the NAWindow and the Screen
INALayer naLayer = m_naWindow.ActiveAnalysis;
mapControl.Refresh(esriViewDrawPhase.esriViewGeography, naLayer, mapControl.Extent);
m_naWindow.UpdateContent(m_naWindow.ActiveCategory);
}
}
private void miClearLocations_Click(object sender, System.EventArgs e)
{
var mapControl = axMapControl1.Object as IMapControl3;
var naHelper = m_naEnv as IEngineNetworkAnalystHelper;
IEngineNAWindow naWindow = m_naWindow;
INALayer naLayer = naWindow.ActiveAnalysis;
// we do not have to run ContextChanged() as with adding an item and loading locations,
// because that is done by the DeleteAllNetworkLocations method.
naHelper.DeleteAllNetworkLocations();
mapControl.Refresh(esriViewDrawPhase.esriViewGeography, naLayer, mapControl.Extent);
}
private void miAddItem_Click(object sender, System.EventArgs e)
{
// Developers Note:
// Once an item has been added, the user can double click on the item to edit the properties
// of the item. For the purposes of this sample, only the default values from the InitDefaultValues method
// and an auto generated Name value are populated initially for the new item.
var mapControl = axMapControl1.Object as IMapControl3;
var activeCategory = m_naWindow.ActiveCategory as IEngineNAWindowCategory2;
IDataLayer pDataLayer = activeCategory.DataLayer;
// In order to add an item, we need to create a new row in the class and populate it
// with the initial default values for that class.
var table = pDataLayer as ITable;
IRow row = table.CreateRow();
var rowSubtypes = row as IRowSubtypes;
rowSubtypes.InitDefaultValues();
// we need to auto generate a display name for the newly added item.
// In some cases (depending on how the schema is set up) InitDefaultValues may result in a nonempty name string
// in these cases do not override the preexisting non-empty name string with our auto generated one.
var ipFeatureLayer = activeCategory.Layer as IFeatureLayer;
var ipStandaloneTable = pDataLayer as IStandaloneTable;
string name = "";
if (ipFeatureLayer != null)
name = ipFeatureLayer.DisplayField;
else if (ipStandaloneTable != null)
name = ipStandaloneTable.DisplayField;
//If the display field is an empty string or does not represent an actual field on the NAClass just skip the auto generation.
// (Some custom solvers may not have set the DisplayField for example).
// Note: The name we are auto generating does not have any spaces in it. This is to ensure that any classes
// that are space sensitive will be able to handle the name (ex Specialties).
string currentName = "";
int fieldIndex = row.Fields.FindField(name);
if (fieldIndex >= 0)
{
currentName = row.get_Value(fieldIndex) as string;
if (currentName.Length <= 0)
row.set_Value(fieldIndex, "Item" + ++autogenInt);
}
// A special case is OrderPairs NAClass because that effectively has a combined 2 field display field.
// You will have to hard code to look for that NAClassName and create a default name for
// both first order and second order field names so the name will display correctly
// (look for the NAClass Name and NOT the layer name).
INAClassDefinition naClassDef = activeCategory.NAClass.ClassDefinition;
if (naClassDef.Name == "OrderPairs")
{
fieldIndex = row.Fields.FindField("SecondOrderName");
if (fieldIndex >= 0)
{
string secondName = row.get_Value(fieldIndex) as string;
if (secondName.Length <= 0)
row.set_Value(fieldIndex, "Item" + ++autogenInt);
}
}
row.Store();
// notify that the context has changed because we have added an item to a NAClass within it
var contextEdit = m_naEnv.NAWindow.ActiveAnalysis.Context as INAContextEdit;
contextEdit.ContextChanged();
// refresh the NAWindow and the Screen
INALayer naLayer = m_naWindow.ActiveAnalysis;
mapControl.Refresh(esriViewDrawPhase.esriViewGeography, naLayer, mapControl.Extent);
m_naWindow.UpdateContent(m_naWindow.ActiveCategory);
}
}
}
[Visual Basic .NET]
frmMain.vb
Imports Microsoft.VisualBasic
Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.Controls
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.SystemUI
Imports ESRI.ArcGIS.NetworkAnalyst
Imports ESRI.ArcGIS.Geodatabase
' This is the main form of the application.
Namespace NAEngine
''' <summary>
''' Summary description for Form1.
''' </summary>
Public Class frmMain : Inherits System.Windows.Forms.Form
''' <summary>
''' Required designer variable.
''' </summary>
Private components As System.ComponentModel.Container = Nothing
Private splitter1 As System.Windows.Forms.Splitter
' Context menu objects for NAWindow's context menu
Private contextMenu1 As System.Windows.Forms.ContextMenu
Private WithEvents miLoadLocations As System.Windows.Forms.MenuItem
Private WithEvents miClearLocations As System.Windows.Forms.MenuItem
Private WithEvents miAddItem As System.Windows.Forms.MenuItem
' ArcGIS Controls on the form
Private axMapControl1 As ESRI.ArcGIS.Controls.AxMapControl
Private axLicenseControl1 As ESRI.ArcGIS.Controls.AxLicenseControl
Private axToolbarControl1 As ESRI.ArcGIS.Controls.AxToolbarControl
Private WithEvents axTOCControl1 As ESRI.ArcGIS.Controls.AxTOCControl
' Listen for context menu on NAWindow
Private m_onContextMenu As IEngineNAWindowEventsEx_OnContextMenuEventHandler
Private m_OnNetworkLayersChanged As IEngineNetworkAnalystEnvironmentEvents_OnNetworkLayersChangedEventHandler
Private m_OnCurrentNetworkLayerChanged As IEngineNetworkAnalystEnvironmentEvents_OnCurrentNetworkLayerChangedEventHandler
' Reference to ArcGIS Network Analyst extension Environment
Private m_naEnv As IEngineNetworkAnalystEnvironment
' Reference to NAWindow. Need to hold on to reference for events to work.
Private m_naWindow As IEngineNAWindow
' Menu for our commands on the TOC context menu
Private m_menuLayer As IToolbarMenu
' incrementor for auto generated names
Private Shared autogenInt As Integer = 0
Public Sub New()
'
' Required for Windows Form Designer support
'
InitializeComponent()
End Sub
''' <summary>
''' Clean up any resources being used.
''' </summary>
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
ESRI.ArcGIS.ADF.COMSupport.AOUninitialize.Shutdown()
If disposing Then
If Not components Is Nothing Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
#Region "Windows Form Designer generated code"
''' <summary>
''' Required method for Designer support - do not modify
''' the contents of this method with the code editor.
''' </summary>
Private Sub InitializeComponent()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(frmMain))
Me.axMapControl1 = New ESRI.ArcGIS.Controls.AxMapControl()
Me.axLicenseControl1 = New ESRI.ArcGIS.Controls.AxLicenseControl()
Me.axToolbarControl1 = New ESRI.ArcGIS.Controls.AxToolbarControl()
Me.splitter1 = New System.Windows.Forms.Splitter()
Me.axTOCControl1 = New ESRI.ArcGIS.Controls.AxTOCControl()
Me.contextMenu1 = New System.Windows.Forms.ContextMenu()
Me.miLoadLocations = New System.Windows.Forms.MenuItem()
Me.miClearLocations = New System.Windows.Forms.MenuItem()
Me.miAddItem = New System.Windows.Forms.MenuItem()
CType(Me.axMapControl1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.axLicenseControl1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.axToolbarControl1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.axTOCControl1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
'
' axMapControl1
'
Me.axMapControl1.Dock = System.Windows.Forms.DockStyle.Fill
Me.axMapControl1.Location = New System.Drawing.Point(227, 28)
Me.axMapControl1.Name = "axMapControl1"
Me.axMapControl1.OcxState = (CType(resources.GetObject("axMapControl1.OcxState"), System.Windows.Forms.AxHost.State))
Me.axMapControl1.Size = New System.Drawing.Size(645, 472)
Me.axMapControl1.TabIndex = 2
'
' axLicenseControl1
'
Me.axLicenseControl1.Enabled = True
Me.axLicenseControl1.Location = New System.Drawing.Point(664, 0)
Me.axLicenseControl1.Name = "axLicenseControl1"
Me.axLicenseControl1.OcxState = (CType(resources.GetObject("axLicenseControl1.OcxState"), System.Windows.Forms.AxHost.State))
Me.axLicenseControl1.Size = New System.Drawing.Size(32, 32)
Me.axLicenseControl1.TabIndex = 1
'
' axToolbarControl1
'
Me.axToolbarControl1.Dock = System.Windows.Forms.DockStyle.Top
Me.axToolbarControl1.Location = New System.Drawing.Point(0, 0)
Me.axToolbarControl1.Name = "axToolbarControl1"
Me.axToolbarControl1.OcxState = (CType(resources.GetObject("axToolbarControl1.OcxState"), System.Windows.Forms.AxHost.State))
Me.axToolbarControl1.Size = New System.Drawing.Size(872, 28)
Me.axToolbarControl1.TabIndex = 0
'
' splitter1
'
Me.splitter1.Location = New System.Drawing.Point(224, 28)
Me.splitter1.Name = "splitter1"
Me.splitter1.Size = New System.Drawing.Size(3, 472)
Me.splitter1.TabIndex = 4
Me.splitter1.TabStop = False
'
' axTOCControl1
'
Me.axTOCControl1.Dock = System.Windows.Forms.DockStyle.Left
Me.axTOCControl1.Location = New System.Drawing.Point(0, 28)
Me.axTOCControl1.Name = "axTOCControl1"
Me.axTOCControl1.OcxState = (CType(resources.GetObject("axTOCControl1.OcxState"), System.Windows.Forms.AxHost.State))
Me.axTOCControl1.Size = New System.Drawing.Size(224, 472)
Me.axTOCControl1.TabIndex = 1
' Me.axTOCControl1.OnMouseDown += New ESRI.ArcGIS.Controls.ITOCControlEvents_Ax_OnMouseDownEventHandler(Me.axTOCControl1_OnMouseDown);
'
' contextMenu1
'
Me.contextMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.miLoadLocations, Me.miClearLocations})
'
' miLoadLocations
'
Me.miLoadLocations.Index = 0
Me.miLoadLocations.Text = "Load Locations..."
' Me.miLoadLocations.Click += New System.EventHandler(Me.miLoadLocations_Click);
'
' miClearLocations
'
Me.miClearLocations.Index = 1
Me.miClearLocations.Text = "Clear Locations"
' Me.miClearLocations.Click += New System.EventHandler(Me.miClearLocations_Click);
'
' miAddItem
'
Me.miAddItem.Index = -1
Me.miAddItem.Text = "Add Item"
' Me.miAddItem.Click += New System.EventHandler(Me.miAddItem_Click);
'
' frmMain
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(872, 500)
Me.Controls.Add(Me.axLicenseControl1)
Me.Controls.Add(Me.axMapControl1)
Me.Controls.Add(Me.splitter1)
Me.Controls.Add(Me.axTOCControl1)
Me.Controls.Add(Me.axToolbarControl1)
Me.Name = "frmMain"
Me.Text = "Network Analyst Engine Application"
' Me.Load += New System.EventHandler(Me.frmMain_Load);
CType(Me.axMapControl1, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.axLicenseControl1, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.axToolbarControl1, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.axTOCControl1, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
#End Region
''' <summary>
''' The main entry point for the application.
''' </summary>
<STAThread()> _
Shared Sub Main()
Dim succeeded As Boolean = ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.EngineOrDesktop)
If succeeded Then
Dim activeRunTimeInfo As ESRI.ArcGIS.RuntimeInfo = ESRI.ArcGIS.RuntimeManager.ActiveRuntime
System.Diagnostics.Debug.Print(activeRunTimeInfo.Product.ToString())
Application.Run(New frmMain())
Else
System.Windows.Forms.MessageBox.Show("Failed to bind to an active ArcGIS runtime")
End If
End Sub
Private Sub frmMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
' Add commands to the NALayer context menu
m_menuLayer = New ToolbarMenuClass()
Dim nItem As Integer = -1
m_menuLayer.AddItem(New cmdLoadLocations(), -1, ++nItem, False, esriCommandStyles.esriCommandStyleTextOnly)
m_menuLayer.AddItem(New cmdRemoveLayer(), -1, ++nItem, False, esriCommandStyles.esriCommandStyleTextOnly)
m_menuLayer.AddItem(New cmdClearAnalysisLayer(), -1, ++nItem, True, esriCommandStyles.esriCommandStyleTextOnly)
m_menuLayer.AddItem(New cmdNALayerProperties(), -1, ++nItem, True, esriCommandStyles.esriCommandStyleTextOnly)
' Since this ToolbarMenu is a standalone popup menu use the SetHook method to
' specify the object that will be sent as a "hook" to the menu commands in their OnCreate methods.
m_menuLayer.SetHook(axMapControl1)
' Add command for ArcGIS Network Analyst extension env properties to end of "Network Analyst" dropdown menu
nItem = -1
Dim i As Integer = 0
Do While i < axToolbarControl1.Count
Dim item As IToolbarItem = axToolbarControl1.GetItem(i)
Dim mnu As IToolbarMenu = item.Menu
If mnu Is Nothing Then
i += 1
Continue Do
End If
Dim mnudef As IMenuDef = mnu.GetMenuDef()
Dim name As String = mnudef.Name
' Find the ArcGIS Network Analyst extension solver menu drop down and note the index
If name = "ControlToolsNetworkAnalyst_SolverMenu" Then
nItem = i
Exit Do
End If
i += 1
Loop
If nItem >= 0 Then
' Using the index found above, get the solver menu drop down and add the Properties command to the end of it.
Dim item As IToolbarItem = axToolbarControl1.GetItem(nItem)
Dim mnu As IToolbarMenu = item.Menu
If Not mnu Is Nothing Then
mnu.AddItem(New cmdNAProperties(), -1, mnu.Count, True, esriCommandStyles.esriCommandStyleTextOnly)
End If
' Since this ToolbarMenu is an item on the ToolbarControl the Hook is shared and initialized by the ToolbarControl.
' Therefore, SetHook is not called here, like it is for the menu above.
End If
' Initialize naEnv variables
m_naEnv = CommonFunctions.GetTheEngineNetworkAnalystEnvironment()
If m_naEnv Is Nothing Then
MessageBox.Show("Error: EngineNetworkAnalystEnvironment is not properly configured")
Return
End If
m_naEnv.ZoomToResultAfterSolve = False
m_naEnv.ShowAnalysisMessagesAfterSolve = CInt(esriEngineNAMessageType.esriEngineNAMessageTypeInformative Or esriEngineNAMessageType.esriEngineNAMessageTypeWarning)
' Set up the buddy control and initialize the NA extension, so we can get to NAWindow to listen to window events.
' This is necessary, as the various controls are not yet set up. They need to be in order to get the NAWindow's events.
axToolbarControl1.SetBuddyControl(axMapControl1)
Dim ext As IExtension = TryCast(m_naEnv, IExtension)
Dim obj As Object = axToolbarControl1.Object
ext.Startup(obj)
' m_naWindow is set after Startup of the Network Analyst extension
m_naWindow = m_naEnv.NAWindow
If m_naWindow Is Nothing Then
MessageBox.Show("Error: Unexpected null NAWindow")
Return
End If
m_onContextMenu = New IEngineNAWindowEventsEx_OnContextMenuEventHandler(AddressOf OnContextMenu)
AddHandler CType(m_naWindow, IEngineNAWindowEventsEx_Event).OnContextMenu, m_onContextMenu
m_OnNetworkLayersChanged = New IEngineNetworkAnalystEnvironmentEvents_OnNetworkLayersChangedEventHandler(AddressOf OnNetworkLayersChanged)
AddHandler CType(m_naEnv, IEngineNetworkAnalystEnvironmentEvents_Event).OnNetworkLayersChanged, m_OnNetworkLayersChanged
m_OnCurrentNetworkLayerChanged = New IEngineNetworkAnalystEnvironmentEvents_OnCurrentNetworkLayerChangedEventHandler(AddressOf OnCurrentNetworkLayerChanged)
AddHandler CType(m_naEnv, IEngineNetworkAnalystEnvironmentEvents_Event).OnCurrentNetworkLayerChanged, m_OnCurrentNetworkLayerChanged
End Sub
' Show the TOC context menu when an NALayer is right-clicked on
Private Sub axTOCControl1_OnMouseDown(ByVal sender As Object, ByVal e As ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent) Handles axTOCControl1.OnMouseDown
If e.button <> 2 Then
Return
End If
Dim item As esriTOCControlItem = esriTOCControlItem.esriTOCControlItemNone
Dim map As IBasicMap = Nothing
Dim layer As ILayer = Nothing
Dim other As Object = Nothing
Dim index As Object = Nothing
'Determine what kind of item has been clicked on
axTOCControl1.HitTest(e.x, e.y, item, map, layer, other, index)
' Only implemented a context menu for NALayers. Exit if the layer is anything else.
If (TryCast(layer, INALayer)) Is Nothing Then
Return
End If
axTOCControl1.SelectItem(layer)
' Set the layer into the CustomProperty.
' This is used by the other commands to know what layer was right-clicked on
' in the table of contents.
axMapControl1.CustomProperty = layer
'Popup the correct context menu and update the TOC when it's done.
If item = esriTOCControlItem.esriTOCControlItemLayer Then
m_menuLayer.PopupMenu(e.x, e.y, axTOCControl1.hWnd)
Dim toc As ITOCControl = TryCast(axTOCControl1.Object, ITOCControl)
toc.Update()
End If
End Sub
Public Sub OnNetworkLayersChanged()
' The OnNetworkLayersChanged event is fired when a new INetworkLayer object is
' added, removed, or renamed within a map.
' If the INetworkLayer is renamed interactively through the user interface
' OnNetworkLayersChanged is fired. If the INetworkLayer is renamed programmatically
' using the ILayer::Name property OnNetworkLayersChanged is not fired.
End Sub
Public Sub OnCurrentNetworkLayerChanged()
' The OnCurrentNetworkLayerChanged event is fired when the user interactively
' changes the NetworkDataset or the IEngineNetworkAnalystEnvironment::CurrentNetworkLayer
' is set programatically.
End Sub
Public Function OnContextMenu(ByVal x As Integer, ByVal y As Integer) As Boolean
Dim pt As System.Drawing.Point = Me.PointToClient(System.Windows.Forms.Cursor.Position)
' Get the active category
Dim activeCategory As IEngineNAWindowCategory2 = TryCast(m_naWindow.ActiveCategory, IEngineNAWindowCategory2)
If activeCategory Is Nothing Then
Return False
End If
Dim separator As MenuItem = New MenuItem("-")
miLoadLocations.Enabled = False
miClearLocations.Enabled = False
' in order for the AddItem choice to appear in the context menu, the class
' should be an input class, and it should not be editable
Dim pNAClassDefinition As INAClassDefinition = activeCategory.NAClass.ClassDefinition
If pNAClassDefinition.IsInput Then
miLoadLocations.Enabled = True
miClearLocations.Enabled = True
' canEditShape should be false for AddItem to Apply (default is false)
' if it's a StandaloneTable canEditShape is implicitly false (there's no shape to edit)
Dim canEditShape As Boolean = False
Dim pFields As IFields = pNAClassDefinition.Fields
Dim nField As Integer = -1
nField = pFields.FindField("Shape")
If nField >= 0 Then
Dim naFieldType As Integer = 0
naFieldType = pNAClassDefinition.FieldType("Shape")
' determining whether or not the shape field can be edited consists of running a bitwise comparison
' on the FieldType of the shape field. See the online help for a list of the possible field types.
' For our case, we want to verify that the shape field is an input field. If it is an input field,
' then we do NOT want to display the Add Item menu option.
If ((naFieldType And CInt(esriNAFieldType.esriNAFieldTypeInput)) = CInt(esriNAFieldType.esriNAFieldTypeInput)) Then
canEditShape = True
Else
canEditShape = False
End If
End If
If (Not canEditShape) Then
contextMenu1.MenuItems.Add(separator)
contextMenu1.MenuItems.Add(miAddItem)
End If
End If
contextMenu1.Show(Me, pt)
' even if the miAddItem menu item has not been added, Remove() won't crash.
contextMenu1.MenuItems.Remove(separator)
contextMenu1.MenuItems.Remove(miAddItem)
Return True
End Function
Private Sub miLoadLocations_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles miLoadLocations.Click
Dim mapControl As IMapControl3 = TryCast(axMapControl1.Object, IMapControl3)
' Show the Property Page form for ArcGIS Network Analyst extension
Dim loadLocations As frmLoadLocations = New frmLoadLocations()
If loadLocations.ShowModal(mapControl, m_naEnv) Then
' notify that the context has changed because we have added locations to a NAClass within it
Dim contextEdit As INAContextEdit = TryCast(m_naEnv.NAWindow.ActiveAnalysis.Context, INAContextEdit)
contextEdit.ContextChanged()
' If loaded locations, refresh the NAWindow and the Screen
Dim naLayer As INALayer = m_naWindow.ActiveAnalysis
mapControl.Refresh(esriViewDrawPhase.esriViewGeography, naLayer, mapControl.Extent)
m_naWindow.UpdateContent(m_naWindow.ActiveCategory)
End If
End Sub
Private Sub miClearLocations_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles miClearLocations.Click
Dim mapControl As IMapControl3 = TryCast(axMapControl1.Object, IMapControl3)
Dim naHelper As IEngineNetworkAnalystHelper = TryCast(m_naEnv, IEngineNetworkAnalystHelper)
Dim naWindow As IEngineNAWindow = m_naWindow
Dim naLayer As INALayer = naWindow.ActiveAnalysis
' we do not have to run ContextChanged() as with adding an item and loading locations,
' because that is done by the DeleteAllNetworkLocations method.
naHelper.DeleteAllNetworkLocations()
mapControl.Refresh(esriViewDrawPhase.esriViewGeography, naLayer, mapControl.Extent)
End Sub
Private Sub miAddItem_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles miAddItem.Click
' Developers Note:
' Once an item has been added, the user can double click on the item to edit the properties
' of the item. For the purposes of this sample, only the default values from the InitDefaultValues method
' and an auto generated Name value are populated initially for the new item.
Dim mapControl As IMapControl3 = TryCast(axMapControl1.Object, IMapControl3)
Dim activeCategory As IEngineNAWindowCategory2 = TryCast(m_naWindow.ActiveCategory, IEngineNAWindowCategory2)
Dim pDataLayer As IDataLayer = activeCategory.DataLayer
' In order to add an item, we need to create a new row in the class and populate it
' with the initial default values for that class.
Dim table As ITable = TryCast(pDataLayer, ITable)
Dim row As IRow = table.CreateRow()
Dim rowSubtypes As IRowSubtypes = TryCast(row, IRowSubtypes)
rowSubtypes.InitDefaultValues()
' we need to auto generate a display name for the newly added item.
' In some cases (depending on how the schema is set up) InitDefaultValues may result in a nonempty name string
' in these cases do not override the preexisting non-empty name string with our auto generated one.
Dim ipFeatureLayer As IFeatureLayer = TryCast(activeCategory.Layer, IFeatureLayer)
Dim ipStandaloneTable As IStandaloneTable = TryCast(pDataLayer, IStandaloneTable)
Dim name As String = ""
If Not ipFeatureLayer Is Nothing Then
name = ipFeatureLayer.DisplayField
ElseIf Not ipStandaloneTable Is Nothing Then
name = ipStandaloneTable.DisplayField
End If
' If the display field is an empty string or does not represent an actual field on the NAClass just skip the auto generation.
' (Some custom solvers may not have set the DisplayField for example).
' Note: The name we are auto generating does not have any spaces in it. This is to ensure that that any classes
' that are space sensitive will be able to handle the name (ex Specialties).
Dim currentName As String = ""
Dim fieldIndex As Integer = row.Fields.FindField(name)
If (fieldIndex >= 0) Then
currentName = CType(row.Value(fieldIndex), String)
If (currentName.Length <= 0) Then
autogenInt += 1
row.Value(fieldIndex) = "Item" & autogenInt
End If
End If
' A special case is OrderPairs NAClass because that effectively has a combined 2 field display field.
' You will have to hard code to look for that NAClassName and create a default name for
' both first order and second order field names so the name will display correctly
' (look for the NAClass Name and NOT the layer name).
Dim naClassDef As INAClassDefinition = activeCategory.NAClass.ClassDefinition
If (naClassDef.Name = "OrderPairs") Then
fieldIndex = row.Fields.FindField("SecondOrderName")
If (fieldIndex >= 0) Then
Dim secondName As String = CType(row.Value(fieldIndex), String)
If (secondName.Length <= 0) Then
autogenInt += 1
row.Value(fieldIndex) = "Item" & autogenInt
End If
End If
End If
row.Store()
' notify that the context has changed because we have added an item to a NAClass within it
Dim contextEdit As INAContextEdit = CType(m_naEnv.NAWindow.ActiveAnalysis.Context, INAContextEdit)
contextEdit.ContextChanged()
' refresh the NAWindow and the Screen
Dim naLayer As INALayer = m_naWindow.ActiveAnalysis
mapControl.Refresh(esriViewDrawPhase.esriViewGeography, naLayer, mapControl.Extent)
m_naWindow.UpdateContent(m_naWindow.ActiveCategory)
End Sub
End Class
End Namespace