Select to view content in your preferred language

IGxDialog filter problem with Personal vs. File geodatabases

3546
3
11-03-2010 01:41 PM
JeffreyHamblin
Occasional Contributor
I am working on code in C# (VS 2008 Express) to return an IFeatureClass from both Personal and File Geodatabases against ArcMap 10 using an AddIn. I am having a problem with filters and determining the type. If I set filters for both, I get the following in the dialog filters list:

File and Personal Geodatabases
File Geodatabases

Why is the first one both types instead of just Personal?

Second problem: The gxDialog.FinalLocation.Category always reports "Folder" no matter which type is selected. I've hacked around that by looking at the file extension instead. But, is there a better way to differentiate between File and Personal?

Here's the code (without the file ext hack). It will always report "Unsupported Category: Folder". With the hack it works fine:

private IFeatureClass GetFeatureClass()
{
    // Check if exists, and just return reference if it does
    string featureClassName = "Test_FC";

    // Setup the dialog to locate the db
    IGxDialog gxDialog = new GxDialogClass();
    IGxObjectFilter gxObjectFilter_PGDB = new GxFilterPersonalGeodatabasesClass();
    IGxObjectFilter gxObjectFilter_FGDB = new GxFilterFileGeodatabasesClass();
    IGxObjectFilterCollection gxObjectFilterCollection = (IGxObjectFilterCollection)gxDialog;
    gxObjectFilterCollection.AddFilter(gxObjectFilter_PGDB, true);
    gxObjectFilterCollection.AddFilter(gxObjectFilter_FGDB, false);

    gxDialog.Title = "Select the Project Geodatabase";

    if (gxDialog.DoModalSave(0))
    {
        string workspaceName = gxDialog.FinalLocation.FullName + "/" + gxDialog.Name;
        string workspaceCategory = gxDialog.FinalLocation.Category;
        //string workspaceCategory = System.IO.Path.GetExtension(gxDialog.Name).ToLower();

        ESRI.ArcGIS.Geodatabase.IWorkspaceFactory workspaceFactory;

        switch (workspaceCategory)
        {
            case "Personal Geodatabase":
            //case ".mdb":
                MessageBox.Show(featureClassName + "Detected Personal Geodatabase");
                workspaceFactory = new ESRI.ArcGIS.DataSourcesGDB.AccessWorkspaceFactoryClass();
                break;
            case "File Geodatabase":
            //case ".gdb":
                MessageBox.Show(featureClassName + "Detected File Geodatabase workspace");
                workspaceFactory = new ESRI.ArcGIS.DataSourcesGDB.FileGDBWorkspaceFactoryClass();
                break;
            default:
                MessageBox.Show("Unsupported Category: " + workspaceCategory);
                return null;
        }


        ESRI.ArcGIS.Geodatabase.IWorkspace workspace = workspaceFactory.OpenFromFile(workspaceName, 0);
        ESRI.ArcGIS.Geodatabase.IWorkspace2 workspace2 = (ESRI.ArcGIS.Geodatabase.IWorkspace2)workspace;

        ESRI.ArcGIS.Geodatabase.IFeatureWorkspace featureWorkspace = (ESRI.ArcGIS.Geodatabase.IFeatureWorkspace)workspace; // Explicit Cast

        if (workspace2.get_NameExists(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTFeatureClass, featureClassName))
        {
            ESRI.ArcGIS.Geodatabase.IFeatureClass featureClass = featureWorkspace.OpenFeatureClass(featureClassName);
            if (featureClass != null)
            {
                return featureClass;
            }
            else
            {
                MessageBox.Show(featureClassName + " feature class can't be opened. It may be in use by another application.");
                return null;
            }
        }
        else
        {
            MessageBox.Show(featureClassName + " feature class does not exist.");
            return null;
        }
    }
    else
    {
        MessageBox.Show("Dialog cancelled. Do nothing.");
        return null;
    }
}


Thanks for any help.

-Jeff Hamblin
3 Replies
NeilClemmons
Honored Contributor
I ran into the same thing.  I can't imagine why ESRI did this.  The good news is that creating your own custom filters is very simple.  You just implement the IGxObjectFilter interface.  Here's a class for a personal GDB filter:

Imports ESRI.ArcGIS.Catalog

<ComClass(GxFilterPersonalGDB.ClassId, GxFilterPersonalGDB.InterfaceId, GxFilterPersonalGDB.EventsId)> _
    Public Class GxFilterPersonalGDB
        Implements IGxObjectFilter

#Region "COM GUIDs"
        ' These  GUIDs provide the COM identity for this class 
        ' and its COM interfaces. If you change them, existing 
        ' clients will no longer be able to access the class.
        Public Const ClassId As String = "cd8263cc-235c-435c-b1c2-030907db0349"
        Public Const InterfaceId As String = "0029f6f3-0676-477d-8961-c514e2b59006"
        Public Const EventsId As String = "d69cfde3-abaf-4b98-b8e3-c7c48dae7912"
#End Region

        ' A creatable COM class must have a Public Sub New() 
        ' with no parameters, otherwise, the class will not be 
        ' registered in the COM registry and cannot be created 
        ' via CreateObject.
        Public Sub New()
            MyBase.New()
        End Sub

        Public Function CanChooseObject(ByVal [object] As ESRI.ArcGIS.Catalog.IGxObject, ByRef result As ESRI.ArcGIS.Catalog.esriDoubleClickResult) As Boolean Implements ESRI.ArcGIS.Catalog.IGxObjectFilter.CanChooseObject
            If Not TypeOf [object] Is IGxDatabase2 Then Return False
            Dim gxDatabase As IGxDatabase2 = DirectCast([object], IGxDatabase2)
            Return gxDatabase.Workspace.PathName.EndsWith(".mdb", StringComparison.CurrentCultureIgnoreCase)
        End Function

        Public Function CanDisplayObject(ByVal [object] As ESRI.ArcGIS.Catalog.IGxObject) As Boolean Implements ESRI.ArcGIS.Catalog.IGxObjectFilter.CanDisplayObject
            If TypeOf [object] Is IGxFolder Then Return True

            If Not TypeOf [object] Is IGxDatabase2 Then Return False
            Dim gxDatabase As IGxDatabase2 = DirectCast([object], IGxDatabase2)
            Return gxDatabase.Workspace.PathName.EndsWith(".mdb", StringComparison.CurrentCultureIgnoreCase)
        End Function

        Public Function CanSaveObject(ByVal Location As ESRI.ArcGIS.Catalog.IGxObject, ByVal newObjectName As String, ByRef objectAlreadyExists As Boolean) As Boolean Implements ESRI.ArcGIS.Catalog.IGxObjectFilter.CanSaveObject
            If Not TypeOf Location Is IGxDatabase2 Then Return False
            Dim gxDatabase As IGxDatabase2 = DirectCast(Location, IGxDatabase2)
            Return gxDatabase.Workspace.PathName.EndsWith(".mdb", StringComparison.CurrentCultureIgnoreCase)
        End Function

        Public ReadOnly Property Description() As String Implements ESRI.ArcGIS.Catalog.IGxObjectFilter.Description
            Get
                Return "Personal Geodatabases"
            End Get
        End Property

        Public ReadOnly Property Name() As String Implements ESRI.ArcGIS.Catalog.IGxObjectFilter.Name
            Get
                Return "Personal Geodatabases"
            End Get
        End Property
    End Class

0 Kudos
JohnNelson3
Occasional Contributor
Neil

Thank you for the code sample, the ESRI C# code wasn't very helpful (http://help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/index.html#//0014000001tt000000).  I include my C# code.

class GxFilterPersonalGDB : IGxObjectFilter
    {
        IGxObjectFilter basicFilter;
        IGxObjectFilter geoFilter;

        public GxFilterPersonalGDB()
        {
            //For Displaying Basic Types
            basicFilter = new GxFilterBasicTypes();
            //For Displaying Personal Geodatabases
            geoFilter = new GxFilterPersonalGeodatabases();
        }
      
        public bool CanChooseObject(IGxObject gxObject,ref esriDoubleClickResult result)
        {
            try
            {
                if (!(geoFilter.CanDisplayObject(gxObject)))
                {
                    return false;
                }
                IGxDatabase2 gxDatabase = gxObject as IGxDatabase2;
                return gxDatabase.Workspace.PathName.EndsWith(".mdb", StringComparison.CurrentCultureIgnoreCase);
            }
            catch
            {
                return false;
            }
        }

        public bool CanSaveObject(IGxObject gxObject, string newObjectName, ref bool objectAlreadyExists)
        {
            try
            {
                if (!(geoFilter.CanDisplayObject(gxObject)))
                {
                    return false;
                }
                IGxDatabase2 gxDatabase = gxObject as IGxDatabase2;
                return gxDatabase.Workspace.PathName.EndsWith(".mdb", StringComparison.CurrentCultureIgnoreCase);
            }
            catch
            {
                return false;
            }
        }

        public bool CanDisplayObject(IGxObject gxObject)
        {
            try
            {
                //Display Basic Types
                if (basicFilter.CanDisplayObject(gxObject))
                {
                    return true;
                }
                else if (!(geoFilter.CanDisplayObject(gxObject)))
                {
                    return false;
                }
                //Filter out File Geodatabases
                IGxDatabase2 gxDatabase = gxObject as IGxDatabase2;
                return gxDatabase.Workspace.PathName.EndsWith(".mdb", StringComparison.CurrentCultureIgnoreCase);
            }
            catch
            {
                return false;
            }
        }

        public string Name
        {
            get
            {
                return "Personal Geodatabase";
            }
        }

        public string Description
        {
            get
            {
                return "Personal Geodatabase";
            }
        }

    }
0 Kudos
YuriAvdoshin
New Contributor
Thank you, guys !
0 Kudos