Retrieve records from related table in ArcGIS Runtime SDK for .NET

1627
20
Jump to solution
07-25-2017 07:01 AM
MiriEshel
New Contributor III

Hi everybody,

We are using ArcGIS Runtime 100.1 and we want to retrieve records from a related table in a FeatureService.

We are able to perform QueryRelatedFeaturesAsync and get the number of features by using NumberOfFeatures but we cannot find any method/property to retrieve the data itself.

Here is the code we are using:

// Select the features based on query parameters defined above
var selectedFeatures = await idLayer.SelectFeaturesAsync(queryParams, Esri.ArcGISRuntime.Mapping.SelectionMode.New);
var feature = selectedFeatures.First() as ArcGISFeature;
var relatedResult = await table.QueryRelatedFeaturesAsync(feature);
var relatedTbl = relatedResult[0].RelatedTable;

var num = relatedTbl.NumberOfFeatures;

What next??

Thanks a lot,

Miri

Reply
0 Kudos
1 Solution

Accepted Solutions
JenniferNery
Esri Regular Contributor

I'll answer your question with a sample. The basic idea is related tables all participate in the same map - whether it is another layer or a non-spatial table. You can get to the feature by identify/query. Once you have a feature, query its related features by either specifying specific relationship or getting all regardless of source.

        xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <esri:MapView x:Name="MyMapView" />
        <TreeView x:Name="Result" Grid.Column="1" >
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate  ItemsSource="{Binding}">
                    <TextBlock Text="{Binding RelatedTable.TableName}" />
                    <HierarchicalDataTemplate.ItemTemplate>
                        <DataTemplate>
                            <ItemsControl ItemsSource="{Binding Attributes}"
                                          Grid.Column="1">

                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <Grid>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition />
                                                <ColumnDefinition />
                                            </Grid.ColumnDefinitions>
                                            <TextBlock Text="{Binding Key, StringFormat={}{0} :}" />
                                            <TextBlock Text="{Binding Value, StringFormat={} {0}}"
                                                       Grid.Column="1" />

                                        </Grid>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </DataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

            MyMapView.GeoViewTapped += MyMapView_GeoViewTapped;
            MyMapView.Map = new Map(Basemap.CreateTopographic());
            MyMapView.Map.OperationalLayers.Add(new FeatureLayer(new Uri("https://services2.arcgis.com/ZQgQTuoyBrtmoGdP/ArcGIS/rest/services/AlaskaNationalParksPreservesSpeci...")));
            MyMapView.Map.OperationalLayers.Add(new FeatureLayer(new Uri("https://services2.arcgis.com/ZQgQTuoyBrtmoGdP/ArcGIS/rest/services/AlaskaNationalParksPreservesSpeci...")));
            MyMapView.Map.Tables.Add(new ServiceFeatureTable(new Uri("https://services2.arcgis.com/ZQgQTuoyBrtmoGdP/ArcGIS/rest/services/AlaskaNationalParksPreservesSpeci...")));

            MyMapView.Map.InitialViewpoint = new Viewpoint(new Envelope(-17677159.6926513, 7932123.08666798, -16355129.8191665, 9451936.95697339, SpatialReferences.WebMercator));
        }

        private async void MyMapView_GeoViewTapped(object sender, GeoViewInputEventArgs e)
        {
            var result = await MyMapView.IdentifyLayersAsync(e.Position, 2, false);
            foreach (var identifyResult in result)
            {
                if (identifyResult.LayerContent is FeatureLayer && ((FeatureLayer)identifyResult.LayerContent).FeatureTable is ArcGISFeatureTable)
                {

                    var table = (ArcGISFeatureTable)((FeatureLayer)identifyResult.LayerContent).FeatureTable;
                    foreach (ArcGISFeature feature in identifyResult.GeoElements)
                    {
                        var queryResults = await table.QueryRelatedFeaturesAsync(feature);                       
                        Result.ItemsSource = queryResults.ToArray();
                    }
                }
            }
        }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

Reply
0 Kudos
20 Replies
JenniferNery
Esri Regular Contributor

I'll answer your question with a sample. The basic idea is related tables all participate in the same map - whether it is another layer or a non-spatial table. You can get to the feature by identify/query. Once you have a feature, query its related features by either specifying specific relationship or getting all regardless of source.

        xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <esri:MapView x:Name="MyMapView" />
        <TreeView x:Name="Result" Grid.Column="1" >
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate  ItemsSource="{Binding}">
                    <TextBlock Text="{Binding RelatedTable.TableName}" />
                    <HierarchicalDataTemplate.ItemTemplate>
                        <DataTemplate>
                            <ItemsControl ItemsSource="{Binding Attributes}"
                                          Grid.Column="1">

                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <Grid>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition />
                                                <ColumnDefinition />
                                            </Grid.ColumnDefinitions>
                                            <TextBlock Text="{Binding Key, StringFormat={}{0} :}" />
                                            <TextBlock Text="{Binding Value, StringFormat={} {0}}"
                                                       Grid.Column="1" />

                                        </Grid>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </DataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

            MyMapView.GeoViewTapped += MyMapView_GeoViewTapped;
            MyMapView.Map = new Map(Basemap.CreateTopographic());
            MyMapView.Map.OperationalLayers.Add(new FeatureLayer(new Uri("https://services2.arcgis.com/ZQgQTuoyBrtmoGdP/ArcGIS/rest/services/AlaskaNationalParksPreservesSpeci...")));
            MyMapView.Map.OperationalLayers.Add(new FeatureLayer(new Uri("https://services2.arcgis.com/ZQgQTuoyBrtmoGdP/ArcGIS/rest/services/AlaskaNationalParksPreservesSpeci...")));
            MyMapView.Map.Tables.Add(new ServiceFeatureTable(new Uri("https://services2.arcgis.com/ZQgQTuoyBrtmoGdP/ArcGIS/rest/services/AlaskaNationalParksPreservesSpeci...")));

            MyMapView.Map.InitialViewpoint = new Viewpoint(new Envelope(-17677159.6926513, 7932123.08666798, -16355129.8191665, 9451936.95697339, SpatialReferences.WebMercator));
        }

        private async void MyMapView_GeoViewTapped(object sender, GeoViewInputEventArgs e)
        {
            var result = await MyMapView.IdentifyLayersAsync(e.Position, 2, false);
            foreach (var identifyResult in result)
            {
                if (identifyResult.LayerContent is FeatureLayer && ((FeatureLayer)identifyResult.LayerContent).FeatureTable is ArcGISFeatureTable)
                {

                    var table = (ArcGISFeatureTable)((FeatureLayer)identifyResult.LayerContent).FeatureTable;
                    foreach (ArcGISFeature feature in identifyResult.GeoElements)
                    {
                        var queryResults = await table.QueryRelatedFeaturesAsync(feature);                       
                        Result.ItemsSource = queryResults.ToArray();
                    }
                }
            }
        }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

Reply
0 Kudos
MiriEshel
New Contributor III

Hi Jennifer,

Thanks. It helped! We missed on ToArray() method.

Thanks again!

Miri

Reply
0 Kudos
ChadYoder1
Occasional Contributor II

Jennifer, thanks for the sample, but I'm a bit confused on how to actually implement what I need.

What I'm looking to do is actually be able to get the related features, and I expected the RelatedFeatureQueryResult.Feature property to be the related feature, but it is the original feature used to query the related records.

For example, I have owner data (point), which is related to a parcel (polygon), which is related to property data (table).

I get the owner data when a point is clicked on the map, so I have that feature.  That is used to call QueryRelatedFeaturesAsync.  What I want to be able to do is iterate the collection of RelatedFeatureQueryResult objects and get the property data, but I can't quite seem to figure out how to get the parcel feature object from this collection, so I can then get all of the records that are related to the parcel.

Any help would be appreciated, thanks.

Reply
0 Kudos
ChadYoder1
Occasional Contributor II

Jennifer, do you have a sample that works on iOS/Android/UWP?

I don't see that the RelatedFeatureQueryResult is a feature set, so not quite sure how to get to the feature/attributes in that collection.

Thanks.

Reply
0 Kudos
JenniferNery
Esri Regular Contributor

Hi, I'm sorry for the delay in reply. The IReadOnlyList<RelatedFeatureQueryResult>, result object from awaiting QueryRelatedFeaturesAsync, is a collection of iterator of features. In any platform, you can do something like this to access the related features and their attributes. In the original sample Result is a TreeView and individual template binds to table name and feature attributes. 

var queryResults = await table.QueryRelatedFeaturesAsync(feature);
var resultCollection = queryResults.ToArray();
foreach (var queryResult in resultCollection)
{
    foreach(var f in queryResult)
    {
        var sft = (ServiceFeatureTable)f.FeatureTable;
        var id = (long)f.Attributes[sft.ObjectIdField];
    }
}
Reply
0 Kudos
ChadYoder1
Occasional Contributor II

Thanks Jennifer, I managed to get this working with the help of minerjoe.

I didn't realize it was a collection within the collection, but I'm pleased that it is now working.

Thanks again.

Reply
0 Kudos
ChadYoder1
Occasional Contributor II

Jennifer, I'm finding that QueryRelatedFeaturesAsync() is not working with an offline database, at least one that is created as runtime content using ArcMap.

What are the requirements for the offline geodatabase to contain relationships?  Do it need to come from Pro?  

I'll try an offline replica next, and post back my results.

Reply
0 Kudos
ChadYoder1
Occasional Contributor II

Quick update: using an offline replica geodatabase works, just not a runtime content geodatabase (ArcMap, 10.4).

Reply
0 Kudos
ChadYoder1
Occasional Contributor II

MMPKs work as well, so it's just runtime content that relationships don't appear to be working.

The RelationshipInfos are there, but a call to QueryRelatedFeaturesAsync returns nothing.

Is this a bug or just not supported?

Thanks.

Reply
0 Kudos