Use branch versioned data

Use branch versioned data (a type of enterprise geodatabase versioning) when you want to provide multiuser editing in a service-oriented architecture (through feature services) and your users don't need direct access to the geodatabase. To compare versioning types, see Versioning types in the ArcGIS Pro documentation.

To use branch versioning in your app:

Branched versioned data can be edited offline the same way you edit feature services offline or use individual layers offline, as described in the Edit data from a branch version section.

Why use branch versioning

With branch versioning, editors can work within their own personal version of a geodatabase so that other users don't see incomplete work and editors don't block one another from accessing the data. Each version can represent ongoing work, such as a design or a group of work orders, work that can span multiple sessions and extend over a period of weeks or months if necessary.

Some common workflows for using branch versioned datasets include:

  • Multiuser editing, such as individual field crews working in their own branches
  • Modeling a variety of outcomes, with each scenario represented in its own branch
  • Editing and tracking different phases of a project

Set up and share versioned data

If you require multiple editors concurrently accessing services with the ability to work with their own set of edits, you must first register your data as branch versioned. When you share that dataset as a service, you have the option to enable the Version Management capability at the time of publishing, which allows for the creation and management of versions. For more information about setting up a database with branch versioning, see Register a dataset as branch versioned in the ArcGIS Pro documentation.

To edit branch versioned data, you must access it through a feature service. After registering data as branch versioned, publish the data to your organization's ArcGIS Enterprise portal as a web feature layer. Be sure you publish a layer that references registered data. The data will then be available as a feature service and you can edit it as part of your branch versioning workflows. For more information about how to share branch versioned data, see ArcGIS Pro help's Share branch versioned data.

Work with branch versions

In ArcGIS Runtime, use the ServiceGeodatabase class to represent a hosted geodatabase. You can create an instance of the class by providing the service URI and optionally the version name. You can also read the service geodatabase property from a service feature table.

A ServiceFeatureTable will have an associated ServiceGeodatabase if the feature table was loaded from a web map or if it was created from a service geodatabase (using ServiceGeodatabase.GetTable()). A standalone service feature table, created using any of the constructors, will not have access to a service geodatabase.

Use ServiceGeodatabase.GetVersionsAsync() to get information about the versions a service geodatabase contains that the current user has access to. The information includes the name, description, access level (private, protected, or public), creation date, and so on. You can create a new version by providing a name, description, and access level. You can access public and protected versions, and private versions you own. You cannot see information about, or connect to, private versions owned by other users.

The following steps show some common tasks when working with versions in a service geodatabase. These include getting the service geodatabase used by a feature layer, getting information about the current version, creating a new version, and switching the version used by the geodatabase to the new one.

  1. Get the service feature table from a feature layer in the map.

    Use dark colors for code blocks
                                                                                                                                                                                                                                                                                     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    // --- Edit ---
    
    private async void AddFeature(MapPoint structureLocation, string type, string cause)
    {
        // Create attributes for the feature.
        Dictionary<string, object> attributes = new Dictionary<string, object>();
        attributes.Add("typdamage", type);
        attributes.Add("primcause", cause);
    
        // Create a new feature from the attributes and the point.
        Feature newFeature = _damagePointsTable.CreateFeature(attributes, structureLocation);
    
        // Add the feature to the local table.
        await _damagePointsTable.AddFeatureAsync(newFeature);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void UpdateFeature(ArcGISFeature arcgisFeature)
    {
        // Change the feature's attribute value.
        arcgisFeature.Attributes["typdamage"] = "Inaccessible";
    
        // Change the feature's geometry.
        MapPoint location = arcgisFeature.Geometry as MapPoint;
        MapPoint newLocation = new MapPoint(location.X, location.Y + 50000);
        arcgisFeature.Geometry = newLocation;
    
        // Update the feature on the local table.
        await _damagePointsTable.UpdateFeatureAsync(f);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void DeleteSelectedFeatures(FeatureLayer damageLayer)
    {
        // Get all selected features in the layer.
        FeatureQueryResult selectedFeatures = await damageLayer.GetSelectedFeaturesAsync();
    
        // Delete the selected features.
        await _damagePointsTable.DeleteFeaturesAsync(selectedFeatures);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    // If the feature table is a service feature table, send these edits
    // to the online service by applying them to its service geodatabase.
    EditResult editResults = await table.ServiceGeodatabase.ApplyEditsAsync();
    
    
    // --- Query ---
    
    
    // Build a buffer (polygon) around a click point
    var buffer = GeometryEngine.Buffer(queryPoint, 5000);
    
    // Use the buffer to define the geometry for a query
    var query = new QueryParameters();
    query.Geometry = buffer;
    query.SpatialRelationship = SpatialRelationship.Contains;
    
    // Select features in a feature layer using the query
    await damageLayer.SelectFeaturesAsync(query, Esri.ArcGISRuntime.Mapping.SelectionMode.New);
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    var layer = MyMapView.Map.OperationalLayers[0];
    var pixelTolerance = 20;
    var returnPopupsOnly = false;
    var maxResults = 5;
    
    // identify a layer using MapView, passing in the layer, the tap point, tolerance, types to return, and max results
    IdentifyLayerResult idResults = await MyMapView.IdentifyLayerAsync(layer, tapScreenPoint, pixelTolerance, returnPopupsOnly, maxResults);
    
    // get the layer identified and cast it to FeatureLayer
    FeatureLayer idLayer = idResults.LayerContent as FeatureLayer;
    
    // iterate each identified GeoElement in the results
    foreach (GeoElement idElement in idResults.GeoElements)
    {
        // cast the result GeoElement to Feature
        Feature idFeature = idElement as Feature;
    
        // select this feature in the feature layer
        idLayer.SelectFeature(idFeature);
    }
    
    
    // -- BRANCH VERSIONING --//
    
    
        // Get the feature table from a feature layer and cast it to ServiceFeatureTable
        // (if the table is not a ServiceFeatureTable, it will be null)
        ServiceFeatureTable table = layer.FeatureTable as ServiceFeatureTable;
    
    
    
        // If the feature table is a ServiceFeatureTable, see if it has a service geodatabase
        if (table != null)
        {
            ServiceGeodatabase serviceGdb = table.ServiceGeodatabase;
            if(serviceGdb != null)
            {
                // Load the service geodatabase if necessary
                if (serviceGdb.LoadStatus != LoadStatus.Loaded)
                {
                    await serviceGdb.LoadAsync();
                }
    
    
    
        // (continued from above)
                // See if the service geodatabase supports branch versioning
                if (serviceGdb.SupportsBranchVersioning)
                {
                    // Get the versions contained in the service geodatabase
                    IReadOnlyList versions = await serviceGdb.GetVersionsAsync();
    
                    // Get the info for the current version and read its description
                    ServiceVersionInfo thisVersionInfo = versions.First(v => v.Name == serviceGdb.VersionName);
                    string versionDesc = thisVersionInfo.Description;
    
    
    
        // (continued from above)
                    // Create service version parameters to define a new private version
                    var versionParams = new ServiceVersionParameters()
                    {
                        Access = VersionAccess.Private,
                        Name = "DesignTwo",
                        Description = "Experimenting with an alternate design"
                    };
    
    
    
        // (continued from above)
                    // Use the parameters to create a new version in the service geodatabase
                    var designTwoVersion = await serviceGdb.CreateVersionAsync(versionParams);
    
                    // Switch the version used in the map to the new one
                    await serviceGdb.SwitchVersionAsync(designTwoVersion.Name);
                }
            }
    
    
    
        // Create a new feature and define its geometry and attributes
        Feature feature = table.CreateFeature();
        feature.Geometry = featureLocation;
        feature.SetAttributeValue("CITY", "Chula Vista");
    
        // Add the new feature to the local table
        await table.AddFeatureAsync(feature);
    
        // Delete some features
        var cityFeatures = await table.QueryFeaturesAsync(new QueryParameters { WhereClause = "CITY='National City'" });
        await table.DeleteFeaturesAsync(cityFeatures);
    
    
    
        // See which tables are from the service geodatabase
        IReadOnlyList serviceTables = serviceGdb.ConnectedTables;
    
    
    
        if (serviceGdb.HasLocalEdits())
        {
            // Apply local edits for all connected tables to the service
            await serviceGdb.ApplyEditsAsync();
        }
    
    
    
        // Undo all local edits for the version
        await serviceGeodabase.UndoLocalEditsAsync();
    
    
    
    // -- CONTINGENT VALUES --//
    
    
        // Store a list of values from the contingent values definition.
        var availableValues = new List<CodedValue>();
    
        // Get all contingent values defined for a specified field name.
        // The attribute values of the feature determine which contingent values are returned.
        var contingentValuesResult = polesFeatureTable.GetContingentValues(inFeature, "Material");
    
        // Get contingent values for a specified field group.
        var contingentValuesList = contingentValuesResult.ContingentValuesByFieldGroup["voltage_material"];
        // You can use code like this to get contingent values for all field groups if this field participates in more than one.
        // var contingentValuesList = contingentValuesResult.ContingentValuesAllGroups;
    
        // Loop through the contingent values and add the coded values to a list.
        foreach(var cv in contingentValuesList)
        {
            var contingentCodedValue = cv as ContingentCodedValue;
            if(contingentCodedValue != null)
            {
                availableValues.Add(contingentCodedValue.CodedValue);
            }
        }
    
    
    
        // Check for ContingentAnyValue (which means any value in the domain is valid).
        var contingentAnyValue = cv as ContingentAnyValue;
        if (contingentAnyValue != null)
        {
            // Add all values from the field's domain.
            var domain = _featureTableCV.GetField(fieldName)?.Domain as CodedValueDomain;
            if (domain != null)
            {
                availableValues.AddRange(domain.CodedValues);
            }
        }
    
    
    
        var contingentRangeValue = cv as ContingentRangeValue;
        if (contingentRangeValue != null)
        {
            (Int16 Min, Int16 Max) rangeTuple = ((Int16)contingentRangeValue.MinValue, (Int16)contingentRangeValue.MaxValue);
        }
    
    
    
        var contingentValueViolations = editFeatureTable.ValidateContingencyConstraints(newFeature);
    
        // If there are no violations, enable the save button and return.
        if (contingentValueViolations.Count == 0)
        {
            ValidateContingentValuesButton.IsEnabled = false;
            SaveFeatureButton.IsEnabled = true;
            return;
        }
    
        // Loop through contingency violations and show messages for errors and warnings.
        // Include the name of the field group that had the violation.
        foreach(var violation in contingentValueViolations)
        {
            // Show the appropriate icon: an error (red X) or warning (yellow exclamation).
            MessageBoxImage messageIcon = violation.Type == ContingencyConstraintViolationType.Error ?
                                            MessageBoxImage.Error : MessageBoxImage.Warning;
            MessageBox.Show("Contingency value violation for field group '" + violation.FieldGroup.Name + "'",
                            "Violation",
                            MessageBoxButton.OK,
                            messageIcon);
        }
    
  2. Get the service geodatabase from the service feature table. Make sure the service geodatabase is loaded. Loading the service feature table will also load its service geodatabase.

    Use dark colors for code blocks
                                                                                                                                                                                                                                                                                     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    // --- Edit ---
    
    private async void AddFeature(MapPoint structureLocation, string type, string cause)
    {
        // Create attributes for the feature.
        Dictionary<string, object> attributes = new Dictionary<string, object>();
        attributes.Add("typdamage", type);
        attributes.Add("primcause", cause);
    
        // Create a new feature from the attributes and the point.
        Feature newFeature = _damagePointsTable.CreateFeature(attributes, structureLocation);
    
        // Add the feature to the local table.
        await _damagePointsTable.AddFeatureAsync(newFeature);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void UpdateFeature(ArcGISFeature arcgisFeature)
    {
        // Change the feature's attribute value.
        arcgisFeature.Attributes["typdamage"] = "Inaccessible";
    
        // Change the feature's geometry.
        MapPoint location = arcgisFeature.Geometry as MapPoint;
        MapPoint newLocation = new MapPoint(location.X, location.Y + 50000);
        arcgisFeature.Geometry = newLocation;
    
        // Update the feature on the local table.
        await _damagePointsTable.UpdateFeatureAsync(f);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void DeleteSelectedFeatures(FeatureLayer damageLayer)
    {
        // Get all selected features in the layer.
        FeatureQueryResult selectedFeatures = await damageLayer.GetSelectedFeaturesAsync();
    
        // Delete the selected features.
        await _damagePointsTable.DeleteFeaturesAsync(selectedFeatures);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    // If the feature table is a service feature table, send these edits
    // to the online service by applying them to its service geodatabase.
    EditResult editResults = await table.ServiceGeodatabase.ApplyEditsAsync();
    
    
    // --- Query ---
    
    
    // Build a buffer (polygon) around a click point
    var buffer = GeometryEngine.Buffer(queryPoint, 5000);
    
    // Use the buffer to define the geometry for a query
    var query = new QueryParameters();
    query.Geometry = buffer;
    query.SpatialRelationship = SpatialRelationship.Contains;
    
    // Select features in a feature layer using the query
    await damageLayer.SelectFeaturesAsync(query, Esri.ArcGISRuntime.Mapping.SelectionMode.New);
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    var layer = MyMapView.Map.OperationalLayers[0];
    var pixelTolerance = 20;
    var returnPopupsOnly = false;
    var maxResults = 5;
    
    // identify a layer using MapView, passing in the layer, the tap point, tolerance, types to return, and max results
    IdentifyLayerResult idResults = await MyMapView.IdentifyLayerAsync(layer, tapScreenPoint, pixelTolerance, returnPopupsOnly, maxResults);
    
    // get the layer identified and cast it to FeatureLayer
    FeatureLayer idLayer = idResults.LayerContent as FeatureLayer;
    
    // iterate each identified GeoElement in the results
    foreach (GeoElement idElement in idResults.GeoElements)
    {
        // cast the result GeoElement to Feature
        Feature idFeature = idElement as Feature;
    
        // select this feature in the feature layer
        idLayer.SelectFeature(idFeature);
    }
    
    
    // -- BRANCH VERSIONING --//
    
    
        // Get the feature table from a feature layer and cast it to ServiceFeatureTable
        // (if the table is not a ServiceFeatureTable, it will be null)
        ServiceFeatureTable table = layer.FeatureTable as ServiceFeatureTable;
    
    
    
        // If the feature table is a ServiceFeatureTable, see if it has a service geodatabase
        if (table != null)
        {
            ServiceGeodatabase serviceGdb = table.ServiceGeodatabase;
            if(serviceGdb != null)
            {
                // Load the service geodatabase if necessary
                if (serviceGdb.LoadStatus != LoadStatus.Loaded)
                {
                    await serviceGdb.LoadAsync();
                }
    
    
    
        // (continued from above)
                // See if the service geodatabase supports branch versioning
                if (serviceGdb.SupportsBranchVersioning)
                {
                    // Get the versions contained in the service geodatabase
                    IReadOnlyList versions = await serviceGdb.GetVersionsAsync();
    
                    // Get the info for the current version and read its description
                    ServiceVersionInfo thisVersionInfo = versions.First(v => v.Name == serviceGdb.VersionName);
                    string versionDesc = thisVersionInfo.Description;
    
    
    
        // (continued from above)
                    // Create service version parameters to define a new private version
                    var versionParams = new ServiceVersionParameters()
                    {
                        Access = VersionAccess.Private,
                        Name = "DesignTwo",
                        Description = "Experimenting with an alternate design"
                    };
    
    
    
        // (continued from above)
                    // Use the parameters to create a new version in the service geodatabase
                    var designTwoVersion = await serviceGdb.CreateVersionAsync(versionParams);
    
                    // Switch the version used in the map to the new one
                    await serviceGdb.SwitchVersionAsync(designTwoVersion.Name);
                }
            }
    
    
    
        // Create a new feature and define its geometry and attributes
        Feature feature = table.CreateFeature();
        feature.Geometry = featureLocation;
        feature.SetAttributeValue("CITY", "Chula Vista");
    
        // Add the new feature to the local table
        await table.AddFeatureAsync(feature);
    
        // Delete some features
        var cityFeatures = await table.QueryFeaturesAsync(new QueryParameters { WhereClause = "CITY='National City'" });
        await table.DeleteFeaturesAsync(cityFeatures);
    
    
    
        // See which tables are from the service geodatabase
        IReadOnlyList serviceTables = serviceGdb.ConnectedTables;
    
    
    
        if (serviceGdb.HasLocalEdits())
        {
            // Apply local edits for all connected tables to the service
            await serviceGdb.ApplyEditsAsync();
        }
    
    
    
        // Undo all local edits for the version
        await serviceGeodabase.UndoLocalEditsAsync();
    
    
    
    // -- CONTINGENT VALUES --//
    
    
        // Store a list of values from the contingent values definition.
        var availableValues = new List<CodedValue>();
    
        // Get all contingent values defined for a specified field name.
        // The attribute values of the feature determine which contingent values are returned.
        var contingentValuesResult = polesFeatureTable.GetContingentValues(inFeature, "Material");
    
        // Get contingent values for a specified field group.
        var contingentValuesList = contingentValuesResult.ContingentValuesByFieldGroup["voltage_material"];
        // You can use code like this to get contingent values for all field groups if this field participates in more than one.
        // var contingentValuesList = contingentValuesResult.ContingentValuesAllGroups;
    
        // Loop through the contingent values and add the coded values to a list.
        foreach(var cv in contingentValuesList)
        {
            var contingentCodedValue = cv as ContingentCodedValue;
            if(contingentCodedValue != null)
            {
                availableValues.Add(contingentCodedValue.CodedValue);
            }
        }
    
    
    
        // Check for ContingentAnyValue (which means any value in the domain is valid).
        var contingentAnyValue = cv as ContingentAnyValue;
        if (contingentAnyValue != null)
        {
            // Add all values from the field's domain.
            var domain = _featureTableCV.GetField(fieldName)?.Domain as CodedValueDomain;
            if (domain != null)
            {
                availableValues.AddRange(domain.CodedValues);
            }
        }
    
    
    
        var contingentRangeValue = cv as ContingentRangeValue;
        if (contingentRangeValue != null)
        {
            (Int16 Min, Int16 Max) rangeTuple = ((Int16)contingentRangeValue.MinValue, (Int16)contingentRangeValue.MaxValue);
        }
    
    
    
        var contingentValueViolations = editFeatureTable.ValidateContingencyConstraints(newFeature);
    
        // If there are no violations, enable the save button and return.
        if (contingentValueViolations.Count == 0)
        {
            ValidateContingentValuesButton.IsEnabled = false;
            SaveFeatureButton.IsEnabled = true;
            return;
        }
    
        // Loop through contingency violations and show messages for errors and warnings.
        // Include the name of the field group that had the violation.
        foreach(var violation in contingentValueViolations)
        {
            // Show the appropriate icon: an error (red X) or warning (yellow exclamation).
            MessageBoxImage messageIcon = violation.Type == ContingencyConstraintViolationType.Error ?
                                            MessageBoxImage.Error : MessageBoxImage.Warning;
            MessageBox.Show("Contingency value violation for field group '" + violation.FieldGroup.Name + "'",
                            "Violation",
                            MessageBoxButton.OK,
                            messageIcon);
        }
    
  3. See if the service geodatabase supports branch versioning. If it does, get a list of its versions and information about the current version.

    Use dark colors for code blocks
                                                                                                                                                                                                                                                                                     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    // --- Edit ---
    
    private async void AddFeature(MapPoint structureLocation, string type, string cause)
    {
        // Create attributes for the feature.
        Dictionary<string, object> attributes = new Dictionary<string, object>();
        attributes.Add("typdamage", type);
        attributes.Add("primcause", cause);
    
        // Create a new feature from the attributes and the point.
        Feature newFeature = _damagePointsTable.CreateFeature(attributes, structureLocation);
    
        // Add the feature to the local table.
        await _damagePointsTable.AddFeatureAsync(newFeature);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void UpdateFeature(ArcGISFeature arcgisFeature)
    {
        // Change the feature's attribute value.
        arcgisFeature.Attributes["typdamage"] = "Inaccessible";
    
        // Change the feature's geometry.
        MapPoint location = arcgisFeature.Geometry as MapPoint;
        MapPoint newLocation = new MapPoint(location.X, location.Y + 50000);
        arcgisFeature.Geometry = newLocation;
    
        // Update the feature on the local table.
        await _damagePointsTable.UpdateFeatureAsync(f);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void DeleteSelectedFeatures(FeatureLayer damageLayer)
    {
        // Get all selected features in the layer.
        FeatureQueryResult selectedFeatures = await damageLayer.GetSelectedFeaturesAsync();
    
        // Delete the selected features.
        await _damagePointsTable.DeleteFeaturesAsync(selectedFeatures);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    // If the feature table is a service feature table, send these edits
    // to the online service by applying them to its service geodatabase.
    EditResult editResults = await table.ServiceGeodatabase.ApplyEditsAsync();
    
    
    // --- Query ---
    
    
    // Build a buffer (polygon) around a click point
    var buffer = GeometryEngine.Buffer(queryPoint, 5000);
    
    // Use the buffer to define the geometry for a query
    var query = new QueryParameters();
    query.Geometry = buffer;
    query.SpatialRelationship = SpatialRelationship.Contains;
    
    // Select features in a feature layer using the query
    await damageLayer.SelectFeaturesAsync(query, Esri.ArcGISRuntime.Mapping.SelectionMode.New);
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    var layer = MyMapView.Map.OperationalLayers[0];
    var pixelTolerance = 20;
    var returnPopupsOnly = false;
    var maxResults = 5;
    
    // identify a layer using MapView, passing in the layer, the tap point, tolerance, types to return, and max results
    IdentifyLayerResult idResults = await MyMapView.IdentifyLayerAsync(layer, tapScreenPoint, pixelTolerance, returnPopupsOnly, maxResults);
    
    // get the layer identified and cast it to FeatureLayer
    FeatureLayer idLayer = idResults.LayerContent as FeatureLayer;
    
    // iterate each identified GeoElement in the results
    foreach (GeoElement idElement in idResults.GeoElements)
    {
        // cast the result GeoElement to Feature
        Feature idFeature = idElement as Feature;
    
        // select this feature in the feature layer
        idLayer.SelectFeature(idFeature);
    }
    
    
    // -- BRANCH VERSIONING --//
    
    
        // Get the feature table from a feature layer and cast it to ServiceFeatureTable
        // (if the table is not a ServiceFeatureTable, it will be null)
        ServiceFeatureTable table = layer.FeatureTable as ServiceFeatureTable;
    
    
    
        // If the feature table is a ServiceFeatureTable, see if it has a service geodatabase
        if (table != null)
        {
            ServiceGeodatabase serviceGdb = table.ServiceGeodatabase;
            if(serviceGdb != null)
            {
                // Load the service geodatabase if necessary
                if (serviceGdb.LoadStatus != LoadStatus.Loaded)
                {
                    await serviceGdb.LoadAsync();
                }
    
    
    
        // (continued from above)
                // See if the service geodatabase supports branch versioning
                if (serviceGdb.SupportsBranchVersioning)
                {
                    // Get the versions contained in the service geodatabase
                    IReadOnlyList versions = await serviceGdb.GetVersionsAsync();
    
                    // Get the info for the current version and read its description
                    ServiceVersionInfo thisVersionInfo = versions.First(v => v.Name == serviceGdb.VersionName);
                    string versionDesc = thisVersionInfo.Description;
    
    
    
        // (continued from above)
                    // Create service version parameters to define a new private version
                    var versionParams = new ServiceVersionParameters()
                    {
                        Access = VersionAccess.Private,
                        Name = "DesignTwo",
                        Description = "Experimenting with an alternate design"
                    };
    
    
    
        // (continued from above)
                    // Use the parameters to create a new version in the service geodatabase
                    var designTwoVersion = await serviceGdb.CreateVersionAsync(versionParams);
    
                    // Switch the version used in the map to the new one
                    await serviceGdb.SwitchVersionAsync(designTwoVersion.Name);
                }
            }
    
    
    
        // Create a new feature and define its geometry and attributes
        Feature feature = table.CreateFeature();
        feature.Geometry = featureLocation;
        feature.SetAttributeValue("CITY", "Chula Vista");
    
        // Add the new feature to the local table
        await table.AddFeatureAsync(feature);
    
        // Delete some features
        var cityFeatures = await table.QueryFeaturesAsync(new QueryParameters { WhereClause = "CITY='National City'" });
        await table.DeleteFeaturesAsync(cityFeatures);
    
    
    
        // See which tables are from the service geodatabase
        IReadOnlyList serviceTables = serviceGdb.ConnectedTables;
    
    
    
        if (serviceGdb.HasLocalEdits())
        {
            // Apply local edits for all connected tables to the service
            await serviceGdb.ApplyEditsAsync();
        }
    
    
    
        // Undo all local edits for the version
        await serviceGeodabase.UndoLocalEditsAsync();
    
    
    
    // -- CONTINGENT VALUES --//
    
    
        // Store a list of values from the contingent values definition.
        var availableValues = new List<CodedValue>();
    
        // Get all contingent values defined for a specified field name.
        // The attribute values of the feature determine which contingent values are returned.
        var contingentValuesResult = polesFeatureTable.GetContingentValues(inFeature, "Material");
    
        // Get contingent values for a specified field group.
        var contingentValuesList = contingentValuesResult.ContingentValuesByFieldGroup["voltage_material"];
        // You can use code like this to get contingent values for all field groups if this field participates in more than one.
        // var contingentValuesList = contingentValuesResult.ContingentValuesAllGroups;
    
        // Loop through the contingent values and add the coded values to a list.
        foreach(var cv in contingentValuesList)
        {
            var contingentCodedValue = cv as ContingentCodedValue;
            if(contingentCodedValue != null)
            {
                availableValues.Add(contingentCodedValue.CodedValue);
            }
        }
    
    
    
        // Check for ContingentAnyValue (which means any value in the domain is valid).
        var contingentAnyValue = cv as ContingentAnyValue;
        if (contingentAnyValue != null)
        {
            // Add all values from the field's domain.
            var domain = _featureTableCV.GetField(fieldName)?.Domain as CodedValueDomain;
            if (domain != null)
            {
                availableValues.AddRange(domain.CodedValues);
            }
        }
    
    
    
        var contingentRangeValue = cv as ContingentRangeValue;
        if (contingentRangeValue != null)
        {
            (Int16 Min, Int16 Max) rangeTuple = ((Int16)contingentRangeValue.MinValue, (Int16)contingentRangeValue.MaxValue);
        }
    
    
    
        var contingentValueViolations = editFeatureTable.ValidateContingencyConstraints(newFeature);
    
        // If there are no violations, enable the save button and return.
        if (contingentValueViolations.Count == 0)
        {
            ValidateContingentValuesButton.IsEnabled = false;
            SaveFeatureButton.IsEnabled = true;
            return;
        }
    
        // Loop through contingency violations and show messages for errors and warnings.
        // Include the name of the field group that had the violation.
        foreach(var violation in contingentValueViolations)
        {
            // Show the appropriate icon: an error (red X) or warning (yellow exclamation).
            MessageBoxImage messageIcon = violation.Type == ContingencyConstraintViolationType.Error ?
                                            MessageBoxImage.Error : MessageBoxImage.Warning;
            MessageBox.Show("Contingency value violation for field group '" + violation.FieldGroup.Name + "'",
                            "Violation",
                            MessageBoxButton.OK,
                            messageIcon);
        }
    
  4. Create service version parameters that define properties for a new version: a name, description, and access level.

    Use dark colors for code blocks
                                                                                                                                                                                                                                                                                     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    // --- Edit ---
    
    private async void AddFeature(MapPoint structureLocation, string type, string cause)
    {
        // Create attributes for the feature.
        Dictionary<string, object> attributes = new Dictionary<string, object>();
        attributes.Add("typdamage", type);
        attributes.Add("primcause", cause);
    
        // Create a new feature from the attributes and the point.
        Feature newFeature = _damagePointsTable.CreateFeature(attributes, structureLocation);
    
        // Add the feature to the local table.
        await _damagePointsTable.AddFeatureAsync(newFeature);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void UpdateFeature(ArcGISFeature arcgisFeature)
    {
        // Change the feature's attribute value.
        arcgisFeature.Attributes["typdamage"] = "Inaccessible";
    
        // Change the feature's geometry.
        MapPoint location = arcgisFeature.Geometry as MapPoint;
        MapPoint newLocation = new MapPoint(location.X, location.Y + 50000);
        arcgisFeature.Geometry = newLocation;
    
        // Update the feature on the local table.
        await _damagePointsTable.UpdateFeatureAsync(f);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void DeleteSelectedFeatures(FeatureLayer damageLayer)
    {
        // Get all selected features in the layer.
        FeatureQueryResult selectedFeatures = await damageLayer.GetSelectedFeaturesAsync();
    
        // Delete the selected features.
        await _damagePointsTable.DeleteFeaturesAsync(selectedFeatures);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    // If the feature table is a service feature table, send these edits
    // to the online service by applying them to its service geodatabase.
    EditResult editResults = await table.ServiceGeodatabase.ApplyEditsAsync();
    
    
    // --- Query ---
    
    
    // Build a buffer (polygon) around a click point
    var buffer = GeometryEngine.Buffer(queryPoint, 5000);
    
    // Use the buffer to define the geometry for a query
    var query = new QueryParameters();
    query.Geometry = buffer;
    query.SpatialRelationship = SpatialRelationship.Contains;
    
    // Select features in a feature layer using the query
    await damageLayer.SelectFeaturesAsync(query, Esri.ArcGISRuntime.Mapping.SelectionMode.New);
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    var layer = MyMapView.Map.OperationalLayers[0];
    var pixelTolerance = 20;
    var returnPopupsOnly = false;
    var maxResults = 5;
    
    // identify a layer using MapView, passing in the layer, the tap point, tolerance, types to return, and max results
    IdentifyLayerResult idResults = await MyMapView.IdentifyLayerAsync(layer, tapScreenPoint, pixelTolerance, returnPopupsOnly, maxResults);
    
    // get the layer identified and cast it to FeatureLayer
    FeatureLayer idLayer = idResults.LayerContent as FeatureLayer;
    
    // iterate each identified GeoElement in the results
    foreach (GeoElement idElement in idResults.GeoElements)
    {
        // cast the result GeoElement to Feature
        Feature idFeature = idElement as Feature;
    
        // select this feature in the feature layer
        idLayer.SelectFeature(idFeature);
    }
    
    
    // -- BRANCH VERSIONING --//
    
    
        // Get the feature table from a feature layer and cast it to ServiceFeatureTable
        // (if the table is not a ServiceFeatureTable, it will be null)
        ServiceFeatureTable table = layer.FeatureTable as ServiceFeatureTable;
    
    
    
        // If the feature table is a ServiceFeatureTable, see if it has a service geodatabase
        if (table != null)
        {
            ServiceGeodatabase serviceGdb = table.ServiceGeodatabase;
            if(serviceGdb != null)
            {
                // Load the service geodatabase if necessary
                if (serviceGdb.LoadStatus != LoadStatus.Loaded)
                {
                    await serviceGdb.LoadAsync();
                }
    
    
    
        // (continued from above)
                // See if the service geodatabase supports branch versioning
                if (serviceGdb.SupportsBranchVersioning)
                {
                    // Get the versions contained in the service geodatabase
                    IReadOnlyList versions = await serviceGdb.GetVersionsAsync();
    
                    // Get the info for the current version and read its description
                    ServiceVersionInfo thisVersionInfo = versions.First(v => v.Name == serviceGdb.VersionName);
                    string versionDesc = thisVersionInfo.Description;
    
    
    
        // (continued from above)
                    // Create service version parameters to define a new private version
                    var versionParams = new ServiceVersionParameters()
                    {
                        Access = VersionAccess.Private,
                        Name = "DesignTwo",
                        Description = "Experimenting with an alternate design"
                    };
    
    
    
        // (continued from above)
                    // Use the parameters to create a new version in the service geodatabase
                    var designTwoVersion = await serviceGdb.CreateVersionAsync(versionParams);
    
                    // Switch the version used in the map to the new one
                    await serviceGdb.SwitchVersionAsync(designTwoVersion.Name);
                }
            }
    
    
    
        // Create a new feature and define its geometry and attributes
        Feature feature = table.CreateFeature();
        feature.Geometry = featureLocation;
        feature.SetAttributeValue("CITY", "Chula Vista");
    
        // Add the new feature to the local table
        await table.AddFeatureAsync(feature);
    
        // Delete some features
        var cityFeatures = await table.QueryFeaturesAsync(new QueryParameters { WhereClause = "CITY='National City'" });
        await table.DeleteFeaturesAsync(cityFeatures);
    
    
    
        // See which tables are from the service geodatabase
        IReadOnlyList serviceTables = serviceGdb.ConnectedTables;
    
    
    
        if (serviceGdb.HasLocalEdits())
        {
            // Apply local edits for all connected tables to the service
            await serviceGdb.ApplyEditsAsync();
        }
    
    
    
        // Undo all local edits for the version
        await serviceGeodabase.UndoLocalEditsAsync();
    
    
    
    // -- CONTINGENT VALUES --//
    
    
        // Store a list of values from the contingent values definition.
        var availableValues = new List<CodedValue>();
    
        // Get all contingent values defined for a specified field name.
        // The attribute values of the feature determine which contingent values are returned.
        var contingentValuesResult = polesFeatureTable.GetContingentValues(inFeature, "Material");
    
        // Get contingent values for a specified field group.
        var contingentValuesList = contingentValuesResult.ContingentValuesByFieldGroup["voltage_material"];
        // You can use code like this to get contingent values for all field groups if this field participates in more than one.
        // var contingentValuesList = contingentValuesResult.ContingentValuesAllGroups;
    
        // Loop through the contingent values and add the coded values to a list.
        foreach(var cv in contingentValuesList)
        {
            var contingentCodedValue = cv as ContingentCodedValue;
            if(contingentCodedValue != null)
            {
                availableValues.Add(contingentCodedValue.CodedValue);
            }
        }
    
    
    
        // Check for ContingentAnyValue (which means any value in the domain is valid).
        var contingentAnyValue = cv as ContingentAnyValue;
        if (contingentAnyValue != null)
        {
            // Add all values from the field's domain.
            var domain = _featureTableCV.GetField(fieldName)?.Domain as CodedValueDomain;
            if (domain != null)
            {
                availableValues.AddRange(domain.CodedValues);
            }
        }
    
    
    
        var contingentRangeValue = cv as ContingentRangeValue;
        if (contingentRangeValue != null)
        {
            (Int16 Min, Int16 Max) rangeTuple = ((Int16)contingentRangeValue.MinValue, (Int16)contingentRangeValue.MaxValue);
        }
    
    
    
        var contingentValueViolations = editFeatureTable.ValidateContingencyConstraints(newFeature);
    
        // If there are no violations, enable the save button and return.
        if (contingentValueViolations.Count == 0)
        {
            ValidateContingentValuesButton.IsEnabled = false;
            SaveFeatureButton.IsEnabled = true;
            return;
        }
    
        // Loop through contingency violations and show messages for errors and warnings.
        // Include the name of the field group that had the violation.
        foreach(var violation in contingentValueViolations)
        {
            // Show the appropriate icon: an error (red X) or warning (yellow exclamation).
            MessageBoxImage messageIcon = violation.Type == ContingencyConstraintViolationType.Error ?
                                            MessageBoxImage.Error : MessageBoxImage.Warning;
            MessageBox.Show("Contingency value violation for field group '" + violation.FieldGroup.Name + "'",
                            "Violation",
                            MessageBoxButton.OK,
                            messageIcon);
        }
    
  5. Pass the parameters to the service geodatabase to create a new version. Then switch the current version of the database to the new one.

    Use dark colors for code blocks
                                                                                                                                                                                                                                                                                     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    // --- Edit ---
    
    private async void AddFeature(MapPoint structureLocation, string type, string cause)
    {
        // Create attributes for the feature.
        Dictionary<string, object> attributes = new Dictionary<string, object>();
        attributes.Add("typdamage", type);
        attributes.Add("primcause", cause);
    
        // Create a new feature from the attributes and the point.
        Feature newFeature = _damagePointsTable.CreateFeature(attributes, structureLocation);
    
        // Add the feature to the local table.
        await _damagePointsTable.AddFeatureAsync(newFeature);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void UpdateFeature(ArcGISFeature arcgisFeature)
    {
        // Change the feature's attribute value.
        arcgisFeature.Attributes["typdamage"] = "Inaccessible";
    
        // Change the feature's geometry.
        MapPoint location = arcgisFeature.Geometry as MapPoint;
        MapPoint newLocation = new MapPoint(location.X, location.Y + 50000);
        arcgisFeature.Geometry = newLocation;
    
        // Update the feature on the local table.
        await _damagePointsTable.UpdateFeatureAsync(f);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void DeleteSelectedFeatures(FeatureLayer damageLayer)
    {
        // Get all selected features in the layer.
        FeatureQueryResult selectedFeatures = await damageLayer.GetSelectedFeaturesAsync();
    
        // Delete the selected features.
        await _damagePointsTable.DeleteFeaturesAsync(selectedFeatures);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    // If the feature table is a service feature table, send these edits
    // to the online service by applying them to its service geodatabase.
    EditResult editResults = await table.ServiceGeodatabase.ApplyEditsAsync();
    
    
    // --- Query ---
    
    
    // Build a buffer (polygon) around a click point
    var buffer = GeometryEngine.Buffer(queryPoint, 5000);
    
    // Use the buffer to define the geometry for a query
    var query = new QueryParameters();
    query.Geometry = buffer;
    query.SpatialRelationship = SpatialRelationship.Contains;
    
    // Select features in a feature layer using the query
    await damageLayer.SelectFeaturesAsync(query, Esri.ArcGISRuntime.Mapping.SelectionMode.New);
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    var layer = MyMapView.Map.OperationalLayers[0];
    var pixelTolerance = 20;
    var returnPopupsOnly = false;
    var maxResults = 5;
    
    // identify a layer using MapView, passing in the layer, the tap point, tolerance, types to return, and max results
    IdentifyLayerResult idResults = await MyMapView.IdentifyLayerAsync(layer, tapScreenPoint, pixelTolerance, returnPopupsOnly, maxResults);
    
    // get the layer identified and cast it to FeatureLayer
    FeatureLayer idLayer = idResults.LayerContent as FeatureLayer;
    
    // iterate each identified GeoElement in the results
    foreach (GeoElement idElement in idResults.GeoElements)
    {
        // cast the result GeoElement to Feature
        Feature idFeature = idElement as Feature;
    
        // select this feature in the feature layer
        idLayer.SelectFeature(idFeature);
    }
    
    
    // -- BRANCH VERSIONING --//
    
    
        // Get the feature table from a feature layer and cast it to ServiceFeatureTable
        // (if the table is not a ServiceFeatureTable, it will be null)
        ServiceFeatureTable table = layer.FeatureTable as ServiceFeatureTable;
    
    
    
        // If the feature table is a ServiceFeatureTable, see if it has a service geodatabase
        if (table != null)
        {
            ServiceGeodatabase serviceGdb = table.ServiceGeodatabase;
            if(serviceGdb != null)
            {
                // Load the service geodatabase if necessary
                if (serviceGdb.LoadStatus != LoadStatus.Loaded)
                {
                    await serviceGdb.LoadAsync();
                }
    
    
    
        // (continued from above)
                // See if the service geodatabase supports branch versioning
                if (serviceGdb.SupportsBranchVersioning)
                {
                    // Get the versions contained in the service geodatabase
                    IReadOnlyList versions = await serviceGdb.GetVersionsAsync();
    
                    // Get the info for the current version and read its description
                    ServiceVersionInfo thisVersionInfo = versions.First(v => v.Name == serviceGdb.VersionName);
                    string versionDesc = thisVersionInfo.Description;
    
    
    
        // (continued from above)
                    // Create service version parameters to define a new private version
                    var versionParams = new ServiceVersionParameters()
                    {
                        Access = VersionAccess.Private,
                        Name = "DesignTwo",
                        Description = "Experimenting with an alternate design"
                    };
    
    
    
        // (continued from above)
                    // Use the parameters to create a new version in the service geodatabase
                    var designTwoVersion = await serviceGdb.CreateVersionAsync(versionParams);
    
                    // Switch the version used in the map to the new one
                    await serviceGdb.SwitchVersionAsync(designTwoVersion.Name);
                }
            }
    
    
    
        // Create a new feature and define its geometry and attributes
        Feature feature = table.CreateFeature();
        feature.Geometry = featureLocation;
        feature.SetAttributeValue("CITY", "Chula Vista");
    
        // Add the new feature to the local table
        await table.AddFeatureAsync(feature);
    
        // Delete some features
        var cityFeatures = await table.QueryFeaturesAsync(new QueryParameters { WhereClause = "CITY='National City'" });
        await table.DeleteFeaturesAsync(cityFeatures);
    
    
    
        // See which tables are from the service geodatabase
        IReadOnlyList serviceTables = serviceGdb.ConnectedTables;
    
    
    
        if (serviceGdb.HasLocalEdits())
        {
            // Apply local edits for all connected tables to the service
            await serviceGdb.ApplyEditsAsync();
        }
    
    
    
        // Undo all local edits for the version
        await serviceGeodabase.UndoLocalEditsAsync();
    
    
    
    // -- CONTINGENT VALUES --//
    
    
        // Store a list of values from the contingent values definition.
        var availableValues = new List<CodedValue>();
    
        // Get all contingent values defined for a specified field name.
        // The attribute values of the feature determine which contingent values are returned.
        var contingentValuesResult = polesFeatureTable.GetContingentValues(inFeature, "Material");
    
        // Get contingent values for a specified field group.
        var contingentValuesList = contingentValuesResult.ContingentValuesByFieldGroup["voltage_material"];
        // You can use code like this to get contingent values for all field groups if this field participates in more than one.
        // var contingentValuesList = contingentValuesResult.ContingentValuesAllGroups;
    
        // Loop through the contingent values and add the coded values to a list.
        foreach(var cv in contingentValuesList)
        {
            var contingentCodedValue = cv as ContingentCodedValue;
            if(contingentCodedValue != null)
            {
                availableValues.Add(contingentCodedValue.CodedValue);
            }
        }
    
    
    
        // Check for ContingentAnyValue (which means any value in the domain is valid).
        var contingentAnyValue = cv as ContingentAnyValue;
        if (contingentAnyValue != null)
        {
            // Add all values from the field's domain.
            var domain = _featureTableCV.GetField(fieldName)?.Domain as CodedValueDomain;
            if (domain != null)
            {
                availableValues.AddRange(domain.CodedValues);
            }
        }
    
    
    
        var contingentRangeValue = cv as ContingentRangeValue;
        if (contingentRangeValue != null)
        {
            (Int16 Min, Int16 Max) rangeTuple = ((Int16)contingentRangeValue.MinValue, (Int16)contingentRangeValue.MaxValue);
        }
    
    
    
        var contingentValueViolations = editFeatureTable.ValidateContingencyConstraints(newFeature);
    
        // If there are no violations, enable the save button and return.
        if (contingentValueViolations.Count == 0)
        {
            ValidateContingentValuesButton.IsEnabled = false;
            SaveFeatureButton.IsEnabled = true;
            return;
        }
    
        // Loop through contingency violations and show messages for errors and warnings.
        // Include the name of the field group that had the violation.
        foreach(var violation in contingentValueViolations)
        {
            // Show the appropriate icon: an error (red X) or warning (yellow exclamation).
            MessageBoxImage messageIcon = violation.Type == ContingencyConstraintViolationType.Error ?
                                            MessageBoxImage.Error : MessageBoxImage.Warning;
            MessageBox.Show("Contingency value violation for field group '" + violation.FieldGroup.Name + "'",
                            "Violation",
                            MessageBoxButton.OK,
                            messageIcon);
        }
    

Edit data from a branch version

Edits can be made to service feature tables from a branch version in the same way they are made to any ServiceFeatureTable. You can use the same workflow described in the Edit topic. Within that standard workflow, the ServiceGeodatabase class provides some additional members for managing edits. For example, all local edits (to all tables in the version) can be applied by calling ServiceGeodatabase.ApplyEditsAsync() and you can undo all edits with ServiceGeodatabase.UndoLocalEditsAsync(). Reconciling and posting versions are back-office operations that should be performed with ArcGIS Pro or other enterprise processes.

  1. Make edits to the service feature tables, such as adding, deleting, or updating features. Edits to attachments and adding or removing relates can also be managed by the service geodatabase. See Perform Edits for more information about how to perform these feature edits.

  2. Service feature table edits only affect the local datasets unless they are explicitly applied to the service. Before applying your local edits, you may want to examine the connected tables for a service geodatabase to see which tables it manages. When loading a web map, the service geodatabase's connected tables will consist of all tables in the map from the same feature service. Accessing a table from the service geodatabase (using ServiceGeodatabase.GetTable()) will also add that table to the collection of connected tables.

    Use dark colors for code blocks
                                                                                                                                                                                                                                                                                     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    // --- Edit ---
    
    private async void AddFeature(MapPoint structureLocation, string type, string cause)
    {
        // Create attributes for the feature.
        Dictionary<string, object> attributes = new Dictionary<string, object>();
        attributes.Add("typdamage", type);
        attributes.Add("primcause", cause);
    
        // Create a new feature from the attributes and the point.
        Feature newFeature = _damagePointsTable.CreateFeature(attributes, structureLocation);
    
        // Add the feature to the local table.
        await _damagePointsTable.AddFeatureAsync(newFeature);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void UpdateFeature(ArcGISFeature arcgisFeature)
    {
        // Change the feature's attribute value.
        arcgisFeature.Attributes["typdamage"] = "Inaccessible";
    
        // Change the feature's geometry.
        MapPoint location = arcgisFeature.Geometry as MapPoint;
        MapPoint newLocation = new MapPoint(location.X, location.Y + 50000);
        arcgisFeature.Geometry = newLocation;
    
        // Update the feature on the local table.
        await _damagePointsTable.UpdateFeatureAsync(f);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void DeleteSelectedFeatures(FeatureLayer damageLayer)
    {
        // Get all selected features in the layer.
        FeatureQueryResult selectedFeatures = await damageLayer.GetSelectedFeaturesAsync();
    
        // Delete the selected features.
        await _damagePointsTable.DeleteFeaturesAsync(selectedFeatures);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    // If the feature table is a service feature table, send these edits
    // to the online service by applying them to its service geodatabase.
    EditResult editResults = await table.ServiceGeodatabase.ApplyEditsAsync();
    
    
    // --- Query ---
    
    
    // Build a buffer (polygon) around a click point
    var buffer = GeometryEngine.Buffer(queryPoint, 5000);
    
    // Use the buffer to define the geometry for a query
    var query = new QueryParameters();
    query.Geometry = buffer;
    query.SpatialRelationship = SpatialRelationship.Contains;
    
    // Select features in a feature layer using the query
    await damageLayer.SelectFeaturesAsync(query, Esri.ArcGISRuntime.Mapping.SelectionMode.New);
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    var layer = MyMapView.Map.OperationalLayers[0];
    var pixelTolerance = 20;
    var returnPopupsOnly = false;
    var maxResults = 5;
    
    // identify a layer using MapView, passing in the layer, the tap point, tolerance, types to return, and max results
    IdentifyLayerResult idResults = await MyMapView.IdentifyLayerAsync(layer, tapScreenPoint, pixelTolerance, returnPopupsOnly, maxResults);
    
    // get the layer identified and cast it to FeatureLayer
    FeatureLayer idLayer = idResults.LayerContent as FeatureLayer;
    
    // iterate each identified GeoElement in the results
    foreach (GeoElement idElement in idResults.GeoElements)
    {
        // cast the result GeoElement to Feature
        Feature idFeature = idElement as Feature;
    
        // select this feature in the feature layer
        idLayer.SelectFeature(idFeature);
    }
    
    
    // -- BRANCH VERSIONING --//
    
    
        // Get the feature table from a feature layer and cast it to ServiceFeatureTable
        // (if the table is not a ServiceFeatureTable, it will be null)
        ServiceFeatureTable table = layer.FeatureTable as ServiceFeatureTable;
    
    
    
        // If the feature table is a ServiceFeatureTable, see if it has a service geodatabase
        if (table != null)
        {
            ServiceGeodatabase serviceGdb = table.ServiceGeodatabase;
            if(serviceGdb != null)
            {
                // Load the service geodatabase if necessary
                if (serviceGdb.LoadStatus != LoadStatus.Loaded)
                {
                    await serviceGdb.LoadAsync();
                }
    
    
    
        // (continued from above)
                // See if the service geodatabase supports branch versioning
                if (serviceGdb.SupportsBranchVersioning)
                {
                    // Get the versions contained in the service geodatabase
                    IReadOnlyList versions = await serviceGdb.GetVersionsAsync();
    
                    // Get the info for the current version and read its description
                    ServiceVersionInfo thisVersionInfo = versions.First(v => v.Name == serviceGdb.VersionName);
                    string versionDesc = thisVersionInfo.Description;
    
    
    
        // (continued from above)
                    // Create service version parameters to define a new private version
                    var versionParams = new ServiceVersionParameters()
                    {
                        Access = VersionAccess.Private,
                        Name = "DesignTwo",
                        Description = "Experimenting with an alternate design"
                    };
    
    
    
        // (continued from above)
                    // Use the parameters to create a new version in the service geodatabase
                    var designTwoVersion = await serviceGdb.CreateVersionAsync(versionParams);
    
                    // Switch the version used in the map to the new one
                    await serviceGdb.SwitchVersionAsync(designTwoVersion.Name);
                }
            }
    
    
    
        // Create a new feature and define its geometry and attributes
        Feature feature = table.CreateFeature();
        feature.Geometry = featureLocation;
        feature.SetAttributeValue("CITY", "Chula Vista");
    
        // Add the new feature to the local table
        await table.AddFeatureAsync(feature);
    
        // Delete some features
        var cityFeatures = await table.QueryFeaturesAsync(new QueryParameters { WhereClause = "CITY='National City'" });
        await table.DeleteFeaturesAsync(cityFeatures);
    
    
    
        // See which tables are from the service geodatabase
        IReadOnlyList serviceTables = serviceGdb.ConnectedTables;
    
    
    
        if (serviceGdb.HasLocalEdits())
        {
            // Apply local edits for all connected tables to the service
            await serviceGdb.ApplyEditsAsync();
        }
    
    
    
        // Undo all local edits for the version
        await serviceGeodabase.UndoLocalEditsAsync();
    
    
    
    // -- CONTINGENT VALUES --//
    
    
        // Store a list of values from the contingent values definition.
        var availableValues = new List<CodedValue>();
    
        // Get all contingent values defined for a specified field name.
        // The attribute values of the feature determine which contingent values are returned.
        var contingentValuesResult = polesFeatureTable.GetContingentValues(inFeature, "Material");
    
        // Get contingent values for a specified field group.
        var contingentValuesList = contingentValuesResult.ContingentValuesByFieldGroup["voltage_material"];
        // You can use code like this to get contingent values for all field groups if this field participates in more than one.
        // var contingentValuesList = contingentValuesResult.ContingentValuesAllGroups;
    
        // Loop through the contingent values and add the coded values to a list.
        foreach(var cv in contingentValuesList)
        {
            var contingentCodedValue = cv as ContingentCodedValue;
            if(contingentCodedValue != null)
            {
                availableValues.Add(contingentCodedValue.CodedValue);
            }
        }
    
    
    
        // Check for ContingentAnyValue (which means any value in the domain is valid).
        var contingentAnyValue = cv as ContingentAnyValue;
        if (contingentAnyValue != null)
        {
            // Add all values from the field's domain.
            var domain = _featureTableCV.GetField(fieldName)?.Domain as CodedValueDomain;
            if (domain != null)
            {
                availableValues.AddRange(domain.CodedValues);
            }
        }
    
    
    
        var contingentRangeValue = cv as ContingentRangeValue;
        if (contingentRangeValue != null)
        {
            (Int16 Min, Int16 Max) rangeTuple = ((Int16)contingentRangeValue.MinValue, (Int16)contingentRangeValue.MaxValue);
        }
    
    
    
        var contingentValueViolations = editFeatureTable.ValidateContingencyConstraints(newFeature);
    
        // If there are no violations, enable the save button and return.
        if (contingentValueViolations.Count == 0)
        {
            ValidateContingentValuesButton.IsEnabled = false;
            SaveFeatureButton.IsEnabled = true;
            return;
        }
    
        // Loop through contingency violations and show messages for errors and warnings.
        // Include the name of the field group that had the violation.
        foreach(var violation in contingentValueViolations)
        {
            // Show the appropriate icon: an error (red X) or warning (yellow exclamation).
            MessageBoxImage messageIcon = violation.Type == ContingencyConstraintViolationType.Error ?
                                            MessageBoxImage.Error : MessageBoxImage.Warning;
            MessageBox.Show("Contingency value violation for field group '" + violation.FieldGroup.Name + "'",
                            "Violation",
                            MessageBoxButton.OK,
                            messageIcon);
        }
    
  3. You can use HasLocalEdits() on the service geodatabase to see if there are unsaved edits in any of the connected tables. You can then use ApplyEditsAsync() on the service geodatabase to send all edits to the service in a single transaction. This ensures that geodatabase behavior is appropriately leveraged.

    Use dark colors for code blocks
                                                                                                                                                                                                                                                                                     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    // --- Edit ---
    
    private async void AddFeature(MapPoint structureLocation, string type, string cause)
    {
        // Create attributes for the feature.
        Dictionary<string, object> attributes = new Dictionary<string, object>();
        attributes.Add("typdamage", type);
        attributes.Add("primcause", cause);
    
        // Create a new feature from the attributes and the point.
        Feature newFeature = _damagePointsTable.CreateFeature(attributes, structureLocation);
    
        // Add the feature to the local table.
        await _damagePointsTable.AddFeatureAsync(newFeature);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void UpdateFeature(ArcGISFeature arcgisFeature)
    {
        // Change the feature's attribute value.
        arcgisFeature.Attributes["typdamage"] = "Inaccessible";
    
        // Change the feature's geometry.
        MapPoint location = arcgisFeature.Geometry as MapPoint;
        MapPoint newLocation = new MapPoint(location.X, location.Y + 50000);
        arcgisFeature.Geometry = newLocation;
    
        // Update the feature on the local table.
        await _damagePointsTable.UpdateFeatureAsync(f);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void DeleteSelectedFeatures(FeatureLayer damageLayer)
    {
        // Get all selected features in the layer.
        FeatureQueryResult selectedFeatures = await damageLayer.GetSelectedFeaturesAsync();
    
        // Delete the selected features.
        await _damagePointsTable.DeleteFeaturesAsync(selectedFeatures);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    // If the feature table is a service feature table, send these edits
    // to the online service by applying them to its service geodatabase.
    EditResult editResults = await table.ServiceGeodatabase.ApplyEditsAsync();
    
    
    // --- Query ---
    
    
    // Build a buffer (polygon) around a click point
    var buffer = GeometryEngine.Buffer(queryPoint, 5000);
    
    // Use the buffer to define the geometry for a query
    var query = new QueryParameters();
    query.Geometry = buffer;
    query.SpatialRelationship = SpatialRelationship.Contains;
    
    // Select features in a feature layer using the query
    await damageLayer.SelectFeaturesAsync(query, Esri.ArcGISRuntime.Mapping.SelectionMode.New);
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    var layer = MyMapView.Map.OperationalLayers[0];
    var pixelTolerance = 20;
    var returnPopupsOnly = false;
    var maxResults = 5;
    
    // identify a layer using MapView, passing in the layer, the tap point, tolerance, types to return, and max results
    IdentifyLayerResult idResults = await MyMapView.IdentifyLayerAsync(layer, tapScreenPoint, pixelTolerance, returnPopupsOnly, maxResults);
    
    // get the layer identified and cast it to FeatureLayer
    FeatureLayer idLayer = idResults.LayerContent as FeatureLayer;
    
    // iterate each identified GeoElement in the results
    foreach (GeoElement idElement in idResults.GeoElements)
    {
        // cast the result GeoElement to Feature
        Feature idFeature = idElement as Feature;
    
        // select this feature in the feature layer
        idLayer.SelectFeature(idFeature);
    }
    
    
    // -- BRANCH VERSIONING --//
    
    
        // Get the feature table from a feature layer and cast it to ServiceFeatureTable
        // (if the table is not a ServiceFeatureTable, it will be null)
        ServiceFeatureTable table = layer.FeatureTable as ServiceFeatureTable;
    
    
    
        // If the feature table is a ServiceFeatureTable, see if it has a service geodatabase
        if (table != null)
        {
            ServiceGeodatabase serviceGdb = table.ServiceGeodatabase;
            if(serviceGdb != null)
            {
                // Load the service geodatabase if necessary
                if (serviceGdb.LoadStatus != LoadStatus.Loaded)
                {
                    await serviceGdb.LoadAsync();
                }
    
    
    
        // (continued from above)
                // See if the service geodatabase supports branch versioning
                if (serviceGdb.SupportsBranchVersioning)
                {
                    // Get the versions contained in the service geodatabase
                    IReadOnlyList versions = await serviceGdb.GetVersionsAsync();
    
                    // Get the info for the current version and read its description
                    ServiceVersionInfo thisVersionInfo = versions.First(v => v.Name == serviceGdb.VersionName);
                    string versionDesc = thisVersionInfo.Description;
    
    
    
        // (continued from above)
                    // Create service version parameters to define a new private version
                    var versionParams = new ServiceVersionParameters()
                    {
                        Access = VersionAccess.Private,
                        Name = "DesignTwo",
                        Description = "Experimenting with an alternate design"
                    };
    
    
    
        // (continued from above)
                    // Use the parameters to create a new version in the service geodatabase
                    var designTwoVersion = await serviceGdb.CreateVersionAsync(versionParams);
    
                    // Switch the version used in the map to the new one
                    await serviceGdb.SwitchVersionAsync(designTwoVersion.Name);
                }
            }
    
    
    
        // Create a new feature and define its geometry and attributes
        Feature feature = table.CreateFeature();
        feature.Geometry = featureLocation;
        feature.SetAttributeValue("CITY", "Chula Vista");
    
        // Add the new feature to the local table
        await table.AddFeatureAsync(feature);
    
        // Delete some features
        var cityFeatures = await table.QueryFeaturesAsync(new QueryParameters { WhereClause = "CITY='National City'" });
        await table.DeleteFeaturesAsync(cityFeatures);
    
    
    
        // See which tables are from the service geodatabase
        IReadOnlyList serviceTables = serviceGdb.ConnectedTables;
    
    
    
        if (serviceGdb.HasLocalEdits())
        {
            // Apply local edits for all connected tables to the service
            await serviceGdb.ApplyEditsAsync();
        }
    
    
    
        // Undo all local edits for the version
        await serviceGeodabase.UndoLocalEditsAsync();
    
    
    
    // -- CONTINGENT VALUES --//
    
    
        // Store a list of values from the contingent values definition.
        var availableValues = new List<CodedValue>();
    
        // Get all contingent values defined for a specified field name.
        // The attribute values of the feature determine which contingent values are returned.
        var contingentValuesResult = polesFeatureTable.GetContingentValues(inFeature, "Material");
    
        // Get contingent values for a specified field group.
        var contingentValuesList = contingentValuesResult.ContingentValuesByFieldGroup["voltage_material"];
        // You can use code like this to get contingent values for all field groups if this field participates in more than one.
        // var contingentValuesList = contingentValuesResult.ContingentValuesAllGroups;
    
        // Loop through the contingent values and add the coded values to a list.
        foreach(var cv in contingentValuesList)
        {
            var contingentCodedValue = cv as ContingentCodedValue;
            if(contingentCodedValue != null)
            {
                availableValues.Add(contingentCodedValue.CodedValue);
            }
        }
    
    
    
        // Check for ContingentAnyValue (which means any value in the domain is valid).
        var contingentAnyValue = cv as ContingentAnyValue;
        if (contingentAnyValue != null)
        {
            // Add all values from the field's domain.
            var domain = _featureTableCV.GetField(fieldName)?.Domain as CodedValueDomain;
            if (domain != null)
            {
                availableValues.AddRange(domain.CodedValues);
            }
        }
    
    
    
        var contingentRangeValue = cv as ContingentRangeValue;
        if (contingentRangeValue != null)
        {
            (Int16 Min, Int16 Max) rangeTuple = ((Int16)contingentRangeValue.MinValue, (Int16)contingentRangeValue.MaxValue);
        }
    
    
    
        var contingentValueViolations = editFeatureTable.ValidateContingencyConstraints(newFeature);
    
        // If there are no violations, enable the save button and return.
        if (contingentValueViolations.Count == 0)
        {
            ValidateContingentValuesButton.IsEnabled = false;
            SaveFeatureButton.IsEnabled = true;
            return;
        }
    
        // Loop through contingency violations and show messages for errors and warnings.
        // Include the name of the field group that had the violation.
        foreach(var violation in contingentValueViolations)
        {
            // Show the appropriate icon: an error (red X) or warning (yellow exclamation).
            MessageBoxImage messageIcon = violation.Type == ContingencyConstraintViolationType.Error ?
                                            MessageBoxImage.Error : MessageBoxImage.Warning;
            MessageBox.Show("Contingency value violation for field group '" + violation.FieldGroup.Name + "'",
                            "Violation",
                            MessageBoxButton.OK,
                            messageIcon);
        }
    

    The advantage of calling ServiceGeodatabase.ApplyEditsAsync() on the service geodatabase, rather than on each individual table, is that it ensures that all of the edit operations take place in a single transaction. Either all of the edits are applied or none of them. If you apply edits on each table individually, it is possible that only some edits will be applied (for example, if you lose network connectivity in the middle of the operation).

  4. To undo local edits in the connected tables, use UndoLocalEditsAsync() on the service geodatabase.

    Use dark colors for code blocks
                                                                                                                                                                                                                                                                                     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    // --- Edit ---
    
    private async void AddFeature(MapPoint structureLocation, string type, string cause)
    {
        // Create attributes for the feature.
        Dictionary<string, object> attributes = new Dictionary<string, object>();
        attributes.Add("typdamage", type);
        attributes.Add("primcause", cause);
    
        // Create a new feature from the attributes and the point.
        Feature newFeature = _damagePointsTable.CreateFeature(attributes, structureLocation);
    
        // Add the feature to the local table.
        await _damagePointsTable.AddFeatureAsync(newFeature);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void UpdateFeature(ArcGISFeature arcgisFeature)
    {
        // Change the feature's attribute value.
        arcgisFeature.Attributes["typdamage"] = "Inaccessible";
    
        // Change the feature's geometry.
        MapPoint location = arcgisFeature.Geometry as MapPoint;
        MapPoint newLocation = new MapPoint(location.X, location.Y + 50000);
        arcgisFeature.Geometry = newLocation;
    
        // Update the feature on the local table.
        await _damagePointsTable.UpdateFeatureAsync(f);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    private async void DeleteSelectedFeatures(FeatureLayer damageLayer)
    {
        // Get all selected features in the layer.
        FeatureQueryResult selectedFeatures = await damageLayer.GetSelectedFeaturesAsync();
    
        // Delete the selected features.
        await _damagePointsTable.DeleteFeaturesAsync(selectedFeatures);
    
        // If the feature table is a service feature table then
        // apply edits to its service geodatabase.
        ...
    }
    
    
    
    // If the feature table is a service feature table, send these edits
    // to the online service by applying them to its service geodatabase.
    EditResult editResults = await table.ServiceGeodatabase.ApplyEditsAsync();
    
    
    // --- Query ---
    
    
    // Build a buffer (polygon) around a click point
    var buffer = GeometryEngine.Buffer(queryPoint, 5000);
    
    // Use the buffer to define the geometry for a query
    var query = new QueryParameters();
    query.Geometry = buffer;
    query.SpatialRelationship = SpatialRelationship.Contains;
    
    // Select features in a feature layer using the query
    await damageLayer.SelectFeaturesAsync(query, Esri.ArcGISRuntime.Mapping.SelectionMode.New);
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    // TODO:
    
    
    
    var layer = MyMapView.Map.OperationalLayers[0];
    var pixelTolerance = 20;
    var returnPopupsOnly = false;
    var maxResults = 5;
    
    // identify a layer using MapView, passing in the layer, the tap point, tolerance, types to return, and max results
    IdentifyLayerResult idResults = await MyMapView.IdentifyLayerAsync(layer, tapScreenPoint, pixelTolerance, returnPopupsOnly, maxResults);
    
    // get the layer identified and cast it to FeatureLayer
    FeatureLayer idLayer = idResults.LayerContent as FeatureLayer;
    
    // iterate each identified GeoElement in the results
    foreach (GeoElement idElement in idResults.GeoElements)
    {
        // cast the result GeoElement to Feature
        Feature idFeature = idElement as Feature;
    
        // select this feature in the feature layer
        idLayer.SelectFeature(idFeature);
    }
    
    
    // -- BRANCH VERSIONING --//
    
    
        // Get the feature table from a feature layer and cast it to ServiceFeatureTable
        // (if the table is not a ServiceFeatureTable, it will be null)
        ServiceFeatureTable table = layer.FeatureTable as ServiceFeatureTable;
    
    
    
        // If the feature table is a ServiceFeatureTable, see if it has a service geodatabase
        if (table != null)
        {
            ServiceGeodatabase serviceGdb = table.ServiceGeodatabase;
            if(serviceGdb != null)
            {
                // Load the service geodatabase if necessary
                if (serviceGdb.LoadStatus != LoadStatus.Loaded)
                {
                    await serviceGdb.LoadAsync();
                }
    
    
    
        // (continued from above)
                // See if the service geodatabase supports branch versioning
                if (serviceGdb.SupportsBranchVersioning)
                {
                    // Get the versions contained in the service geodatabase
                    IReadOnlyList versions = await serviceGdb.GetVersionsAsync();
    
                    // Get the info for the current version and read its description
                    ServiceVersionInfo thisVersionInfo = versions.First(v => v.Name == serviceGdb.VersionName);
                    string versionDesc = thisVersionInfo.Description;
    
    
    
        // (continued from above)
                    // Create service version parameters to define a new private version
                    var versionParams = new ServiceVersionParameters()
                    {
                        Access = VersionAccess.Private,
                        Name = "DesignTwo",
                        Description = "Experimenting with an alternate design"
                    };
    
    
    
        // (continued from above)
                    // Use the parameters to create a new version in the service geodatabase
                    var designTwoVersion = await serviceGdb.CreateVersionAsync(versionParams);
    
                    // Switch the version used in the map to the new one
                    await serviceGdb.SwitchVersionAsync(designTwoVersion.Name);
                }
            }
    
    
    
        // Create a new feature and define its geometry and attributes
        Feature feature = table.CreateFeature();
        feature.Geometry = featureLocation;
        feature.SetAttributeValue("CITY", "Chula Vista");
    
        // Add the new feature to the local table
        await table.AddFeatureAsync(feature);
    
        // Delete some features
        var cityFeatures = await table.QueryFeaturesAsync(new QueryParameters { WhereClause = "CITY='National City'" });
        await table.DeleteFeaturesAsync(cityFeatures);
    
    
    
        // See which tables are from the service geodatabase
        IReadOnlyList serviceTables = serviceGdb.ConnectedTables;
    
    
    
        if (serviceGdb.HasLocalEdits())
        {
            // Apply local edits for all connected tables to the service
            await serviceGdb.ApplyEditsAsync();
        }
    
    
    
        // Undo all local edits for the version
        await serviceGeodabase.UndoLocalEditsAsync();
    
    
    
    // -- CONTINGENT VALUES --//
    
    
        // Store a list of values from the contingent values definition.
        var availableValues = new List<CodedValue>();
    
        // Get all contingent values defined for a specified field name.
        // The attribute values of the feature determine which contingent values are returned.
        var contingentValuesResult = polesFeatureTable.GetContingentValues(inFeature, "Material");
    
        // Get contingent values for a specified field group.
        var contingentValuesList = contingentValuesResult.ContingentValuesByFieldGroup["voltage_material"];
        // You can use code like this to get contingent values for all field groups if this field participates in more than one.
        // var contingentValuesList = contingentValuesResult.ContingentValuesAllGroups;
    
        // Loop through the contingent values and add the coded values to a list.
        foreach(var cv in contingentValuesList)
        {
            var contingentCodedValue = cv as ContingentCodedValue;
            if(contingentCodedValue != null)
            {
                availableValues.Add(contingentCodedValue.CodedValue);
            }
        }
    
    
    
        // Check for ContingentAnyValue (which means any value in the domain is valid).
        var contingentAnyValue = cv as ContingentAnyValue;
        if (contingentAnyValue != null)
        {
            // Add all values from the field's domain.
            var domain = _featureTableCV.GetField(fieldName)?.Domain as CodedValueDomain;
            if (domain != null)
            {
                availableValues.AddRange(domain.CodedValues);
            }
        }
    
    
    
        var contingentRangeValue = cv as ContingentRangeValue;
        if (contingentRangeValue != null)
        {
            (Int16 Min, Int16 Max) rangeTuple = ((Int16)contingentRangeValue.MinValue, (Int16)contingentRangeValue.MaxValue);
        }
    
    
    
        var contingentValueViolations = editFeatureTable.ValidateContingencyConstraints(newFeature);
    
        // If there are no violations, enable the save button and return.
        if (contingentValueViolations.Count == 0)
        {
            ValidateContingentValuesButton.IsEnabled = false;
            SaveFeatureButton.IsEnabled = true;
            return;
        }
    
        // Loop through contingency violations and show messages for errors and warnings.
        // Include the name of the field group that had the violation.
        foreach(var violation in contingentValueViolations)
        {
            // Show the appropriate icon: an error (red X) or warning (yellow exclamation).
            MessageBoxImage messageIcon = violation.Type == ContingencyConstraintViolationType.Error ?
                                            MessageBoxImage.Error : MessageBoxImage.Warning;
            MessageBox.Show("Contingency value violation for field group '" + violation.FieldGroup.Name + "'",
                            "Violation",
                            MessageBoxButton.OK,
                            messageIcon);
        }
    

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.