How to I get OpenQueryTable to work?

1038
9
01-25-2019 05:30 AM
BradJones3
Occasional Contributor

Trying this as a Question instead of a Discussion.

I'm having trouble getting a QueryTable to display.  The tool selects a single sewer line, gets the feature ID for the line (called COMPKEY), then uses the ID to build the where clause and hopefully open the query table. 

 

What am I missing?

 protected override Task<bool> OnSketchCompleteAsync(Geometry geometry)
        {
            Uri path = new Uri("O:\\P\\A\\T\\H\\CONNECTION.sde");
            return QueuedTask.Run(() =>
            {
                ActiveMapView.SelectFeatures(geometry, SelectionCombinationMethod.New);

                string slComp = Module1.GetCompkey();
                if (!string.IsNullOrEmpty(slComp))
                {
                    // Set up Geodatabase Object)
                    using (Geodatabase geodatabase = new Geodatabase(new DatabaseConnectionFile(path)))
                    {
                        string queryString = $"COMPKEY = {slComp}";
                        QueryDef queryDef = new QueryDef()
                        {
                            Tables = "SDE.TABLE.NAME",
                            WhereClause = queryString,
                        };

                        QueryTableDescription queryTableDescription = new QueryTableDescription(queryDef)
                        {
                            MakeCopy = true,
                            Name = $"Preventive Maintenance: {slComp}.",
                            PrimaryKeys = geodatabase.GetSQLSyntax().QualifyColumnName("SDE.sewerman.tblV8PMTOOL", "COMPKEY")
                        };

                        var queryTable = geodatabase.OpenQueryTable(queryTableDescription);

                        int count = queryTable.GetCount();
                        if (count == 0)
                        {
                            MessageBox.Show("Sewer line selected has no preventive maintenance scheduled.");
                        }

                        else
                        {
                            // Used since query table doesn't display
                            // MessageBox.Show($"Row count: {count}");
                        }
                    }
                };
0 Kudos
9 Replies
RichRuh
Esri Regular Contributor

Brad,

Do you know where this code is failing? Have you stepped through with a debugger to see the value of count?

You state: "I'm having trouble getting a QueryTable to display."  At the risk to taking your question too literally, you haven't included any code to display a QueryTable, just to create one.  Is that the issue?  (If so, do you want this to display as a table view or a layer on your map)

--Rich

0 Kudos
BradJones3
Occasional Contributor

Yes, that is the issue.  I couldn't find any snippits/examples on how to do this.

0 Kudos
RichRuh
Esri Regular Contributor

Brad-

I'm not an expert on using the ArcGIS Pro Content classes, but I think this code should do it:

// Create a standalone table from the queryTable Table
IStandaloneTableFactory tableFactory = StandaloneTableFactory.Instance;
StandaloneTable standaloneTable = tableFactory.CreateStandaloneTable(queryTable, MapView.Active.Map);

// Open the standalone table into a window
FrameworkApplication.Panes.OpenTablePane(standaloneTable, TableViewMode.eAllRecords);

--Rich

0 Kudos
BradJones3
Occasional Contributor

Thanks, for your help, Rich.  But the following method must be called on the UI thread. 

FrameworkApplication.Panes.OpenTablePane(standaloneTable, TableViewMode.eAllRecords);

OpenTablePane reference

0 Kudos
RichRuh
Esri Regular Contributor

That's correct, Brad.  You'll need to restructure your code so that the QueryTable is called on the MCT (main CIM thread) using QueuedTask, and you create the standalone table on the UI thread.

0 Kudos
BradJones3
Occasional Contributor

Unfortunately, because of my own inadequacies as a .Net developer, I can't figure out how to display—OpenTablePane— the standalone table from the UI thread.  I'm missing something. 

I think I'll try to do it in a DockPane.  It's not ideal for this situation, but there seems to be plenty of code examples for this.

Thanks for your help, Rich.

0 Kudos
CharlesMacleod
Esri Regular Contributor

Hi Brad, so here are some possibilities:

Option 1: Make the table and return the table from the QueuedTask and show it

internal class OpenTableButton : Button
    {
        protected async override void OnClick()
        {
            //capture the active map
            var theMap = MapView.Active.Map;

            //option 1 - return the table from the QueuedTask
            var table = await QueuedTask.Run(() =>
            {
                return StandaloneTableFactory.Instance.CreateStandaloneTable(
                    new Uri(@"Path_To_File_GDB.gdb\EarthquakeDamage_Table", 
                            UriKind.Absolute),
                    theMap);
            });
            FrameworkApplication.Panes.OpenTablePane(table);
        }
    }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Option 2: Make the table and show it from the QueuedTask (the syntax to do that is a bit gnarly I must confess)...still...it is here if you need it

internal class OpenTableButton : Button
    {
        protected async override void OnClick()
        {
            //capture the active map
            var theMap = MapView.Active.Map;

            //option 2 - invoke the OpenTablePane on the UI thread from
            //~within~ the QueuedTask
            await QueuedTask.Run(() =>
            {
                var table2 = StandaloneTableFactory.Instance.CreateStandaloneTable(
                    new Uri(@"Path_to_File_GDB.gdb\Meteorites_UK_Table",
                             UriKind.Absolute),
                    theMap);
                //now put us on the UI thread to open the table pane
                FrameworkApplication.Current.Dispatcher.BeginInvoke((Action)(() =>
                {
                    FrameworkApplication.Panes.OpenTablePane(table2);
                }));
            });

        }
    }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Option 3: Make the table on the QueuedTask. Return from the QueuedTask. Retrieve the table from the Map (on the UI) and show it. This would be akin to how you would retrieve a table from the TOC that had previously been added.

internal class OpenTableButton : Button
    {
        protected async override void OnClick()
        {
            //capture the active map
            var theMap = MapView.Active.Map;

            //Create the table from the QueuedTask
            await QueuedTask.Run(() =>
            {
                StandaloneTableFactory.Instance.CreateStandaloneTable(
                    new Uri(@"Path_To_File_GDB.gdb\EarthquakeDamage_Table", 
                    UriKind.Absolute),
                    theMap);
            });
            

            //option 3...get the table from the map after it has been added...
            var table3 = theMap.FindStandaloneTables("EarthquakeDamage_Table").First();
            FrameworkApplication.Panes.OpenTablePane(table3);
        }
    }
BradJones3
Occasional Contributor

Thanks for the snippets, Charles.  But the problem I was having was trying to open the table without the user having to go to the ribbon click another button.  I want them to click on a tool to activate, click on a feature, and the table opens with the subset of data.

Thanks for your help. 

0 Kudos
BradJones3
Occasional Contributor

I just want to point out that this was the solution I was looking for. 

I did not want the users to have to click a second bottom to open the table. I wanted it to run in OnSketchCompleteAsync method.  

        protected override async Task<bool> OnSketchCompleteAsync(Geometry geometry)
        {
            
            var standaloneTable =  await QueuedTask.Run(() =>
            {

                ActiveMapView.SelectFeatures(geometry, SelectionCombinationMethod.New);

                slComp = Module1.GetCompkey();
                if (!string.IsNullOrEmpty(slComp))
                {
                    Uri path = new Uri("\\P\\A\\T\\H.sde");

                    // Set up Geodatabase Object)
                    using (Geodatabase geodatabase = new Geodatabase(new DatabaseConnectionFile(path)))
                    {
                        string queryString = $"COMPKEY = {slComp}";
                        QueryDef queryDef = new QueryDef()
                        {
                            Tables = "SDE.sewerman.tblV8PMTOOL",
                            WhereClause = queryString,
                        };

                        QueryTableDescription queryTableDescription = new QueryTableDescription(queryDef)
                        {
                            MakeCopy = true,
                            Name = $"Preventive Maintenance: {slComp}",
                            PrimaryKeys = geodatabase.GetSQLSyntax().QualifyColumnName("SDE.CONNECTION", "COMPKEY")
                        };

                        var queryTable = geodatabase.OpenQueryTable(queryTableDescription);

                        int count = queryTable.GetCount();
                        if (count == 0)
                        {
                            MessageBox.Show("Sewer line selected has no preventive maintenance scheduled.");
                            
                        }

                        else
                        {
                            // Create a standalone table from the queryTable Table
                            IStandaloneTableFactory tableFactory = StandaloneTableFactory.Instance;
                            StandaloneTable pmTable = tableFactory.CreateStandaloneTable(queryTable, MapView.Active.Map);

                            return pmTable;
                        }                     
                    }
                };
                //return base.OnSketchCompleteAsync(geometry);
                return null;
            });
            // Open the standalone table pane
            FrameworkApplication.Panes.OpenTablePane(standaloneTable, TableViewMode.eAllRecords);
            return true;
        }