ArcObjects Library Reference  

frmMain

About the Network Analyst 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;

		// Reference to Network Analyst 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()
		{
			if (!ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Engine))
			{
				if (!ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Desktop))
				{
					if (ESRI.ArcGIS.RuntimeManager.ActiveRuntime.Version == "") // "" is less than 10
					{
						System.Windows.Forms.MessageBox.Show("Loading ArcGIS Version Failed");
						return;
					}
				}
			}

			Application.Run(new frmMain());
		}

		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);
			m_menuLayer.SetHook(axMapControl1);

			// Add command for Network Analyst 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;
				if (name == "ControlToolsNetworkAnalyst_SolverMenu")
				{
					nItem = i;
					break;
				}
			}

			if (nItem >= 0)
			{
				IToolbarItem item = axToolbarControl1.GetItem(nItem);
				IToolbarMenu mnu = item.Menu;
				if (mnu != null)
					mnu.AddItem(new cmdNAProperties(), -1, mnu.Count, true, esriCommandStyles.esriCommandStyleTextOnly);
			}

			// Initialize naEnv variables
			m_naEnv = new EngineNetworkAnalystEnvironmentClass();
			m_naEnv.ZoomToResultAfterSolve = false;
			m_naEnv.ShowAnalysisMessagesAfterSolve = (int)(esriEngineNAMessageType.esriEngineNAMessageTypeInformative | esriEngineNAMessageType.esriEngineNAMessageTypeWarning);

			// Explicitly setup buddy control and initialize NA extension 
			// so we can get to NAWindow to listen to window events
			// This is necessary the various controls are not yet setup and 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 = m_naEnv.NAWindow;
			m_onContextMenu = new IEngineNAWindowEventsEx_OnContextMenuEventHandler(OnContextMenu);
			((IEngineNAWindowEventsEx_Event)m_naWindow).OnContextMenu += m_onContextMenu;
		}

		//  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 bool OnContextMenu(int x, int y)
		{
			System.Drawing.Point pt = this.PointToClient(System.Windows.Forms.Cursor.Position);

			//Get the active category
			IEngineNAWindowCategory2 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)
		{
			IMapControl3 mapControl = (IMapControl3)axMapControl1.Object;

			// Show the Property Page form for Network Analyst
			frmLoadLocations 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
				INAContextEdit 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)
		{
			IMapControl3 mapControl = (IMapControl3)axMapControl1.Object;

			IEngineNetworkAnalystHelper 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.

			IMapControl3 mapControl = (IMapControl3)axMapControl1.Object;

			IEngineNAWindowCategory2 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.
			ITable table = pDataLayer as ITable;
			IRow row = table.CreateRow();
			IRowSubtypes 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.
			IFeatureLayer ipFeatureLayer = activeCategory.Layer as IFeatureLayer;
			IStandaloneTable 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
			INAContextEdit 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

		' Reference to Network Analyst 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

        ' integer to use for auto generated names
        Private autogenInt As Integer

        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)
			'Release COM objects
			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
			'
			'contextMenu1
			'
			Me.contextMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.miLoadLocations, Me.miClearLocations})
			'
			'miLoadLocations
			'
			Me.miLoadLocations.Index = 0
			Me.miLoadLocations.Text = "Load Locations..."
			'
			'miClearLocations
			'
			Me.miClearLocations.Index = 1
			Me.miClearLocations.Text = "Clear Locations"
			'
			'miAddItem
			'
			Me.miAddItem.Index = -1
			Me.miAddItem.Text = "Add Item"
			'
			'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"
			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()

			If (ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Engine) Or _
			 ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Desktop)) Then
				Application.Run(New frmMain())
			Else
				If (ESRI.ArcGIS.RuntimeManager.ActiveRuntime.Version = "") Then	' "" is less than 10
					System.Windows.Forms.MessageBox.Show("Loading ArcGIS Version Failed")
				End If
			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 LoadLocations(), -1, ++nItem, False, esriCommandStyles.esriCommandStyleTextOnly)
			m_menuLayer.AddItem(New RemoveLayer(), -1, ++nItem, False, esriCommandStyles.esriCommandStyleTextOnly)
			m_menuLayer.AddItem(New ClearAnalysisLayer(), -1, ++nItem, True, esriCommandStyles.esriCommandStyleTextOnly)
			m_menuLayer.AddItem(New NALayerProperties(), -1, ++nItem, True, esriCommandStyles.esriCommandStyleTextOnly)
			m_menuLayer.SetHook(axMapControl1)

			For i As Integer = 0 To axToolbarControl1.Count - 1
				Dim item As IToolbarItem = axToolbarControl1.GetItem(i)
				Dim mnu As IToolbarMenu = item.Menu

				If mnu Is Nothing Then
					Continue For
				End If

				Dim mnudef As IMenuDef = mnu.GetMenuDef()
				Dim name As String = mnudef.Name
				If name = "ControlToolsNetworkAnalyst_SolverMenu" Then
					nItem = i
					Exit For
				End If
			Next

			If nItem >= 0 Then
				Dim item As IToolbarItem = axToolbarControl1.GetItem(nItem)
				Dim mnu As IToolbarMenu = item.Menu
				If mnu IsNot Nothing Then
					mnu.AddItem(New NAProperties(), -1, mnu.Count, True, esriCommandStyles.esriCommandStyleTextOnly)
				End If
			End If

			' Initialize naEnv variables
            m_naEnv = New EngineNetworkAnalystEnvironmentClass()
            m_naEnv.ZoomToResultAfterSolve = False
            m_naEnv.ShowAnalysisMessagesAfterSolve = CInt(esriEngineNAMessageType.esriEngineNAMessageTypeInformative Or esriEngineNAMessageType.esriEngineNAMessageTypeWarning)

            ' Explicitly setup buddy control and initialize NA extension 
            ' so we can get to NAWindow to listen to window events
            ' This is necessary the various controls are not yet setup and 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 = m_naEnv.NAWindow
            m_onContextMenu = New IEngineNAWindowEventsEx_OnContextMenuEventHandler(AddressOf OnContextMenu)
            AddHandler CType(m_naWindow, IEngineNAWindowEventsEx_Event).OnContextMenu, m_onContextMenu
        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 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.
                    Dim bitwiseAnd As Integer = (naFieldtype And esriNAFieldType.esriNAFieldTypeInput)
                    If (bitwiseAnd = esriNAFieldType.esriNAFieldTypeInput) Then
                        canEditShape = True
                    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 = CType(axMapControl1.Object, IMapControl3)

			' Show the Property Page form for Network Analyst
            Dim dlgLoadLocations As frmLoadLocations = New frmLoadLocations()
            If dlgLoadLocations.ShowModal(mapControl, m_naEnv) Then
                ' If loaded locations, refresh the NAWindow and the Screen
                Dim naLayer As INALayer = m_naWindow.ActiveAnalysis

                ' 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()

                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 = CType(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 = CType(axMapControl1.Object, IMapControl3)

            Dim activeCategory As IEngineNAWindowCategory2 = CType(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 = CType(pDataLayer, ITable)
            Dim row As IRow = table.CreateRow()
            Dim rowSubtypes As IRowSubtypes = CType(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