Select to view content in your preferred language

How to perform spatial query between two services...

6198
24
07-15-2010 04:45 AM
MichaelBlom
Deactivated User
Hello,
all of the sdk examples involving spatial qeuries involve a service being queried against a feature that the user creates in th UI. 

ie drag a box, take the geometry from that box, set that geometry into the query, perform task

I want to do a query task between two service layers.

I see that I need to get at the recordset from the service in Silverlight, does anyone know how to do this?

Thanks,
Mike
0 Kudos
24 Replies
JenniferNery
Esri Regular Contributor
Oh I'm sorry I missed to include that - layers in my sample is of type ObservableCollection<FeatureLayer>.
0 Kudos
JMcNeil
Deactivated User
Oh I'm sorry I missed to include that - layers in my sample is of type ObservableCollection<FeatureLayer>.


Jennifer, thanks for the quick response.

I feel horrible that I can't get this....I'm just lost!

Like -  Inherited from System.Collections.ObjectModel.ObservableCollection<Graphic>
And you said that is for layer? 



What about query?

J.
0 Kudos
JenniferNery
Esri Regular Contributor
If your ComboBox is named "Layers" with ItemSource bound to ObservableCollection<FeatureLayer> as described in my previous post, you can modify your query this way:

 
            QueryTask queryTask = new QueryTask((Layers.SelectedItem as FeatureLayer).Url);
            //... more code here
            query.OutFields.Add("*");


That is Layers.SelectedItem is FeatureLayer and is not null, you can grab it's Url.

This was just one way to do it, you can have instead an list of url strings in your ComboBox and perform your query against the selected string. 

Since you don't know what fields that layer will contain and don't want to hard-code it, you can just return all fields by using "*", no need to specify AddRange(new string[]{ "field1", "field2", ...}).

I suggested using FeatureLayer incase you wish to see the LayerInfo.Fields before performing the query. You can get these values after the layer has been initialized.
0 Kudos
JMcNeil
Deactivated User
Jennifer.  Thanks again for all the replies.  I started over straight with the Spatial Query SDK because my code was twisted and I had a bunch of extra stuff that was getting more confused.

I add the two xaml code snippits exactly how you wrote them. 

The I tried to implement your code behind but app hangs and I do get the error warning about
ObservableCollection<FeatureLayer> layers; - is never assigned and always has a defualt value of null.....I'm sorry but what I'm I missing.

 public partial class MainPage : UserControl
    {

  private Draw MyDrawSurface;

  ObservableCollection<FeatureLayer> layers;

        public MainPage()
        {
            InitializeComponent();

           

            string baseUrl = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer";

            for (int i = 0; i <= 5; i++)
            {
                FeatureLayer featureLayer = new FeatureLayer() { Url = string.Format("{0}/{1}", baseUrl, i) };
                featureLayer.Initialize();
                layers.Add(featureLayer);
            }
            Layers.ItemsSource = layers;
            Layers.SelectedIndex = 0;

           
            MyDrawSurface = new Draw(MyMap)
            {
              LineSymbol = LayoutRoot.Resources["DefaultLineSymbol"] as SimpleLineSymbol,
              FillSymbol = LayoutRoot.Resources["DefaultFillSymbol"] as FillSymbol
            };
            MyDrawSurface.DrawComplete += MyDrawSurface_DrawComplete;
        }

        private void esriTools_ToolbarItemClicked(object sender, ESRI.ArcGIS.Client.Toolkit.SelectedToolbarItemArgs e)
        {
            switch (e.Index)
            {
                case 0: // Point
                    MyDrawSurface.DrawMode = DrawMode.Point;                    
                    break;
                case 1: // Polyline
                    MyDrawSurface.DrawMode = DrawMode.Polyline;                    
                    break;
                case 2: // Polygon
                    MyDrawSurface.DrawMode = DrawMode.Polygon;                    
                    break;
                case 3: // Rectangle
                    MyDrawSurface.DrawMode = DrawMode.Rectangle;                    
                    break;
                default: // Clear
                    MyDrawSurface.DrawMode = DrawMode.None;
                    GraphicsLayer selectionGraphicslayer = MyMap.Layers["MySelectionGraphicsLayer"] as GraphicsLayer;
                    selectionGraphicslayer.ClearGraphics();
                    QueryDetailsDataGrid.ItemsSource = null;
                    ResultsDisplay.Visibility = Visibility.Collapsed;
                    break;
            }
            MyDrawSurface.IsEnabled = (MyDrawSurface.DrawMode != DrawMode.None);
            StatusTextBlock.Text = e.Item.Text;
        }

        private void MyDrawSurface_DrawComplete(object sender, ESRI.ArcGIS.Client.DrawEventArgs args)
        {
            GraphicsLayer selectionGraphicslayer = MyMap.Layers["MySelectionGraphicsLayer"] as GraphicsLayer;
            selectionGraphicslayer.ClearGraphics();

        

            QueryTask queryTask = new QueryTask((Layers.SelectedItem as FeatureLayer).Url);
            //... more code here
           

            queryTask.ExecuteCompleted += QueryTask_ExecuteCompleted;
            queryTask.Failed += QueryTask_Failed;


            // Bind data grid to query results
            Binding resultFeaturesBinding = new Binding("LastResult.Features");
            resultFeaturesBinding.Source = queryTask;
            QueryDetailsDataGrid.SetBinding(DataGrid.ItemsSourceProperty, resultFeaturesBinding);
            Query query = new ESRI.ArcGIS.Client.Tasks.Query();

            // Specify fields to return from query
            //query.OutFields.AddRange(new string[] { "STATE_NAME", "SUB_REGION", "STATE_FIPS", "STATE_ABBR", "POP2000", "POP2007" });
            //

            query.OutFields.Add("*");

            query.Geometry = args.Geometry;

            // Return geometry with result features
            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 = MyMap.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;
            }
            MyDrawSurface.IsEnabled = false;
        }

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

        private void GraphicsLayer_MouseEnter(object sender, GraphicMouseEventArgs args)
        {
                QueryDetailsDataGrid.Focus();
                QueryDetailsDataGrid.SelectedItem = args.Graphic;
                QueryDetailsDataGrid.CurrentColumn = QueryDetailsDataGrid.Columns[0];
                QueryDetailsDataGrid.ScrollIntoView(QueryDetailsDataGrid.SelectedItem, QueryDetailsDataGrid.Columns[0]);
        }

        private void GraphicsLayer_MouseLeave(object sender, GraphicMouseEventArgs args)
        {
                QueryDetailsDataGrid.Focus();
                QueryDetailsDataGrid.SelectedItem = null;
        }

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

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

        private void QueryDetailsDataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.MouseEnter += Row_MouseEnter;
            e.Row.MouseLeave += Row_MouseLeave;
        }

        void Row_MouseEnter(object sender, MouseEventArgs e)
        {
            (((System.Windows.FrameworkElement)(sender)).DataContext as Graphic).Select();
        }

        void Row_MouseLeave(object sender, MouseEventArgs e)
        {
            DataGridRow row = sender as DataGridRow;            
            Graphic g = ((System.Windows.FrameworkElement)(sender)).DataContext as Graphic;

            if (!QueryDetailsDataGrid.SelectedItems.Contains(g))
                g.UnSelect();
        }
    }   
}

0 Kudos
JenniferNery
Esri Regular Contributor
No problem.  We learn a lot from the forum too 🙂

You missed:
private ObservableCollection<FeatureLayer> layers = new ObservableCollection<FeatureLayer>();
0 Kudos
JMcNeil
Deactivated User
Thanks Jennifer!  With the help of another friend who pointed out that I did not need this code!

// Bind data grid to query results
            Binding resultFeaturesBinding = new Binding("LastResult.Features");
            resultFeaturesBinding.Source = queryTask;
            QueryDetailsDataGrid.SetBinding(DataGrid.ItemsSourceProperty, resultFeaturesBinding);
            Query query = new ESRI.ArcGIS.Client.Tasks.Query();


I finally got it working.  Super Sweet.  thanks for sticking with me and thanks to buddy Alan aka The Wolf!

As promised I'm going to do my best to help out a few lingering posts!

Thanks so much
0 Kudos
DavidAshton
Frequent Contributor
Jennifer and John,

Thanks for all the posts.  This is exactly what I was looking for and I also got it implemented with this forum.

I have a quick question, which I was hoping Jennfier could answer. 

If I'm populating my combo layers list with serveral layers that are either points, polys, and lines.  How can set the right fill (SimpleLine, Fill, or Marker) and keep the interaction with the table/graphic (hover over, row click to highlight, etc.) 

I can handle writing the VisualState Groups in xaml but as far as the code behind how should I change it.

It seems like I need to add a conditional statement in the  foreach (Graphic feature in featureSet.Features) loop.....as you can see below I tired to just add a SimpleLineSymbol ref but it breaks my FillSymbol and all the interaction.



    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 = MyMap.Layers["MySelectionGraphicsLayer"] as GraphicsLayer;


            if (featureSet != null && featureSet.Features.Count > 0)

                ResultsDisplay.Visibility = Visibility.Visible;

            {
                foreach (Graphic feature in featureSet.Features)
                {
                    feature.Symbol = LayoutRoot.Resources["ResultsFillSymbol"] as FillSymbol;
                   

                    feature.Symbol = LayoutRoot.Resources["DefaultLineSymbol"] as SimpleLineSymbol;
                    graphicsLayer.Graphics.Insert(0, feature);

                }
              ResultsDisplay.Visibility = Visibility.Visible;
            }
            MyDrawSurface.IsEnabled = false;
        }





Thanks again!

Great Post!

Sincerely,
Dave Ashton
0 Kudos
JMcNeil
Deactivated User
Dave,

What about writing a switch statement....something like:

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)

                   
                {

                    switch (feature.Attributes["Shape"].ToString())
                    {
                        case "Polygon":
                            feature.Symbol = LayoutRoot.Resources["DefaultFillSymbol"] as FillSymbol;
                            break;
                        case "Polyline":
                            feature.Symbol = LayoutRoot.Resources["DefaultLineSymbol"] as SimpleMarkerSymbol;
                            break;
                        case "Point":
                            feature.Symbol = LayoutRoot.Resources["Default.MarkerSymbol"] as SimpleLineSymbol;
                            break;
                    }



                    graphicsLayer.Graphics.Insert(0, feature);

       
                }
                ResultsDisplay.Visibility = Visibility.Visible;
            }
            MyDrawSurface.IsEnabled = false;
        }





I'm not sure if that will work.  I just copied Jen's code from above and add the switch there might be a few typos.

J.
0 Kudos
DavidAshton
Frequent Contributor
Dave,

What about writing a switch statement....something like:

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)

                   
                {

                    switch (feature.Attributes["Shape"].ToString())
                    {
                        case "Polygon":
                            feature.Symbol = LayoutRoot.Resources["DefaultFillSymbol"] as FillSymbol;
                            break;
                        case "Polyline":
                            feature.Symbol = LayoutRoot.Resources["DefaultLineSymbol"] as SimpleMarkerSymbol;
                            break;
                        case "Point":
                            feature.Symbol = LayoutRoot.Resources["Default.MarkerSymbol"] as SimpleLineSymbol;
                            break;
                    }



                    graphicsLayer.Graphics.Insert(0, feature);

       
                }
                ResultsDisplay.Visibility = Visibility.Visible;
            }
            MyDrawSurface.IsEnabled = false;
        }





I'm not sure if that will work.  I just copied Jen's code from above and add the switch there might be a few typos.

J.



John,

Thanks for the reply, looks like there is no typos and I get no errors but now the query doesn't work.  Nothing gets selected and nothing returns to the table?  Any other suggestions.

Dave
0 Kudos
JMcNeil
Deactivated User
Oh, Jennifer is working with featureSet not Graphic what about commenting out this and adding

    // switch (feature.Attributes["Shape"].ToString())

 switch (feature.Geometry.ToString())
               


What does that do for you?
0 Kudos