ArcObjects Library Reference  

SubsetHelperUI

About the Subset network evaluators Sample

[C#]

SubsetHelperUI.cs

using System;
using System.Drawing;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using ESRI.ArcGIS.ADF.BaseClasses;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.NetworkAnalyst;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.NetworkAnalystUI;
using SubsetNetworkEvaluators;

namespace SubsetNetworkEvaluatorsUI
{
	/// <summary>
	/// The SubsetHelperUI is a utility class to aid in determining the relevant set of parameters
	/// to auto-update when set to listen to the events and other shared utilities.
	/// </summary>	
	class SubsetHelperUI
	{
		public static void PushParameterValuesToNetwork(INetworkAnalystExtension nax)
		{
			try
			{
				if (nax == null)
					return;

				bool naxEnabled = false;
				IExtensionConfig naxConfig = nax as IExtensionConfig;
				naxEnabled = naxConfig.State == esriExtensionState.esriESEnabled;

				if (!naxEnabled)
					return;

				INAWindow naWindow = nax.NAWindow;
				INALayer naLayer = null;
				INAContext naContext = null;
				INetworkDataset nds = null;

				naLayer = naWindow.ActiveAnalysis;
				if (naLayer != null)
					naContext = naLayer.Context;

				if (naContext != null)
					nds = naContext.NetworkDataset;

				if (nds == null)
					return;

				IDatasetComponent dsComponent = nds as IDatasetComponent;
				IDENetworkDataset deNet = dsComponent.DataElement as IDENetworkDataset;

				INASolver naSolver = naContext.Solver;
				INASolverSettings2 naSolverSettings2 = naSolver as INASolverSettings2;

				if (naSolverSettings2 == null)
					return;

				INetworkAttribute2 netAttribute;
				string attributeName;

				IArray netParameters;
				INetworkAttributeParameter netParameter;
				string paramName;
				int cParameters;

				object paramValue;

				int cAttributes = nds.AttributeCount;
				for (int a = 0; a < cAttributes; ++a)
				{
					netAttribute = nds.get_Attribute(a) as INetworkAttribute2;
					attributeName = netAttribute.Name;
					netParameters = netAttribute.Parameters;

					cParameters = netParameters.Count;
					for (int p = 0; p < cParameters; ++p)
					{
						netParameter = netParameters.get_Element(p) as INetworkAttributeParameter;
						paramName = netParameter.Name;

						paramValue = naSolverSettings2.get_AttributeParameterValue(attributeName, paramName);
						netParameter.Value = paramValue;
					}

					netAttribute.Refresh();
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "Push Parameter Values To Network");
			}
		}

		public static bool ParameterExists(INetworkDataset nds, string searchName, VarType vt)
		{
			bool found = false;

			INetworkAttribute2 netAttribute;
			IArray netParams;
			INetworkAttributeParameter netParam;

			int cAttributes = nds.AttributeCount;
			for (int a = 0; a < cAttributes; ++a)
			{
				netAttribute = nds.get_Attribute(a) as INetworkAttribute2;
				netParams = null;
				int cParams = 0;
				if (netAttribute != null)
					netParams = netAttribute.Parameters;

				if (netParams != null)
					cParams = netParams.Count;

				string compareName;
				for (int p = 0; p < cParams; ++p)
				{
					netParam = netParams.get_Element(p) as INetworkAttributeParameter;
					compareName = netParam.Name;
					if (String.Compare(searchName, compareName, true) == 0)
					{
						found = true;
						break;
					}
				}
				if (found)
					break;
			}

			return found;
		}

		public static void ClearEIDArrayParameterValues(INetworkAnalystExtension nax, string baseName)
		{
			try
			{
				INAWindow naWindow = nax.NAWindow;
				INALayer naLayer = null;
				INAContext naContext = null;
				INetworkDataset nds = null;

				naLayer = naWindow.ActiveAnalysis;
				if (naLayer != null)
					naContext = naLayer.Context;

				if (naContext != null)
					nds = naContext.NetworkDataset;

				if (nds == null)
					return;

				VarType vt = SubsetHelperUI.GetEIDArrayParameterType();
				List<string> sourceNames = SubsetHelperUI.FindParameterizedSourceNames(nds, baseName, vt);

				SubsetHelperUI.ClearEIDArrayParameterValues(nax, sourceNames, baseName);
				SubsetHelperUI.PushParameterValuesToNetwork(nax);
			}
			catch (Exception ex)
			{
				string msg = SubsetHelperUI.GetFullExceptionMessage(ex);
				MessageBox.Show(msg, "Clear Network Element Array Parameters");
			}
		}

		private static void ClearEIDArrayParameterValues(INetworkAnalystExtension nax, List<string> sourceNames, string baseName)
		{
			if (nax == null)
				return;

			bool naxEnabled = false;
			IExtensionConfig naxConfig = nax as IExtensionConfig;
			naxEnabled = naxConfig.State == esriExtensionState.esriESEnabled;

			if (!naxEnabled)
				return;

			Dictionary<string, List<int>> eidsBySourceName = new Dictionary<string, List<int>>();
			foreach (string sourceName in sourceNames)
			{
				List<int> eids = null;
				if (!eidsBySourceName.TryGetValue(sourceName, out eids))
					eidsBySourceName.Add(sourceName, null);
			}

			UpdateEIDArrayParameterValuesFromEIDLists(nax, eidsBySourceName, baseName);
		}

		public static void UpdateEIDArrayParameterValuesFromEIDLists(INetworkAnalystExtension nax, Dictionary<string, List<int>> eidsBySourceName, string baseName)
		{
			if (nax == null)
				return;

			bool naxEnabled = false;
			IExtensionConfig naxConfig = nax as IExtensionConfig;
			naxEnabled = naxConfig.State == esriExtensionState.esriESEnabled;

			if (!naxEnabled)
				return;

			INAWindow naWindow = nax.NAWindow;
			INALayer naLayer = null;
			INAContext naContext = null;
			INetworkDataset nds = null;

			naLayer = naWindow.ActiveAnalysis;
			if (naLayer != null)
				naContext = naLayer.Context;

			if (naContext != null)
				nds = naContext.NetworkDataset;

			if (nds == null)
				return;

			IDatasetComponent dsComponent = nds as IDatasetComponent;
			IDENetworkDataset deNet = dsComponent.DataElement as IDENetworkDataset;

			INASolver naSolver = naContext.Solver;
			INASolverSettings2 naSolverSettings2 = naSolver as INASolverSettings2;

			if (naSolverSettings2 == null)
				return;

			string prefix = GetEIDArrayPrefixFromBaseName(baseName);
			VarType vt = GetEIDArrayParameterType();

			int cAttributes = nds.AttributeCount;
			for (int a = 0; a < cAttributes; ++a)
			{
				INetworkAttribute2 netAttribute = nds.get_Attribute(a) as INetworkAttribute2;
				IArray netParams = netAttribute.Parameters;
				int cParams = netParams.Count;
				object paramValue;
				for (int p = 0; p < cParams; ++p)
				{
					INetworkAttributeParameter param = netParams.get_Element(p) as INetworkAttributeParameter;
					if (param.VarType != (int)vt)
						continue;

					string paramName = param.Name;
					string sourceName = GetSourceNameFromParameterName(prefix, paramName);
					if (sourceName.Length == 0)
						continue;

					List<int> eids = null;
					if (eidsBySourceName.TryGetValue(sourceName, out eids))
					{
						if (eids != null)
						{
							if (eids.Count == 0)
								eids = null;
						}
					}

					paramValue = (eids != null) ? eids.ToArray() : null;
					naSolverSettings2.set_AttributeParameterValue(netAttribute.Name, param.Name, paramValue);
				}
			}
		}

		public static void UpdateEIDArrayParameterValuesFromOIDArrays(INetworkAnalystExtension nax, Dictionary<string, ILongArray> oidArraysBySourceName, string baseName)
		{
			Dictionary<string, List<int>> eidsBySourceName = GetEIDListsBySourceName(nax, oidArraysBySourceName, baseName);
			UpdateEIDArrayParameterValuesFromEIDLists(nax, eidsBySourceName, baseName);
		}

		public static void UpdateEIDArrayParameterValuesFromGeometry(INetworkAnalystExtension nax, IGeometry searchGeometry, string baseName)
		{
			Dictionary<string, List<int>> eidsBySourceName = GetEIDListsBySourceName(nax, searchGeometry, baseName);
			UpdateEIDArrayParameterValuesFromEIDLists(nax, eidsBySourceName, baseName);
		}

		private static Dictionary<string, List<int>> GetEIDListsBySourceName(INetworkAnalystExtension nax, object searchObject, string baseName)
		{
			if (nax == null)
				return null;

			bool naxEnabled = false;
			IExtensionConfig naxConfig = nax as IExtensionConfig;
			naxEnabled = naxConfig.State == esriExtensionState.esriESEnabled;

			if (!naxEnabled)
				return null;

			INAWindow naWindow = nax.NAWindow;
			INALayer naLayer = null;
			INAContext naContext = null;
			INetworkDataset nds = null;

			naLayer = naWindow.ActiveAnalysis;
			if (naLayer != null)
				naContext = naLayer.Context;

			if (naContext != null)
				nds = naContext.NetworkDataset;

			INetworkQuery netQuery = nds as INetworkQuery;
			if (netQuery == null)
				return null;

			bool oidSearch = false;
			bool geometrySearch = false;

			if (searchObject == null)
				return null;
			else if (searchObject is Dictionary<string, ILongArray>)
				oidSearch = true;
			else if (searchObject is IGeometry)
				geometrySearch = true;
			else
				return null;

			VarType vt = GetEIDArrayParameterType();
			List<string> sourceNames = FindParameterizedSourceNames(nds, baseName, vt);
			Dictionary<string, List<int>> eidsBySourceName = new Dictionary<string, List<int>>();
			foreach (string sourceName in sourceNames)
			{
				INetworkSource netSource = nds.get_SourceByName(sourceName);
				int sourceID = netSource.ID;
				List<int> eids = new List<int>();

				if (oidSearch)
				{
					Dictionary<string, ILongArray> oidArraysBySourceName = (Dictionary<string, ILongArray>)searchObject;
					ILongArray oids = null;
					IEnumNetworkElement enumNetElement;
					INetworkElement netElement;

					if (oidArraysBySourceName.TryGetValue(sourceName, out oids))
					{
						enumNetElement = netQuery.get_ElementsByOIDs(sourceID, oids);
						enumNetElement.Reset();
						netElement = enumNetElement.Next();
						while (netElement != null)
						{
							eids.Add(netElement.EID);
							netElement = enumNetElement.Next();
						}
					}
				}
				else if (geometrySearch)
				{
					IGeometry searchGeometry = (IGeometry)searchObject;
					if (searchGeometry != null && !searchGeometry.IsEmpty)
					{
						IGeometry elementGeometry = null;
						esriNetworkElementType elementType = esriNetworkElementType.esriNETEdge;
						int eid = -1;

						// Search for the network dataset layer associated with the active analysis layer or create one using the
						// network dataset if matching one not found.
						// If, for example, multiple network dataset layers are added to the map, the active analysis layer
						// might not reference the current network dataset layer (nax.CurrentNetworkLayer).

						INetworkLayer ndsLayer = new NetworkLayerClass();
						ndsLayer.NetworkDataset = nds;

						int count = nax.NetworkLayerCount;
						for (int i = 0; i < count; ++i)
						{
							ndsLayer = nax.get_NetworkLayer(i);
							if (ndsLayer.NetworkDataset == nds)
								break;
							else
								ndsLayer = null;
						}

						if (ndsLayer == null)
						{
							ndsLayer = new NetworkLayerClass();
							ndsLayer.NetworkDataset = nds;
						}

						IEnumLocatedNetworkElement enumLocatedNetElement = null;
						if (ndsLayer != null)
						{
							enumLocatedNetElement = ndsLayer.SearchLocatedNetworkElements(sourceName, searchGeometry);
							enumLocatedNetElement.Reset();
							eid = enumLocatedNetElement.Next(ref elementGeometry, ref elementType);
							while (eid != -1)
							{
								eids.Add(eid);
								eid = enumLocatedNetElement.Next(ref elementGeometry, ref elementType);
							}
						}
					}
				}

				eidsBySourceName.Add(sourceName, eids);
			}

			return eidsBySourceName;
		}

		public static Dictionary<string, ILongArray> GetOIDArraysBySourceNameFromMapSelection(IMap map, List<string> sourceNames)
		{
			UIDClass uid = new UIDClass();
			uid.Value = "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}"; //IGeoFeatureLayer

			IEnumLayer searchEnumLayer = map.get_Layers(uid, true);
			searchEnumLayer.Reset();

			//create result dictionary from source names with empty oidArrays

			Dictionary<string, ILongArray> oidArraysBySourceName = new Dictionary<string, ILongArray>();
			ILongArray oidArray = null;

			foreach (string sourceName in sourceNames)
			{
				if (!oidArraysBySourceName.TryGetValue(sourceName, out oidArray))
				{
					oidArray = new LongArrayClass();
					oidArraysBySourceName.Add(sourceName, oidArray);
				}
			}

			ILayer layer = searchEnumLayer.Next();
			while (layer != null)
			{
				IDisplayTable displayTable = layer as IDisplayTable;
				string sourceName = "";
				if (layer.Valid && layer.Visible && displayTable != null)
				{
					IDataset ds = displayTable.DisplayTable as IDataset;
					if (ds != null)
						sourceName = ds.Name;
				}

				if (sourceName.Length > 0)
				{
					if (oidArraysBySourceName.TryGetValue(sourceName, out oidArray))
					{
						ISelectionSet selSet = displayTable.DisplaySelectionSet;
						IEnumIDs enumOIDs = null;
						if (selSet != null)
							enumOIDs = selSet.IDs;

						if (enumOIDs != null)
						{
							enumOIDs.Reset();
							int oid = enumOIDs.Next();
							while (oid != -1)
							{
								oidArray.Add(oid);
								oid = enumOIDs.Next();
							}
						}
					}
				}

				layer = searchEnumLayer.Next();
			}

			return oidArraysBySourceName;
		}

		public static IGeometry GetSearchGeometryFromGraphics(IGraphicsContainer graphics)
		{
			IGeometryCollection geometryBag = new GeometryBagClass();
			IElement element;
			IGeometry geometry;

			graphics.Reset();
			element = graphics.Next();

			object before = Type.Missing;
			object after = Type.Missing;

			while (element != null)
			{
				geometry = element.Geometry;
				if (geometry is IPolygon)
					geometryBag.AddGeometry(geometry, ref before, ref after);

				element = graphics.Next();
			}

			IGeometry searchGeometry = geometryBag as IGeometry;

			return searchGeometry;
		}

		public static List<string> FindParameterizedSourceNames(INetworkDataset nds, string baseName, VarType vt)
		{
			List<string> sourceNamesList = new List<string>();
			Dictionary<string, int?> sourceNamesDictionary = new Dictionary<string, int?>();

			int? dummyValue = null;
			int? foundDummyValue = null;

			string prefix = GetEIDArrayPrefixFromBaseName(baseName);

			INetworkSource netSource;
			string sourceName;
			string searchParamName;
			int count = nds.SourceCount;
			for (int i = 0; i < count; ++i)
			{
				netSource = nds.get_Source(i);
				sourceName = netSource.Name;
				if (sourceNamesDictionary.TryGetValue(sourceName, out foundDummyValue))
					continue;

				searchParamName = GetSourceParameterName(prefix, sourceName);

				if (ParameterExists(nds, searchParamName, vt))
				{
					sourceNamesList.Add(sourceName);
					sourceNamesDictionary.Add(sourceName, dummyValue);
				}
			}

			return sourceNamesList;
		}

		public static VarType GetEIDArrayParameterType()
		{
			VarType vt = VarType.Array | VarType.Integer;
			return vt;
		}

		public static string SelectionEIDArrayBaseName
		{
			get
			{
				return FilterSubsetEvaluator.BaseParameterName;
			}
		}

		public static string GraphicsEIDArrayBaseName
		{
			get
			{
				return ScaleSubsetEvaluator.BaseParameterName;
			}
		}

		private static string GetEIDArrayPrefixFromBaseName(string baseName)
		{
			string baseNameEIDArrayModifer = "_eids";
			string prefix = baseName;
			prefix += baseNameEIDArrayModifer;

			return prefix;
		}

		private static string GetSourceNameFromParameterName(string prefix, string paramName)
		{
			string searchSubName = prefix + "_";

			int searchSubNameLen = searchSubName.Length;
			int paramNameLen = paramName.Length;
			if (searchSubNameLen <= 0 || searchSubNameLen >= paramNameLen)
				return "";

			string compareSubName = paramName.Substring(0, searchSubNameLen);
			if (String.Compare(compareSubName, searchSubName, true) != 0)
				return "";

			string sourceName = paramName.Substring(searchSubNameLen);
			return sourceName;
		}

		private static string GetSourceParameterName(string prefix, string sourceName)
		{
			string paramName = prefix;
			paramName += "_";
			paramName += sourceName;

			return paramName;
		}

		public static IExtensionConfig GetNAXConfiguration(IApplication app)
		{
			IExtensionConfig extConfig = null;
			try
			{
				if (app != null)
				{
					UID extCLSID = new UIDClass();
					extCLSID.Value = "{C967BD39-1118-42EE-AAAB-B31642C89C3E}"; // Network Analyst
					extConfig = app.FindExtensionByCLSID(extCLSID) as IExtensionConfig;
				}
			}
			catch
			{
				extConfig = null;
			}

			return extConfig;
		}

		public static string GetFullExceptionMessage(Exception ex)
		{
			string msg = "";
			string subMsg = "";

			while (ex != null)
			{
				subMsg = ex.Message;
				if (subMsg.Length > 0 && msg.Length > 0)
					msg += "\n";

				msg += subMsg;
				ex = ex.InnerException;
			}

			return msg;
		}
	}
}

[Visual Basic .NET]

SubsetHelperUI.vb

Imports Microsoft.VisualBasic
Imports System
Imports System.Drawing
Imports System.Collections.Generic
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports ESRI.ArcGIS.ADF.BaseClasses
Imports ESRI.ArcGIS.ADF.CATIDs
Imports ESRI.ArcGIS.Framework
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.NetworkAnalyst
Imports ESRI.ArcGIS.ArcMapUI
Imports ESRI.ArcGIS.NetworkAnalystUI
Imports SubsetNetworkEvaluators

Namespace SubsetNetworkEvaluatorsUI
	''' <summary>
	''' The SubsetHelperUI is a utility class to aid in determining the relevant set of parameters
	''' to auto-update when set to listen to the events and other shared utilities.
	''' </summary>	
	Friend Class SubsetHelperUI
		Public Shared Sub PushParameterValuesToNetwork(ByVal nax As INetworkAnalystExtension)
			Try
				If nax Is Nothing Then
					Return
				End If

				Dim naxEnabled As Boolean = False
				Dim naxConfig As IExtensionConfig = TryCast(nax, IExtensionConfig)
				naxEnabled = naxConfig.State = esriExtensionState.esriESEnabled

				If (Not naxEnabled) Then
					Return
				End If

				Dim naWindow As INAWindow = nax.NAWindow
				Dim naLayer As INALayer = Nothing
				Dim naContext As INAContext = Nothing
				Dim nds As INetworkDataset = Nothing

				naLayer = naWindow.ActiveAnalysis
				If Not naLayer Is Nothing Then
					naContext = naLayer.Context
				End If

				If Not naContext Is Nothing Then
					nds = naContext.NetworkDataset
				End If

				If nds Is Nothing Then
					Return
				End If

				Dim dsComponent As IDatasetComponent = TryCast(nds, IDatasetComponent)
				Dim deNet As IDENetworkDataset = TryCast(dsComponent.DataElement, IDENetworkDataset)

				Dim naSolver As INASolver = naContext.Solver
				Dim naSolverSettings2 As INASolverSettings2 = TryCast(naSolver, INASolverSettings2)

				If naSolverSettings2 Is Nothing Then
					Return
				End If

				Dim netAttribute As INetworkAttribute2
				Dim attributeName As String

				Dim netParameters As IArray
				Dim netParameter As INetworkAttributeParameter
				Dim paramName As String
				Dim cParameters As Integer

				Dim paramValue As Object

				Dim cAttributes As Integer = nds.AttributeCount
				Dim a As Integer = 0
				Do While a < cAttributes
					netAttribute = TryCast(nds.Attribute(a), INetworkAttribute2)
					attributeName = netAttribute.Name
					netParameters = netAttribute.Parameters

					cParameters = netParameters.Count
					Dim p As Integer = 0
					Do While p < cParameters
						netParameter = TryCast(netParameters.Element(p), INetworkAttributeParameter)
						paramName = netParameter.Name

						paramValue = naSolverSettings2.AttributeParameterValue(attributeName, paramName)
						netParameter.Value = paramValue
						p += 1
					Loop

					netAttribute.Refresh()
					a += 1
				Loop
			Catch ex As Exception
				MessageBox.Show(ex.Message, "Push Parameter Values To Network")
			End Try
		End Sub

		Public Shared Function ParameterExists(ByVal nds As INetworkDataset, ByVal searchName As String, ByVal vt As VarType) As Boolean
			Dim found As Boolean = False

			Dim netAttribute As INetworkAttribute2
			Dim netParams As IArray
			Dim netParam As INetworkAttributeParameter

			Dim cAttributes As Integer = nds.AttributeCount
			Dim a As Integer = 0
			Do While a < cAttributes
				netAttribute = TryCast(nds.Attribute(a), INetworkAttribute2)
				netParams = Nothing
				Dim cParams As Integer = 0
				If Not netAttribute Is Nothing Then
					netParams = netAttribute.Parameters
				End If

				If Not netParams Is Nothing Then
					cParams = netParams.Count
				End If

				Dim compareName As String
				Dim p As Integer = 0
				Do While p < cParams
					netParam = TryCast(netParams.Element(p), INetworkAttributeParameter)
					compareName = netParam.Name
					If String.Compare(searchName, compareName, True) = 0 Then
						found = True
						Exit Do
					End If
					p += 1
				Loop
				If found Then
					Exit Do
				End If
				a += 1
			Loop

			Return found
		End Function

		Public Shared Sub ClearEIDArrayParameterValues(ByVal nax As INetworkAnalystExtension, ByVal baseName As String)
			Try
				Dim naWindow As INAWindow = nax.NAWindow
				Dim naLayer As INALayer = Nothing
				Dim naContext As INAContext = Nothing
				Dim nds As INetworkDataset = Nothing

				naLayer = naWindow.ActiveAnalysis
				If Not naLayer Is Nothing Then
					naContext = naLayer.Context
				End If

				If Not naContext Is Nothing Then
					nds = naContext.NetworkDataset
				End If

				If nds Is Nothing Then
					Return
				End If

				Dim vt As VarType = SubsetHelperUI.GetEIDArrayParameterType()
				Dim sourceNames As List(Of String) = SubsetHelperUI.FindParameterizedSourceNames(nds, baseName, vt)

				SubsetHelperUI.ClearEIDArrayParameterValues(nax, sourceNames, baseName)
				SubsetHelperUI.PushParameterValuesToNetwork(nax)
			Catch ex As Exception
				Dim msg As String = SubsetHelperUI.GetFullExceptionMessage(ex)
				MessageBox.Show(msg, "Clear Network Element Array Parameters")
			End Try
		End Sub

		Private Shared Sub ClearEIDArrayParameterValues(ByVal nax As INetworkAnalystExtension, ByVal sourceNames As List(Of String), ByVal baseName As String)
			If nax Is Nothing Then
				Return
			End If

			Dim naxEnabled As Boolean = False
			Dim naxConfig As IExtensionConfig = TryCast(nax, IExtensionConfig)
			naxEnabled = naxConfig.State = esriExtensionState.esriESEnabled

			If (Not naxEnabled) Then
				Return
			End If

			Dim eidsBySourceName As Dictionary(Of String, List(Of Integer)) = New Dictionary(Of String, List(Of Integer))
			For Each sourceName As String In sourceNames
				Dim eids As List(Of Integer) = Nothing
				If (Not eidsBySourceName.TryGetValue(sourceName, eids)) Then
					eidsBySourceName.Add(sourceName, Nothing)
				End If
			Next sourceName

			UpdateEIDArrayParameterValuesFromEIDLists(nax, eidsBySourceName, baseName)
		End Sub

		Public Shared Sub UpdateEIDArrayParameterValuesFromEIDLists(ByVal nax As INetworkAnalystExtension, ByVal eidsBySourceName As Dictionary(Of String, List(Of Integer)), ByVal baseName As String)
			If nax Is Nothing Then
				Return
			End If

			Dim naxEnabled As Boolean = False
			Dim naxConfig As IExtensionConfig = TryCast(nax, IExtensionConfig)
			naxEnabled = naxConfig.State = esriExtensionState.esriESEnabled

			If (Not naxEnabled) Then
				Return
			End If

			Dim naWindow As INAWindow = nax.NAWindow
			Dim naLayer As INALayer = Nothing
			Dim naContext As INAContext = Nothing
			Dim nds As INetworkDataset = Nothing

			naLayer = naWindow.ActiveAnalysis
			If Not naLayer Is Nothing Then
				naContext = naLayer.Context
			End If

			If Not naContext Is Nothing Then
				nds = naContext.NetworkDataset
			End If

			If nds Is Nothing Then
				Return
			End If

			Dim dsComponent As IDatasetComponent = TryCast(nds, IDatasetComponent)
			Dim deNet As IDENetworkDataset = TryCast(dsComponent.DataElement, IDENetworkDataset)

			Dim naSolver As INASolver = naContext.Solver
			Dim naSolverSettings2 As INASolverSettings2 = TryCast(naSolver, INASolverSettings2)

			If naSolverSettings2 Is Nothing Then
				Return
			End If

			Dim prefix As String = GetEIDArrayPrefixFromBaseName(baseName)
			Dim vt As VarType = GetEIDArrayParameterType()

			Dim cAttributes As Integer = nds.AttributeCount
			Dim a As Integer = 0
			For a = 0 To cAttributes - 1
				Dim netAttribute As INetworkAttribute2 = TryCast(nds.Attribute(a), INetworkAttribute2)
				Dim netParams As IArray = netAttribute.Parameters
				Dim cParams As Integer = netParams.Count
				Dim paramValue As Object
				Dim p As Integer = 0
				For p = 0 To cParams - 1
					Dim param As INetworkAttributeParameter = TryCast(netParams.Element(p), INetworkAttributeParameter)
					If param.VarType <> CInt(vt) Then
						Continue For
					End If

					Dim paramName As String = param.Name
					Dim sourceName As String = GetSourceNameFromParameterName(prefix, paramName)
					If sourceName.Length = 0 Then
						Continue For
					End If

					Dim eids As List(Of Integer) = Nothing
					If eidsBySourceName.TryGetValue(sourceName, eids) Then
						If Not eids Is Nothing Then
							If eids.Count = 0 Then
								eids = Nothing
							End If
						End If
					End If

					If (Not eids Is Nothing) Then
						paramValue = eids.ToArray()
					Else
						paramValue = Nothing
					End If

					naSolverSettings2.AttributeParameterValue(netAttribute.Name, param.Name) = paramValue
				Next p
			Next a
		End Sub

		Public Shared Sub UpdateEIDArrayParameterValuesFromOIDArrays(ByVal nax As INetworkAnalystExtension, ByVal oidArraysBySourceName As Dictionary(Of String, ILongArray), ByVal baseName As String)
			Dim eidsBySourceName As Dictionary(Of String, List(Of Integer)) = GetEIDListsBySourceName(nax, oidArraysBySourceName, baseName)
			UpdateEIDArrayParameterValuesFromEIDLists(nax, eidsBySourceName, baseName)
		End Sub

		Public Shared Sub UpdateEIDArrayParameterValuesFromGeometry(ByVal nax As INetworkAnalystExtension, ByVal searchGeometry As IGeometry, ByVal baseName As String)
			Dim eidsBySourceName As Dictionary(Of String, List(Of Integer)) = GetEIDListsBySourceName(nax, searchGeometry, baseName)
			UpdateEIDArrayParameterValuesFromEIDLists(nax, eidsBySourceName, baseName)
		End Sub

		Private Shared Function GetEIDListsBySourceName(ByVal nax As INetworkAnalystExtension, ByVal searchObject As Object, ByVal baseName As String) As Dictionary(Of String, List(Of Integer))
			If nax Is Nothing Then
				Return Nothing
			End If

			Dim naxEnabled As Boolean = False
			Dim naxConfig As IExtensionConfig = TryCast(nax, IExtensionConfig)
			naxEnabled = naxConfig.State = esriExtensionState.esriESEnabled

			If (Not naxEnabled) Then
				Return Nothing
			End If

			Dim naWindow As INAWindow = nax.NAWindow
			Dim naLayer As INALayer = Nothing
			Dim naContext As INAContext = Nothing
			Dim nds As INetworkDataset = Nothing

			naLayer = naWindow.ActiveAnalysis
			If Not naLayer Is Nothing Then
				naContext = naLayer.Context
			End If

			If Not naContext Is Nothing Then
				nds = naContext.NetworkDataset
			End If

			Dim netQuery As INetworkQuery = TryCast(nds, INetworkQuery)
			If netQuery Is Nothing Then
				Return Nothing
			End If

			Dim oidSearch As Boolean = False
			Dim geometrySearch As Boolean = False

			If searchObject Is Nothing Then
				Return Nothing
			ElseIf TypeOf searchObject Is Dictionary(Of String, ILongArray) Then
				oidSearch = True
			ElseIf TypeOf searchObject Is IGeometry Then
				geometrySearch = True
			Else
				Return Nothing
			End If

			Dim vt As VarType = GetEIDArrayParameterType()
			Dim sourceNames As List(Of String) = FindParameterizedSourceNames(nds, baseName, vt)
			Dim eidsBySourceName As Dictionary(Of String, List(Of Integer)) = New Dictionary(Of String, List(Of Integer))
			For Each sourceName As String In sourceNames
				Dim netSource As INetworkSource = nds.SourceByName(sourceName)
				Dim sourceID As Integer = netSource.ID
				Dim eids As List(Of Integer) = New List(Of Integer)()

				If oidSearch Then
					Dim oidArraysBySourceName As Dictionary(Of String, ILongArray) = TryCast(searchObject, Dictionary(Of String, ILongArray))
					Dim oids As ILongArray = Nothing
					Dim enumNetElement As IEnumNetworkElement
					Dim netElement As INetworkElement

					If oidArraysBySourceName.TryGetValue(sourceName, oids) Then
						enumNetElement = netQuery.ElementsByOIDs(sourceID, oids)
						enumNetElement.Reset()
						netElement = enumNetElement.Next()
						Do While Not netElement Is Nothing
							eids.Add(netElement.EID)
							netElement = enumNetElement.Next()
						Loop
					End If
				ElseIf geometrySearch Then
					Dim searchGeometry As IGeometry = CType(searchObject, IGeometry)
					If Not searchGeometry Is Nothing AndAlso (Not searchGeometry.IsEmpty) Then
						Dim elementGeometry As IGeometry = Nothing
						Dim elementType As esriNetworkElementType = esriNetworkElementType.esriNETEdge
						Dim eid As Integer = -1

						' Search for the network dataset layer associated with the active analysis layer or create one using the
						' network dataset if matching one not found.
						' If, for example, multiple network dataset layers are added to the map, the active analysis layer
						' might not reference the current network dataset layer (nax.CurrentNetworkLayer).

						Dim ndsLayer As INetworkLayer = New NetworkLayerClass()
						ndsLayer.NetworkDataset = nds

						Dim count As Integer = nax.NetworkLayerCount
						Dim i As Integer = 0
						Do While i < count
							ndsLayer = nax.NetworkLayer(i)
							If ndsLayer.NetworkDataset Is nds Then
								Exit Do
							Else
								ndsLayer = Nothing
							End If
							i += 1
						Loop

						If ndsLayer Is Nothing Then
							ndsLayer = New NetworkLayerClass()
							ndsLayer.NetworkDataset = nds
						End If

						Dim enumLocatedNetElement As IEnumLocatedNetworkElement = Nothing
						If Not ndsLayer Is Nothing Then
							enumLocatedNetElement = ndsLayer.SearchLocatedNetworkElements(sourceName, searchGeometry)
							enumLocatedNetElement.Reset()
							eid = enumLocatedNetElement.Next(elementGeometry, elementType)
							Do While eid <> -1
								eids.Add(eid)
								eid = enumLocatedNetElement.Next(elementGeometry, elementType)
							Loop
						End If
					End If
				End If

				eidsBySourceName.Add(sourceName, eids)
			Next sourceName

			Return eidsBySourceName
		End Function

		Public Shared Function GetOIDArraysBySourceNameFromMapSelection(ByVal map As IMap, ByVal sourceNames As List(Of String)) As Dictionary(Of String, ILongArray)
			Dim uid As UIDClass = New UIDClass()
			uid.Value = "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}" 'IGeoFeatureLayer

			Dim searchEnumLayer As IEnumLayer = map.Layers(uid, True)
			searchEnumLayer.Reset()

			'create result dictionary from source names with empty oidArrays

			Dim oidArraysBySourceName As Dictionary(Of String, ILongArray) = New Dictionary(Of String, ILongArray)()
			Dim oidArray As ILongArray = Nothing

			For Each sourceName As String In sourceNames
				If (Not oidArraysBySourceName.TryGetValue(sourceName, oidArray)) Then
					oidArray = New LongArrayClass()
					oidArraysBySourceName.Add(sourceName, oidArray)
				End If
			Next sourceName

			Dim layer As ILayer = searchEnumLayer.Next()
			Do While Not layer Is Nothing
				Dim displayTable As IDisplayTable = TryCast(layer, IDisplayTable)
				Dim sourceName As String = ""
				If layer.Valid AndAlso layer.Visible AndAlso Not displayTable Is Nothing Then
					Dim ds As IDataset = TryCast(displayTable.DisplayTable, IDataset)
					If Not ds Is Nothing Then
						sourceName = ds.Name
					End If
				End If

				If sourceName.Length > 0 Then
					If oidArraysBySourceName.TryGetValue(sourceName, oidArray) Then
						Dim selSet As ISelectionSet = displayTable.DisplaySelectionSet
						Dim enumOIDs As IEnumIDs = Nothing
						If Not selSet Is Nothing Then
							enumOIDs = selSet.IDs
						End If

						If Not enumOIDs Is Nothing Then
							enumOIDs.Reset()
							Dim oid As Integer = enumOIDs.Next()
							Do While oid <> -1
								oidArray.Add(oid)
								oid = enumOIDs.Next()
							Loop
						End If
					End If
				End If

				layer = searchEnumLayer.Next()
			Loop

			Return oidArraysBySourceName
		End Function

		Public Shared Function GetSearchGeometryFromGraphics(ByVal graphics As IGraphicsContainer) As IGeometry
			Dim geometryBag As IGeometryCollection = New GeometryBagClass()
			Dim element As IElement
			Dim geometry As IGeometry

			graphics.Reset()
			element = graphics.Next()

			Dim before As Object = Type.Missing
			Dim after As Object = Type.Missing

			Do While Not element Is Nothing
				geometry = element.Geometry
				If TypeOf geometry Is IPolygon Then
					geometryBag.AddGeometry(geometry, before, after)
				End If

				element = graphics.Next()
			Loop

			Dim searchGeometry As IGeometry = TryCast(geometryBag, IGeometry)

			Return searchGeometry
		End Function

		Public Shared Function FindParameterizedSourceNames(ByVal nds As INetworkDataset, ByVal baseName As String, ByVal vt As VarType) As List(Of String)
			Dim sourceNamesList As List(Of String) = New List(Of String)()
			Dim sourceNamesDictionary As Dictionary(Of String, Nullable(Of Integer)) = New Dictionary(Of String, Nullable(Of Integer))

			Dim dummyValue As Nullable(Of Integer) = Nothing
			Dim foundDummyValue As Nullable(Of Integer) = Nothing

			Dim prefix As String = GetEIDArrayPrefixFromBaseName(baseName)

			Dim netSource As INetworkSource
			Dim sourceName As String
			Dim searchParamName As String
			Dim count As Integer = nds.SourceCount
			Dim i As Integer = 0
			For i = 0 To count - 1
				netSource = nds.Source(i)
				sourceName = netSource.Name
				If sourceNamesDictionary.TryGetValue(sourceName, foundDummyValue) Then
					Continue For
				End If

				searchParamName = GetSourceParameterName(prefix, sourceName)

				If ParameterExists(nds, searchParamName, vt) Then
					sourceNamesList.Add(sourceName)
					sourceNamesDictionary.Add(sourceName, dummyValue)
				End If
			Next i

			Return sourceNamesList
		End Function

		Public Shared Function GetEIDArrayParameterType() As VarType
			Dim vt As VarType = VarType.Array Or VarType.Integer
			Return vt
		End Function

		Public Shared ReadOnly Property SelectionEIDArrayBaseName() As String
			Get
				Return FilterSubsetEvaluator.BaseParameterName
			End Get
		End Property

		Public Shared ReadOnly Property GraphicsEIDArrayBaseName() As String
			Get
				Return ScaleSubsetEvaluator.BaseParameterName
			End Get
		End Property

		Private Shared Function GetEIDArrayPrefixFromBaseName(ByVal baseName As String) As String
			Dim baseNameEIDArrayModifer As String = "_eids"
			Dim prefix As String = baseName
			prefix &= baseNameEIDArrayModifer

			Return prefix
		End Function

		Private Shared Function GetSourceNameFromParameterName(ByVal prefix As String, ByVal paramName As String) As String
			Dim searchSubName As String = prefix & "_"

			Dim searchSubNameLen As Integer = searchSubName.Length
			Dim paramNameLen As Integer = paramName.Length
			If searchSubNameLen <= 0 OrElse searchSubNameLen >= paramNameLen Then
				Return ""
			End If

			Dim compareSubName As String = paramName.Substring(0, searchSubNameLen)
			If String.Compare(compareSubName, searchSubName, True) <> 0 Then
				Return ""
			End If

			Dim sourceName As String = paramName.Substring(searchSubNameLen)
			Return sourceName
		End Function

		Private Shared Function GetSourceParameterName(ByVal prefix As String, ByVal sourceName As String) As String
			Dim paramName As String = prefix
			paramName &= "_"
			paramName &= sourceName

			Return paramName
		End Function

		Public Shared Function GetNAXConfiguration(ByVal app As IApplication) As IExtensionConfig
			Dim extConfig As IExtensionConfig = Nothing
			Try
				If Not app Is Nothing Then
					Dim extCLSID As UID = New UIDClass()
					extCLSID.Value = "{C967BD39-1118-42EE-AAAB-B31642C89C3E}" ' Network Analyst
					extConfig = TryCast(app.FindExtensionByCLSID(extCLSID), IExtensionConfig)
				End If
			Catch
				extConfig = Nothing
			End Try

			Return extConfig
		End Function

		Public Shared Function GetFullExceptionMessage(ByVal ex As Exception) As String
			Dim msg As String = ""
			Dim subMsg As String = ""

			Do While Not ex Is Nothing
				subMsg = ex.Message
				If subMsg.Length > 0 AndAlso msg.Length > 0 Then
					msg &= Constants.vbLf
				End If

				msg &= subMsg
				ex = ex.InnerException
			Loop

			Return msg
		End Function
	End Class
End Namespace