ThinkGeo.com    |     Documentation    |     Premium Support

Query by unique ID

Hello,


I downloaded the Desktop Evaluation Edition 5.0 recently and this is my first post. What I'm trying to do is query a shapefile using a unique ID. Specifically, it is an ID that is made up of section, block and lot numbers (e.g. Section=6, Block=7, Lot=34, ID=6734). I would like to use something similar to the GetFeatureById method, however it seems this only works by querying the generated feature ID. Is there a way to perform a query using a custom unique ID? Does anyone have any suggestions?


Thanks!


Bart



 Bart,


 


Welcome to MapSuite world.


 


You can create a custom FeatureSource and override the GetFeatureByIdsCore API with your code to get features by unique id, which FeatureSource you are using, I use ShapeFileFeatureSource as example below:


  public class CustomFeatureSource : ShapeFileFeatureSource
    {
        protected override Collection<Feature> GetFeaturesByIdsCore(IEnumerable<string> ids, IEnumerable<string> returningColumnNames)
        {
            Collection<Feature> result = new Collection<Feature>();
            // Write your code to get features by unique id

            return result;
        }
    }

 


Let me know if you have more questions.


 


Thanks,


James



Hi James,


Thank you for your help. What I have is an MDI form where the user can input a section, block, and lot number. These numbers are combined to form a unique ID. After the user enters these numbers and clicks a button, I would like the map to zoom into the selected lot which has the corresponding unique ID. I've included the code I have so far. Right now the "pID" variable is used to access the feature ID. Instead I would like this variable to access a column of unique IDs made up of the section, block, and lot numbers. I'm not sure I need a collection feature like you suggest as I only want to select one feature. I also do not know how to pass the "pID" variable to the CustomFeatureSource class. I'm a bit of a newbie with this. Thanks again! 


 



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.DesktopEdition;

namespace HelloWorld
{
    public partial class Form2 : Form
    {
        
        public Form2()
        {
            InitializeComponent();
        }

        private void Form2_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {

            string firstName = txtFirstName.Text;
            string lastName = txtLastName.Text;
            string section = txtSection.Text;
            string block = txtBlock.Text;
            string lot = txtLot.Text;
            string pID;
            WinformsMap winformsMap2 = (WinformsMap)this.Parent;

            InMemoryFeatureLayer inMemoryFeatureLayer = new InMemoryFeatureLayer();
            inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = new AreaStyle(new GeoSolidBrush(GeoColor.FromArgb(200, GeoColor.SimpleColors.PastelRed)));
            inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle.OutlinePen.Color = GeoColor.StandardColors.Red;
            inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;

            LayerOverlay layerOverlay = new LayerOverlay();
            layerOverlay.Layers.Add("QueryResultLayer", inMemoryFeatureLayer);
            winformsMap2.Overlays.Add("QueryResultLayer", layerOverlay);

            if (section.ToString() == "")
            {
                MessageBox.Show("Please enter Section number");
                winformsMap2.Overlays.Remove("QueryResultLayer");
                return;
            }
            else if (block.ToString() == "")
            {
                MessageBox.Show("Please enter Block number");
                winformsMap2.Overlays.Remove("QueryResultLayer");
                return;
            }
            else if (lot.ToString() == "")
            {
                MessageBox.Show("Please enter Lot number");
                winformsMap2.Overlays.Remove("QueryResultLayer");
                return;
            }
            else
            {
                pID = (section + block + lot);
            }

            selectLot(pID);
        }

        private void selectLot(string pID)
        { 
            WinformsMap winformsMap2 = (WinformsMap)this.Parent;
            ShapeFileFeatureLayer selection = new ShapeFileFeatureLayer(@"H:\temp2\elkland_lots.shp");
            InMemoryFeatureLayer queryResultLayer = (InMemoryFeatureLayer)winformsMap2.FindFeatureLayer("QueryResultLayer");

            selection.Open();
            Feature feature = selection.QueryTools.GetFeatureById(pID, ReturningColumnsType.NoColumns);
            RectangleShape rect = new RectangleShape();
            selection.Close();

            queryResultLayer.InternalFeatures.Clear();
            queryResultLayer.InternalFeatures.Add(feature.Id, feature);


            queryResultLayer.Open();
            rect = queryResultLayer.GetBoundingBox();
            queryResultLayer.Close();

            rect.ScaleUp(200);
            winformsMap2.CurrentExtent = rect;
            winformsMap2.Refresh();
        }


    }
}


Bart, 
  
 GetFeatureById will call GetFeatureByIdsCore internally and pass in a collection with one id, now I know your column names, so I finish the sample code for you: 
  public class CustomFeatureSource : ShapeFileFeatureSource 
     { 
         protected override Collection<Feature> GetFeaturesByIdsCore(IEnumerable<string> ids, IEnumerable<string> returningColumnNames) 
         { 
             Collection<Feature> result = new Collection<Feature>(); 
             Collection<Feature> features = GetAllFeaturesCore(returningColumnNames); 
             foreach (string id in ids) 
             { 
                 foreach (Feature feature in features) 
                 { 
                     string pId = feature.ColumnValues["section"] + feature.ColumnValues["block"] + feature.ColumnValues["lot"]; 
                     if (id == pId) 
                     { 
                         result.Add(feature); 
                     } 
                 } 
             } 
  
             return result; 
         } 
     } 
  
 Thanks, 
 James

Thanks James! You steered me in the right direction. Besides some error handling I have it working now. Thanks again for your help.


 



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.DesktopEdition;

namespace HelloWorld
{
    public partial class Form2 : Form
    {
        
        public Form2()
        {
            InitializeComponent();
        }

        private void Form2_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {

            string firstName = txtFirstName.Text;
            string lastName = txtLastName.Text;
            string section = txtSection.Text;
            string block = txtBlock.Text;
            string lot = txtLot.Text;
            string pID;
            WinformsMap winformsMap2 = (WinformsMap)this.Parent;

            InMemoryFeatureLayer inMemoryFeatureLayer = new InMemoryFeatureLayer();
            inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = new AreaStyle(new GeoSolidBrush(GeoColor.FromArgb(200, GeoColor.SimpleColors.PastelRed)));
            inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle.OutlinePen.Color = GeoColor.StandardColors.Red;
            inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;

            LayerOverlay layerOverlay = new LayerOverlay();
            layerOverlay.Layers.Add("QueryResultLayer", inMemoryFeatureLayer);
            winformsMap2.Overlays.Add("QueryResultLayer", layerOverlay);

            if (section.ToString() == "")
            {
                MessageBox.Show("Please enter Section number");
                winformsMap2.Overlays.Remove("QueryResultLayer");
                return;
            }
            else if (block.ToString() == "")
            {
                MessageBox.Show("Please enter Block number");
                winformsMap2.Overlays.Remove("QueryResultLayer");
                return;
            }
            else if (lot.ToString() == "")
            {
                MessageBox.Show("Please enter Lot number");
                winformsMap2.Overlays.Remove("QueryResultLayer");
                return;
            }
            else
            {
                pID = (section + block + lot);
            }

            selectLot(pID);
            
        }

        private System.Collections.ObjectModel.Collection<Feature> selectLot(string pID)
        {

            WinformsMap winformsMap2 = (WinformsMap)this.Parent;
            ShapeFileFeatureLayer selection = new ShapeFileFeatureLayer(@"H:\temp2\elkland_lots.shp");
            InMemoryFeatureLayer queryResultLayer = (InMemoryFeatureLayer)winformsMap2.FindFeatureLayer("QueryResultLayer");
            
            selection.Open();

            System.Collections.ObjectModel.Collection<Feature> result = new System.Collections.ObjectModel.Collection<Feature>();
            System.Collections.ObjectModel.Collection<Feature> features = new System.Collections.ObjectModel.Collection<Feature>();
            features = selection.QueryTools.GetFeaturesByColumnValue("pIDx", pID);
            
            foreach (Feature f in features)
            {
                if (f.ColumnValues["pIDx"] == pID)
                {
                    result.Add(f);
                }
                
            }

            queryLot(result, selection);
            return result;
        }

        private void queryLot(System.Collections.ObjectModel.Collection<Feature> result,ShapeFileFeatureLayer selection)
        {
            IEnumerator<Feature> enumer = result.GetEnumerator();
            bool x = enumer.MoveNext();
            x = true;
            Feature feat = enumer.Current;
            string fid = feat.Id;

            
            Feature feature = selection.QueryTools.GetFeatureById(fid.ToString(), ReturningColumnsType.NoColumns);
            WinformsMap winformsMap2 = (WinformsMap)this.Parent;
            InMemoryFeatureLayer queryResultLayer = (InMemoryFeatureLayer)winformsMap2.FindFeatureLayer("QueryResultLayer");

            RectangleShape rect = new RectangleShape();
            selection.Close();

            queryResultLayer.InternalFeatures.Clear();
            queryResultLayer.InternalFeatures.Add(feature.Id, feature);

            queryResultLayer.Open();
            rect = queryResultLayer.GetBoundingBox();
            queryResultLayer.Close();

            rect.ScaleUp(200);
            winformsMap2.CurrentExtent = rect;
            winformsMap2.Refresh();
        }
    }
}


Bart, 
  
 I am glad it’s working with you, and thanks for your code to let other users know how to do the same thing. 
  
 Feel free to let me know if you have more questions. 
  
 James