Select to view content in your preferred language

Passing a field value to an outside database.

1649
12
12-06-2010 07:51 AM
NathalieNeagle
Regular Contributor
I'm green to programming and silverlight and I have started created an application, which I'm almost finished.  But the most important tool/feature of the applicaiton is the one I'm having the most trouble with.

I have a parcel layer, which has a unique field (identifier number) the main part of this applicaiton is quering the parcel by using an Attribute query (similar to the SDK exmaple http://help.arcgis.com/en/webapi/silverlight/samples/start.htm#AttributeQuery but not a drop down list just a text box enter) and the spatial query tool (http://help.arcgis.com/en/webapi/silverlight/samples/start.htm#SpatialQuery) to select parcels.

So basically there is an outside data base with extra information about the parcles (the common key primary/secondary) is the identifier number/field.  I'm wondering if there is an example or someone has some code/information they can share about how to grab a field record value and pass it to an outside database.
0 Kudos
12 Replies
AliMirzabeigi
Emerging Contributor
For every Graphic in the FeatureSet returned by your QueryTask you can get the attributes using:
theGraphic.Attributes["FieldName"]

If you queried against a FeatureLayer you can get the unique identifier value of your object (ObjectID field) like the following:
theGraphic.Attributes[theFeatureLayer.LayerInfo.ObjectIdField]
0 Kudos
NathalieNeagle
Regular Contributor
Ali,

Thanks for the reply.  This will definitely help me get started.  I guess I�??m struggling with another design/process question.  If the attribute query/find or the select spatial attributes return several features/graphics and populates several records in the table grid how could I allow the user to select just one and then pass the parcel id to retrieve the outside data?  I guess I�??m struggling with the initial design. 

So if I�??m binding  my selection/graphics to the feature grid, what would suggest to add to fire off the passing of the parcel id?  Would it be easy to add something to the grid/table like a button next to each record or a check box, maybe make the parcel id hyperlinkable, maybe a right click on a record, I�??m just not sure and would like to go the easiest and cleanest route.   My users might initial query several features and then limit it to just one (via viewing the map and table grid information)

<esri:FeatureDataGrid Grid.Row="1" x:Name="QueryDetailsDataGrid" Height="170"
                                      Map="{Binding ElementName=Map}"
                                      GraphicsLayer="{Binding ElementName=Map, Path=Layers[MySelectionGraphicsLayer]}" />
0 Kudos
JenniferNery
Esri Regular Contributor
You can probably do this on FeatureDataGrid's SelectionChanged event? Provided you know the ObjectID Field. You can do this on the first
private void FeatureDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
 var graphics = (sender as ESRI.ArcGIS.Client.Toolkit.FeatureDataGrid).SelectedGraphics;
 foreach(var g in graphics)
 {
  // get id 
  var id = g.Attributes["objectIdField"];
  // TODO: retrieve outside data for this id
  break;
 }
}
0 Kudos
NathalieNeagle
Regular Contributor
Jennifer,

Thanks for the reply.  I did not completely follow you:confused:

I currently have the standard Selection Change Event
private void QueryDetailsDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            foreach (Graphic g in e.AddedItems)
                g.Select();

            foreach (Graphic g in e.RemovedItems)
                g.UnSelect();
        }


I'm basically using the out of the box spatial select and featuredatagrid so per Ali suggestion "If you queried against a FeatureLayer you can get the unique identifier value of your object (ObjectID field) like the following:"

I should be able to get the objectid Correct?

When you stated the ObjectID field did you mean the GIS/ESRI ObjectID field or the field I'm after (ParcelID)?  Do I need to be able to see/grab the objectid before I can grab and use the ParcelID?

I'm hoping I could just place your snippet like this:

private void QueryDetailsDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            foreach (Graphic g in e.AddedItems)
                g.Select();

            foreach (Graphic g in e.RemovedItems)
                g.UnSelect();
        }


var graphics = (sender as ESRI.ArcGIS.Client.Toolkit.FeatureDataGrid).SelectedGraphics;
 foreach(var g in graphics)
 {
  // get id 
  var id = g.Attributes["objectIdField"];

  // TODO: retrieve outside data for this id

              
  break;
 }

0 Kudos
JenniferNery
Esri Regular Contributor
What type of layer is "MySelectionGraphicsLayer"?

If it is a FeatureLayer, per Ali's suggestion you can get the ObjectID field (which I assume is the same as your ParcelID, is that correct?), then you can use this attribute key:
MySelectionGraphicsLayer.LayerInfo.ObjectIdField

Otherwise, if it is a GraphicsLayer and you know the actual field name for ParcelID, then you can hardcode the attribute key, for example:
"ParcelID"

Also, I don't think you can assume e.AddedItems or e.RemovedItems to be an IEnumerable<Graphic>, this is not the case for FeatureDataGrid's SelectionChangedEventArgs.
 string id = MySelectionGraphicsLayer.LayerInfo.ObjectIdField; //or "ParcelID"
 var graphics = (sender as ESRI.ArcGIS.Client.Toolkit.FeatureDataGrid).SelectedGraphics;
 foreach(var g in graphics)
 {
  // get id 
  var id = g.Attributes[id];
  // TODO: retrieve outside data for this id
  break;
 }
0 Kudos
NathalieNeagle
Regular Contributor
Jennifer thanks again! O.K. I'm hoping this will be our last correspondence on this item.

The field I'm after is PARCELID and it is not the same as OBJECTID.  It is a unique field/key that corresponsed to our Code Enforcement database.  I think MySelectionGraphicLayers is a GraphicsLayer; Here's my code.

private void esriTools_ToolbarItemClicked(object sender, ESRI.ArcGIS.Client.Toolkit.SelectedToolbarItemArgs e)
        {
            switch (e.Index)
            {
                case 0: // Point
                    _drawSurface.DrawMode = DrawMode.Point;
                    break;
                case 1: // Polyline
                    _drawSurface.DrawMode = DrawMode.Polyline;
                    break;
                case 2: // Polygon
                    _drawSurface.DrawMode = DrawMode.Polygon;
                    break;
                case 3: // Rectangle
                    _drawSurface.DrawMode = DrawMode.Rectangle;
                    break;
                default: // Clear
                    _drawSurface.DrawMode = DrawMode.None;
                    GraphicsLayer selectionGraphicslayer = Map.Layers["MySelectionGraphicsLayer"] as GraphicsLayer;
                    selectionGraphicslayer.ClearGraphics();
                    QueryDetailsDataGrid.ItemsSource = null;
                    ResultsDisplay.IsExpanded = true;
                    break;
            }
            _drawSurface.IsEnabled = (_drawSurface.DrawMode != DrawMode.None);
            StatusTextBlock.Text = e.Item.Text;
        }
        private void MyDrawSurface_DrawComplete(object sender, ESRI.ArcGIS.Client.DrawEventArgs args)
        {
            GraphicsLayer selectionGraphicslayer = Map.Layers["MySelectionGraphicsLayer"] as GraphicsLayer;
            selectionGraphicslayer.ClearGraphics();
            QueryTask queryTask = new QueryTask("http://SERVERNAME/ArcGIS/rest/services/Parcels/MapServer/0")
            queryTask.ExecuteCompleted += QueryTask_ExecuteCompleted;
            queryTask.Failed += QueryTask_Failed;
            Query query = new ESRI.ArcGIS.Client.Tasks.Query();


            query.OutFields.Add("*");
            query.Geometry = args.Geometry;
            query.ReturnGeometry = true;
            _queryTask.ExecuteAsync(query);
        }
        private void QueryTask_ExecuteCompleted(object sender, ESRI.ArcGIS.Client.Tasks.QueryEventArgs args)
        {
            FeatureSet featureSet = args.FeatureSet;
            if (featureSet == null || featureSet.Features.Count < 1)
            {
                MessageBox.Show("No features retured from query");
                return;
            }
            GraphicsLayer graphicsLayer = Map.Layers["MySelectionGraphicsLayer"] as GraphicsLayer;
            if (featureSet != null && featureSet.Features.Count > 0)
            {
                foreach (Graphic feature in featureSet.Features)
                {
                    feature.Symbol = LayoutRoot.Resources["ResultsFillSymbol"] as FillSymbol;
                    graphicsLayer.Graphics.Insert(0, feature);
                }
            }
            //ResultsDisplay.Visibility = Visibility.Visible;
            ResultsDisplay.IsExpanded = true;

            _drawSurface.IsEnabled = false;
        }
        private void QueryTask_Failed(object sender, TaskFailedEventArgs args)
        {
            MessageBox.Show("Query failed: " + args.Error);
        }


Right now I would just like to just display and pass the PARCELID to a textblock that will display in my app; once I get this working I can move on to the next piece.

Here's what I'm trying and It is not working out.



        private void FeatureDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

           

            var graphics = (sender as ESRI.ArcGIS.Client.Toolkit.FeatureDataGrid).SelectedGraphics;
            foreach (var g in graphics)
            {
                // get id 
                var id = g.Attributes["PARCELID"];
                // TODO: retrieve outside data for this id
                PARCELIDPASS.Text = string.Format("The ParcelID passed is {1}", id);
                break;
            }

        }




In my XAML I have:

    <TextBlock x:Name="PARCELIDPASS" Text="" Foreground="Red" FontWeight="SemiBold" Margin="0,5,0,5" HorizontalAlignment="Center" TextWrapping="Wrap"/>
0 Kudos
JenniferNery
Esri Regular Contributor
Check that your map service (visit through web browser) for the Query contains "PARCELID" as one of its fields. This is case-sensitive.
0 Kudos
NathalieNeagle
Regular Contributor
Yea the PARCELID field is returned...it is not the primary display field but it is return in my FeatureDataGrid, I can see the field return in Fiddler, the field is also listed in the service/featurelayer/fields. 

I guess the field is only return in service (Query) when I ask for it to be a return field = PARCELID or * but I think I'm using the * (all) in my code so shouldn't it be returned?

I just tired to pass plain text with the FeatureDataGrid_SelectionChanged event: and I can not do that so this is going to sound stupid but do I need to envoke the event...shouldn't it just fire when a new selection happens (by clicking on a record in the FeatureTableGrid?

 private void FeatureDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

            var graphics = (sender as ESRI.ArcGIS.Client.Toolkit.FeatureDataGrid).SelectedGraphics;
            foreach (var g in graphics)
            {
                // get id 
                var id = g.Attributes["PARCELID"];
                // TODO: retrieve outside data for this id
                PARCELIDPASS.Text = "The ParcelID passed is";
                break;
            }

        }

0 Kudos
JenniferNery
Esri Regular Contributor
If your FeatureDataGrid's GraphicsLayer is set to the same GraphicsLayer that contains the results of your Query. The graphics in both FeatureDataGrid and GraphicsLayer must contain this attribute. Are you saying that g.Attributes["PARCELID"] returns null? You can check also that g.Attributes.ContainsKey("PARCELID"), which it should if you set up FeatureDataGrid correctly.
The code you posted in #7 need to change to this.
PARCELIDPASS.Text = string.Format("The ParcelID passed is {0}", id);
0 Kudos