ThinkGeo.com    |     Documentation    |     Premium Support

GeoDbf

One of the feature requirements we have is to display a table with all the DBF rows associated with a displayed shapefile, and then be able to click on a row and have the corresponding shape highlighted on the map. A simple example would be to load your Countries02.shp file and somehow also load and display its associated dbf file. Then you could click on row 7 (Canada) which would cause Canada to be highlighted on the map. So my questions are:



        
  1. Would you recommend your GeoDbf class for this? It would be great if it could be databound to a XAML grid view or similar. If not, I could iterate through the rows and create my own WPF ObservableCollection from the data.

  2.     
  3. How do I tell an already loaded and rendered map with a ShapeFileFeatureLayer to highlight one of its polygons? I can see in your various examples how to do this at load time (via ValueStyle for example), but how can it be done at runtime? Or can a ValueStyle object be applied to an already loaded map?


Thank you for your help!



Thaine: 



One way of doing this is as follows: 



-  When loading each ShapeFile, add a FeatureColumn that would represent the layer's clicked state to the layer's FeatureSource. 

-  Define a ValueStyle bound to this this FeatureColumn 



After resolving the Shapefile a user clicked. 



- Search for corresponding ShapeFileFeatureLayer and modify that FeatureColumn created above.. 

- Next call map.Refresh() 



This is mostly theoretical but should help. 



That’s great! Very simple. What about GeoDbf? Is that the preferred DBF class? Or should I write or find my own? Is there another WpfMap DBF class that exposes an iterator or a collection?

Hello Thaine, 
  
 Thanks for Klaus, very good instruction. 
  
 GeoDbf is the class which we recommend to use for operation .dbf file. you don’t need write a own one. The GeoDbf is in the MapSuiteCore, that means every products can use it, including WpfDesktopEdtion. You can easily get the dbf records by some properties, then loop the records result to get the data details. Also you can do the same thing using ShapeFileFeatureSource, but the featureSource is use GeoDbf too, so in efficiency, use GeoDbf directly is much better. 
  
 Regards, 
  
 Gary

Hi Klaus, Gary, 



Thank you for your pointers here. I am having trouble finding out how to accomplish what you suggest within the API, to which I am new. Could either of you provide some sample code that would do the steps you mentioned above? I have many unanswered questions as I try to implement this. For example,  

1. When you say 'FeatureColumn," do you mean "FeatureSourceColumn?" 

2. How does one access the FeatureSourceColumns of a ShapeFileFeatureLayer? Do you use layer.FeatureSource.GetColumns()?


3. Does one add a column like this? 


worldLayer.FeatureSource.GetColumns().Add(new FeatureSourceColumn("Selected"));


But then how does one initialize it's value? Or specify it's data type?


Is there a sample that you can point me to that manipulates custom FeatureColumn/FeatureSourceColumns?


 


Thank you for your help as I learn the API. 



Best regards, 

Thaine



Hello Thaine, 
  
 1) Yes. 
  
 2) Yes, you have the right way, also you can use layer.QueryTools.GetColumns(), it’s almost the same. 
  
 3) Sorry I’m not sure you want to add a column or add a record? Your code looks like you want to add a column, but the ShapeFileFeatureLayer’s FeatureSourceColumn is connect to the Dbf file, so you can’t edit it in the ShapeFileFeatureLayer directly, the only way you can add it is in some dynamic way, add it in the memory. You can see the HowDoISamples —>Querying Feature Layers—>Add my own custom data in a FeatureLayer. 
  
 Any more questions just let us know. 
  
 Regards, 
  
 Gary

Hello Gary, 



I finally found that sample, but I don't see how that will help to accomplish the original suggestion from Klaus which was:



        
  1. When loading each ShapeFile, add a FeatureColumn that would represent the layer's clicked state to the layer's FeatureSource. 

  2.     
  3. Define a ValueStyle bound to this this FeatureColumn


After resolving the Shapefile a user clicked:



        
  1. Search for corresponding ShapeFileFeatureLayer and modify that FeatureColumn created above.

  2.     
  3. Next call map.Refresh() 


So I am trying to figure out the first half of this; I am trying the following:


 


m_worldLayer.FeatureSource.Open();
m_worldLayer.FeatureSource.GetColumns().Add(new FeatureSourceColumn("Selected", "String", 10));
foreach (Feature f in m_worldLayer.FeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns))
{
f.ColumnValues.Add("Selected", "No");
}
ValueStyle valueStyle = new ValueStyle();
valueStyle.ColumnName = "Selected";
valueStyle.ValueItems.Add(new ValueItem("Yes", AreaStyles.CreateSimpleAreaStyle(GeoColor.StandardColors.Green, GeoColor.StandardColors.Black)));
valueStyle.ValueItems.Add(new ValueItem("No", AreaStyles.Country1));
m_worldLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(valueStyle);


 

 


But this code does not actually add the new column to the Features that are loaded into memory. GetAllFeatures fails saying there is no column by that name. How can I dynamically add that column to each feature?




Thank you, 

Thaine



Thaine, my response was mostly theoretical to give you an idea on what you will need to do.  In practice, however, is may be overly simplistic as you probably cannot modify the schema (adding a new FeatureSourceColumn) on the FeatureSource of a ShapeFileFeatureLayer.   



You will need to create a separate InMemoryFeatureLayer to be able add a new FeatureSourceColumn.  But before doing this, clarify one more thing:  How will you determine which of the polygons on the selected ShapeFileFeatureLayer to highlight?  Will it be the same polygon or a different one based on some other criteria?



Hi Klaus,


Here is an example of what we need to do:



        
  • Consider the Countries02.shp as the sample shapefile.

  •     
  • Assume that we create a UI option for the user to select a key column such as CNTRY_NAME as an example

  •     
  • The associated Countries02.dbf file is loaded into a WPF GridView control

  •     
  • The user clicks on a row in the GridView and the click event handler gets the selected key from the row (for example CNTRY_NAME)

  •     
  • Using this key, the code finds the matching polygon, sets the previously added "Selected" column in the polygon's feature object to "Yes"

  •     
  • The map is programmiatically refreshed resulting in the polygon's color changing to the highlight color


This seems like an extremely straightforward task, though I am finding it extremely complicated to figure out.


Thank you for your help!


Thaine



Then there may be a simpler approach as follows: 
  
 1. Add an InMemoryFeatureLayer to your Overlays collection for highlighting. 
 2. Set is Styles accordingly. 
 3. Use the information from your click event handler to create a query that can be used to find the feature the user clicked on. 
 4. Once you have this feature, clear the InternalFeatures collection of your highlight layer and add this new feature. 
 5. Refresh map. 
  
 - For reference material on how to query a ShapeFileFeatureLayer, look at the sample CS HowDoISamples/Querying Feature Layers/SqlQueryAFeatureLayer. 
 -  CS HowDoISamples/Getting Started/FindTheFeatureAUserClickedOn should help on how to create a layer for highlighting features. 
  
 Hope this helps. 
  


Thank you Klaus for this new suggestion, and especially for the relevant samples. I will explore this new approach. 
  
 Thaine

Klaus, thanks for the detailed instruction.