ThinkGeo.com    |     Documentation    |     Premium Support

CustomColumnFetch not getting called

In an attempt to resolve another map WinformsMap issue, we updated to the latest production build (9.0.0.58).  I’ve run into several problems as a consequence of marking classes as obsolete, apparently providing equivalent functionality otherwise (mainly [Style].CreateSimpleStyles and InMemoryFeatureLayer.Columns).  Once I got through those, I found that somehow custom label text is also now broken.  Creating a reduced case is going to be a real pain, so hopefully the fix will be obvious due to known changes from 8.x to 9.x.



In short, I have an InMemoryFeatureLayer to which I have added a collection of features, with an appropriate text style for the labels.  and hook the event for providing custom label text and bound to a custom column name.  

layer.FeatureSource.CustomColumnFetch += CustomColumnFetchForLabel;



Everything works fine when our application starts, the map displays, and the labels are correct.



However, after loading, the user can change the labels specified within our application.  I correctly record the users selection within our state and call refresh on the overlay containing the layer that has the labels to update.  But the CustomColumnFetch event does not fire.  It works correctly previous to your 9.0 update.



One more thing, just as a test I changed it to refresh the entire map object, not just the overlay, and it still does not call the indicated event.

Hi Russ, 



It looks the CustomColumnFetch event will only be fired if target feature don’t contains the new column, but after you assign that value once, it won’t be fired again. 



So my suggestion here is, 



1. Delete all added column before you modify the label, then the event will be fired again. 



2. Directly modify the value in feature because you are using InmemoryFeatureLayer. 



Regards, 



Don







private void WpfMap_Loaded(object sender, RoutedEventArgs e)
        {
            Map1.MapUnit = GeographyUnit.DecimalDegree;
            Map1.CurrentExtent = new RectangleShape(-10, 10, 10, -10);



            InMemoryFeatureLayer layer = new InMemoryFeatureLayer();
            layer.Open();



            layer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.City1;
            layer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.City1(“customlabel”);
            layer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            
            Feature testFeature = new Feature(0, 0);            
            layer.InternalFeatures.Add(testFeature);



            layer.FeatureSource.CustomColumnFetch += CustomColumnFetchForLabel;






            LayerOverlay worldOverlay = new LayerOverlay();
            worldOverlay.Layers.Add(“WorldLayer”, layer);
            Map1.Overlays.Add(“WorldOverlay”, worldOverlay);



            worldOverlay.TransitionEffect = TransitionEffect.None;



            Map1.Refresh();
        }



        void CustomColumnFetchForLabel(object sender, CustomColumnFetchEventArgs e)
        {
            if (e.ColumnName == “customlabel”)
            {
                InMemoryFeatureLayer layer = (Map1.Overlays[“WorldOverlay”] as LayerOverlay).Layers[“WorldLayer”] as InMemoryFeatureLayer;
                Feature currentFeature = layer.QueryTools.GetFeatureById(e.Id, ReturningColumnsType.AllColumns);
                e.ColumnValue = “The label”;
            }
        }

That is similar to what I originally had, but performance was not acceptable.  The only difference for my old implementation was that the information needed to provide the label (in any format) was actually stashed in the feature instances.  So once I had the feature, I could format the correct string where you have "the label".  But it could be quite slow, so I changed it to my own hash table lookup and performance improvement was huge. 
  
 But none of that helps me now. 
  
 The real problem for me is that the event method CustomColumnFetchForLabel simply does not get called after the first values are returned.  When the user selects another label format in our external UI, I need a way to make the map update the label contents (almost) immediately for between 1000 and 100000 feature points.  In the past, simply calling refresh with the overlay containing the layers which in turn contain those dynamic points, and your component would call CustomColumnFetchForLabel for each point allowing me to return the newly constructed string.  With 9.x, how do I get CustomColumnFetchForLabel called as needed?  The user generally chooses the format they need and rarely change it afterward, so for now our workaround is to select the new format and restart the application.  That may work for internal testing, but for a public release.  Most may not change it frequently, but when they do we cannot require them to restart the program.

Hi Russ, 
  
 I think you should want to modify the column format in this event: inmemoryFeatureLayer.DrawingFeatures 
  
 Or you can override the GetFeaturesForDrawingCore function of MyInMemoryFeatureSource which inherited from InMemoryFeatureSource, and assign it to your inmemoryFeatureLayer. 
  
 Wish that’s helpful. 
  
 Regards, 
  
 Don

Modifying the column values in DrawingFeatures seems to produce no change in the labels that are drawn.   
  
 The other solution requires a lot more work to test.   
  
 But it seems there should be some less convoluted way to change the label.  They way I did it in the previous version (based on one of your samples I believe) made sense and worked well.  Why make such an intrusive change that breaks existing code?  This breaking change seems to be more of a bug than an intentional feature update.

Hi Russ, 
  
 The code as below works for me, it can replace the feature label when user click button. You can see the layer.DrawingFeatures works for this scenario. 
  
 
  private void ShowHideLayer_Load(object sender, EventArgs e)
        {
            winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
            winformsMap1.BackgroundOverlay.BackgroundBrush = new GeoSolidBrush(GeoColor.GeographicColors.ShallowOcean);

            InMemoryFeatureLayer layer = new InMemoryFeatureLayer();
            layer.InternalFeatures.Add(new Feature(0, 0));
            layer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.Capital1;
            layer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.Capital1("text");
            layer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            layer.DrawingFeatures += layer_DrawingFeatures;
            layer.Open();

            LayerOverlay staticOverlay = new LayerOverlay();
            staticOverlay.Layers.Add("WorldLayer", layer);

            winformsMap1.Overlays.Add("WorldOverlay", staticOverlay);

            winformsMap1.CurrentExtent = new RectangleShape(-10, 10, 10, -10);
            winformsMap1.Refresh();
        }

        string labelString = "1st label";

        void layer_DrawingFeatures(object sender, DrawingFeaturesEventArgs e)
        {
            Feature f = e.FeaturesToDraw[0];
            if (f.ColumnValues.ContainsKey("text"))
            {
                f.ColumnValues["text"] = labelString;
            }
            else
            {
                f.ColumnValues.Add("text", labelString);
            }
            e.FeaturesToDraw[0] = f;
        }

        private void cbkShowLayer_CheckedChanged(object sender, EventArgs e)
        {
            labelString = "2nd label";

            winformsMap1.Refresh(winformsMap1.Overlays["WorldOverlay"]);
        }

 
 
  
 Regards, 
  
 Don

Thanks.  That provides a basis for re-implementing what worked in the previous version.   
  
 However, why was it changed?  I need to go back and look at the version changes, but I don’t remember this breaking change being listed, much less a suggestion for how to adapt to the breaking change.

Hi Russ, 
  
 Today I talked with our developer, it looks we hadn’t modified the CustomColumnFetch, it caused by an performance enhancement from GetAllFeatures. 
  
 Development team will look into whether that enhancement cause some other issue. 
  
 I think maybe this change won’t be roll back, so please try my solution for DrawingFeatures for now. 
  
 Regards, 
  
 Don 
  


No problem, thanks for the explanation.  I have already converted to function as you suggested.   
  
 But I was most curious why it wasn’t listed clearly as a breaking change with clear instruction on how to proceed.  If I didn’t miss something, that information is nowhere but in this thread.  Posting that with the change log would have avoided this whole discussion.

Hi Russ, 
  
 I am glad to hear you convert that succeed. I am sorry for that make trouble for you, but it looks we don’t have a breaking change list, only the API change log. I think it’s a good suggestion, I will let our release manager knows it. 
  
 Regards, 
  
 Don