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