About the Tabbed feature inspector Sample
[C#]
AttachTabbedInspectorExtensionCommand.cs
using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; using ESRI.ArcGIS.ADF.BaseClasses; using ESRI.ArcGIS.ADF.CATIDs; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Controls; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.Geodatabase; using System.Diagnostics; namespace TabbedFeatureInspector { /// <summary> /// A command that attaches/detaches the 'tabbed inspector' extension class from /// the feature class selected in the table of contents. /// In order to work correctly, the hosting application must implement and pass an /// instance of IApplicationServices in the CustomProperty of its toolbar control. /// </summary> [Guid("14BAA8DD-677E-425b-B5CC-26F18B41D5B3")] [ClassInterface(ClassInterfaceType.None)] [ProgId("TabbedFeatureInspectorCS.AttachTabbedInspectorExtensionCommand")] public sealed class AttachTabbedInspectorExtensionCommand : BaseCommand { #region COM Registration Function(s) [ComRegisterFunction] [ComVisible(false)] public static void RegisterFunction(Type registerType) { // Required for ArcGIS Component Category Registrar support ArcGISCategoryRegistration(registerType); } [ComUnregisterFunction] [ComVisible(false)] public static void UnregisterFunction(Type registerType) { // Required for ArcGIS Component Category Registrar support ArcGISCategoryUnregistration(registerType); } #region ArcGIS Component Category Registrar generated code /// <summary> /// Required method for ArcGIS Component Category registration - /// Do not modify the contents of this method with the code editor. /// </summary> private static void ArcGISCategoryRegistration(Type registerType) { string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID); ControlsCommands.Register(regKey); } /// <summary> /// Required method for ArcGIS Component Category unregistration - /// Do not modify the contents of this method with the code editor. /// </summary> private static void ArcGISCategoryUnregistration(Type registerType) { string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID); ControlsCommands.Unregister(regKey); } #endregion #endregion IHookHelper m_hookHelper; IApplicationServices m_appServices; public AttachTabbedInspectorExtensionCommand() { m_category = "Developer Samples"; m_caption = "Attach/Detach Tabbed Inspector Extension CS"; m_message = "This command attaches or detaches the Tabbed Inspector class extension from the selected feature class."; m_toolTip = "This command attaches or detaches the Tabbed Inspector class extension from the selected feature class."; m_name = "TabbedInspector_AttachDetachExtension_CS"; } /// <summary> /// Occurs when this command is created /// </summary> /// <param name="hook">Instance of the application</param> public override void OnCreate(object hook) { if (hook == null) return; m_hookHelper = new HookHelperClass(); m_hookHelper.Hook = hook; m_appServices = null; } /// <summary> /// Occurs when this command is clicked /// </summary> public override void OnClick() { try { GetApplicationServices(); IFeatureLayer fl = m_appServices.GetLayerSelectedInTOC(); if (fl != null) AlterClassExtension(fl.FeatureClass); else m_appServices.SetStatusMessage("Couldn't attach the 'custom inspector' extension. No feature layer was selected in the Table of Contents.", true); } catch (Exception ex) { MessageBox.Show("Error: Could open the feature class. Original error: " + ex.Message); } } /// <summary> /// Obtains the IApplicationServices interface instance implemented by the hosting application. /// This is needed so the command can determine the selected layer, and update the application's status message. /// </summary> void GetApplicationServices() { if (m_appServices == null) { IToolbarControl2 toolbarControl = m_hookHelper.Hook as IToolbarControl2; if (toolbarControl == null) throw new ApplicationException( "Command appears to be running in an unexpected environment. Its hookHelper ought to be a toolbar control."); m_appServices = toolbarControl.CustomProperty as IApplicationServices; if (m_appServices == null) throw new ApplicationException( "Command appears to be running in an unexpected environment. The toolbar custom property ought to be an instance of IApplicationServices."); } } /// <summary> /// Perform the work contained in the delegate inside an exclusive schema lock. /// </summary> /// <param name="fc">The feature class whose schema is to be exclusively locked.</param> /// <param name="work">The work to be performed.</param> static void DoInSchemaLock(IFeatureClass fc, MethodInvoker work) { ISchemaLock schemaLock = (ISchemaLock)fc; try { // Exclusively lock the class schema. schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock); // Do the work inside the schema lock work(); } finally { // Release the exclusive lock on the featureclass' schema. schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock); } } /// <summary> /// This method attaches or detaches the "TabbedInspector" class extension to/from the specified /// feature class. If the featureclass already has an extension class, and it isn't the 'TabbedInspector' extension, /// the method does not modify the class extension. /// </summary> /// <param name="fc">The feature class to be altered.</param> /// <returns>Whether the operation succeeded (successful detach or attach).</returns> bool AlterClassExtension(IFeatureClass fc) { // Attempt to get access to schema-editing functionality on the feature class IClassSchemaEdit classSchemaEdit = fc as IClassSchemaEdit; if (classSchemaEdit == null) { m_appServices.SetStatusMessage("The selected feature class doesn't support attaching an extension class.", true); return false; } // Create a UID object holding the TabbedInspector's CLSID UID classUID = new UIDClass(); classUID.Value = "{" + TabbedInspector.TabbedInspectorCLSID + "}"; // Do the schema update within a schema lock. bool succeeded = false; DoInSchemaLock(fc, delegate { // Does the feature class already have an extension class associated with it? if (fc.EXTCLSID != null) { // The featureclass already has an extension attached. if (fc.EXTCLSID.Value.Equals(classUID.Value)) { // The extension is the TabbedInspector extension. Detach it. classSchemaEdit.AlterClassExtensionCLSID(null, null); m_appServices.SetStatusMessage( string.Format("The 'custom inspector' extension class was detached from {0}.", fc.AliasName), false); succeeded = true; } else { //Don't mess with featureclasses that have some other existing extension class associated with them. m_appServices.SetStatusMessage( string.Format("{0} already has another extension class attached to it. No change was made.", fc.AliasName), true); succeeded = false; } } else { // There is no extension attached to the featureclass. Attach the TabbedInspector extension. classSchemaEdit.AlterClassExtensionCLSID(classUID, null); m_appServices.SetStatusMessage( string.Format("The 'custom inspector' extension class was attached to {0}.", fc.AliasName), false); succeeded = true; } }); return succeeded; } } }
[Visual Basic .NET]
AttachTabbedInspectorExtensionCommand.vb
Imports System Imports System.Drawing Imports System.Runtime.InteropServices Imports System.Windows.Forms Imports ESRI.ArcGIS.ADF.BaseClasses Imports ESRI.ArcGIS.ADF.CATIDs Imports ESRI.ArcGIS.Carto Imports ESRI.ArcGIS.Controls Imports ESRI.ArcGIS.esriSystem Imports ESRI.ArcGIS.Geodatabase Imports System.Diagnostics Namespace TabbedFeatureInspector '/ <summary> '/ A command that attaches/detaches the 'tabbed inspector' extension class from '/ the feature class selected in the table of contents. '/ In order to work correctly, the hosting application must implement and pass an '/ instance of IApplicationServices in the CustomProperty of its toolbar control. '/ </summary> <Guid("61B2CFFB-35DB-4aec-8DA2-C40C20C76901")> _ <ClassInterface(ClassInterfaceType.None)> _ <ProgId("TabbedFeatureInspectorVB.AttachTabbedInspectorExtensionCommand")> _ Public Class AttachTabbedInspectorExtensionCommand Inherits BaseCommand #Region "COM Registration Function(s)" <ComRegisterFunction()> _ <ComVisible(False)> _ Public Shared Sub RegisterFunction(ByVal registerType As Type) ' Required for ArcGIS Component Category Registrar support ArcGISCategoryRegistration(registerType) End Sub <ComUnregisterFunction()> _ <ComVisible(False)> _ Public Shared Sub UnregisterFunction(ByVal registerType As Type) ' Required for ArcGIS Component Category Registrar support ArcGISCategoryUnregistration(registerType) End Sub #Region "ArcGIS Component Category Registrar generated code" '/ <summary> '/ Required method for ArcGIS Component Category registration - '/ Do not modify the contents of this method with the code editor. '/ </summary> Private Shared Sub ArcGISCategoryRegistration(ByVal registerType As Type) Dim regKey As String = String.Format("HKEY_CLASSES_ROOT\CLSID\{{{0}}}", registerType.GUID) ControlsCommands.Register(regKey) End Sub '/ <summary> '/ Required method for ArcGIS Component Category unregistration - '/ Do not modify the contents of this method with the code editor. '/ </summary> Private Shared Sub ArcGISCategoryUnregistration(ByVal registerType As Type) Dim regKey As String = String.Format("HKEY_CLASSES_ROOT\CLSID\{{{0}}}", registerType.GUID) ControlsCommands.Unregister(regKey) End Sub #End Region #End Region Dim m_hookHelper As IHookHelper Dim m_appServices As IApplicationServices Dim workHelper As System.Windows.Forms.MethodInvoker = AddressOf Work Dim fc As IFeatureClass Dim succeeded As Boolean = False 'return value of the 'Work' delegate Public Sub New() m_category = "Developer Samples" m_caption = "Attach/Detach Tabbed Inspector Extension VB" m_message = "This command attaches or detaches the Tabbed Inspector class extension from the selected feature class." m_toolTip = "This command attaches or detaches the Tabbed Inspector class extension from the selected feature class." m_name = "TabbedInspector_AttachDetachExtension_VB" End Sub '/ <summary> '/ Occurs when this command is created '/ </summary> '/ <param name="hook">Instance of the application</param> Public Overrides Sub OnCreate(ByVal hook As Object) If hook Is Nothing Then Return End If m_hookHelper = New HookHelperClass() m_hookHelper.Hook = hook m_appServices = Nothing End Sub '/ <summary> '/ Occurs when this command is clicked '/ </summary> Public Overrides Sub OnClick() Try GetApplicationServices() Dim fl As IFeatureLayer = m_appServices.GetLayerSelectedInTOC() If Not fl Is Nothing Then fc = fl.FeatureClass AlterClassExtension() Else m_appServices.SetStatusMessage("Couldn't attach the 'custom inspector' extension. No feature layer was selected in the Table of Contents.", True) End If Catch ex As Exception MessageBox.Show("Error: Could open the feature class. Original error: " + ex.Message) End Try End Sub '/ <summary> '/ Obtains the IApplicationServices interface instance implemented by the hosting application. '/ This is needed so the command can determine the selected layer, and update the application's status message. '/ </summary> Private Sub GetApplicationServices() If m_appServices Is Nothing Then Dim toolbarControl As IToolbarControl2 = m_hookHelper.Hook If toolbarControl Is Nothing Then Throw New ApplicationException( _ "Command appears to be running in an unexpected environment. Its hookHelper ought to be a toolbar control.") End If m_appServices = toolbarControl.CustomProperty If m_appServices Is Nothing Then Throw New ApplicationException( _ "Command appears to be running in an unexpected environment. The toolbar custom property ought to be an instance of IApplicationServices.") End If End If End Sub '/ <summary> '/ Perform the work contained in the delegate inside an exclusive schema lock. '/ </summary> '/ <param name="fc">The feature class whose schema is to be exclusively locked.</param> '/ <param name="work">The work to be performed.</param> Shared Sub DoInSchemaLock(ByVal fc As IFeatureClass, ByVal work As MethodInvoker) Dim schemaLock As ISchemaLock = DirectCast(fc, ISchemaLock) Try ' Exclusively lock the class schema. schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock) ' Do the work inside the schema lock work() Finally ' Release the exclusive lock on the featureclass' schema. schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock) End Try End Sub '/ <summary> '/ This method attaches or detaches the "TabbedInspector" class extension to/from the specified '/ feature class. If the featureclass already has an extension class, and it isnt the 'TabbedInspector' extension, '/ the method does not modify the class extension. '/ </summary> '/ <param name="fc">The feature class to be altered.</param> '/ <returns>Whether the operation succeeded (successful detach or attach).</returns> Private Function AlterClassExtension() As Boolean ' Attempt to get access to schema-editing functionality on the feature class Dim classSchemaEdit As IClassSchemaEdit = TryCast(fc, IClassSchemaEdit) If classSchemaEdit Is Nothing Then m_appServices.SetStatusMessage("The selected feature class doesn't support attaching an extension class.", True) Return False End If ' Do the schema update within a schema lock. DoInSchemaLock(fc, workHelper) AlterClassExtension = succeeded End Function Public Sub Work() succeeded = False ' Attempt to get access to schema-editing functionality on the feature class Dim classSchemaEdit As IClassSchemaEdit = DirectCast(fc, IClassSchemaEdit) ' Create a UID object holding the TabbedInspector's CLSID Dim classUID As UID = New UIDClass() classUID.Value = "{" + TabbedInspectorCLSID.TabbedInspectorCLSID + "}" ' Does the feature class already have an extension class associated with it? If Not fc.EXTCLSID Is Nothing Then ' The featureclass already has an extension attached. If fc.EXTCLSID.Value.Equals(classUID.Value) Then ' The extension is the TabbedInspector extension. Detach it. classSchemaEdit.AlterClassExtensionCLSID(Nothing, Nothing) m_appServices.SetStatusMessage( _ String.Format("The 'custom inspector' extension class was detached from {0}.", fc.AliasName), False) succeeded = True Else 'Don't mess with featureclasses that have some other existing extension class associated with them. m_appServices.SetStatusMessage( _ String.Format("{0} already has another extension class attached to it. No change was made.", fc.AliasName), True) succeeded = False End If Else ' There is no extension attached to the featureclass. Attach the TabbedInspector extension. classSchemaEdit.AlterClassExtensionCLSID(classUID, Nothing) m_appServices.SetStatusMessage( _ String.Format("The 'custom inspector' extension class was attached to {0}.", fc.AliasName), False) succeeded = True End If End Sub End Class End Namespace