ThinkGeo.com    |     Documentation    |     Premium Support

Exception in GetBoundingBoxesByIds

Hello,

if I call GetBoundingBoxesByIds right after creation and refresh of the layers, I get following exception:

Der Index war außerhalb des Arraybereichs. (IndexOutOfRangeException)
bei ThinkGeo.MapSuite.Core.ShapeFileIndex.3UI=(Int32 recordIndex)
bei ThinkGeo.MapSuite.Core.ShapeFile.5xQ=(Int32 recordIndex)
bei ThinkGeo.MapSuite.Core.ShapeFileFeatureSource.GetBoundingBoxByIdCore(String id)
bei ThinkGeo.MapSuite.Core.FeatureSource.GetBoundingBoxById(String id)
bei ThinkGeo.MapSuite.Core.FeatureSource.GetBoundingBoxesByIds(IEnumerable1 ids) bei ThinkGeo.MapSuite.Core.QueryTools.GetBoundingBoxesByIds(IEnumerable1 ids)

What can I do to avoid this exception?

Regards,
Markus Meyer

Hi Markus Meyer,

I did some tests, and did not reproduce the exception.
I even test with invalid ‘ids’, then the API will return the ‘null’. As shown below:

This exception occurs in the process of reading the file contents, so I think we should check the parameters and shapefiles, if possible could you please share the shapefiles(including: XXX.shp XXX.shx XXX.idx XXX.ids XXX.dbf) and your ‘ids’ to us, we can work based on them.

Thanks,
Emil

Hi Emil,

as I figured out, the exception is also on my machine only reproducable if I rebuild up the map (readd and reconfigure the layers) while the original layers are still building up on screen (I have enabled multiple tiles).
So before we turn to the shapefiles, I would consider disabling user interaction as long as the tiles are still drawing. So is there a way to determine when the tiles are readily drawn?

Regards,
Markus

Hi Markus,

We can binding the Drawn of LayerOverlay for the TileType.SingleTile mode, but it doesn’t work for the TileType.MultipleTile scenario, in this case, we can use the WPF VisualTreeHelper to achieve this goals, please try the following code snippet.

var tiles = Helper.FindChildren<ThinkGeo.MapSuite.WpfDesktopEdition.Tile>(layerOverlay.OverlayCanvas); // layerOverlay.OverlayCanvas or wpfMap
if (tiles.Any(p => p.ImageSource == null || p.ImageSource.Width == 0))
{
    return;
}

public static class Helper
{
    public static List<T> FindChildren<T>(FrameworkElement fe) where T : FrameworkElement
    {
        var children = new List<T>();
        var childrenCount = VisualTreeHelper.GetChildrenCount(fe);
        for (int i = 0; i < childrenCount; i++)
        {
            var child = VisualTreeHelper.GetChild(fe, i);
            Walk<T>(child as FrameworkElement, children);
        }

        return children;
    }

    private static void Walk<T>(DependencyObject fe, List<T> items) where T : FrameworkElement
    {
        var targetType = typeof(T);
        if (fe.GetType() == targetType || fe.GetType().IsSubclassOf(targetType))
        {
            items.Add((T)fe);
        }
        else
        {
            var childrenCount = VisualTreeHelper.GetChildrenCount(fe);
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(fe, i);
                if (child != DependencyProperty.UnsetValue)
                {
                    Walk<T>(child, items);
                }
            }
        }

    }
}

Thanks,
Peter

Hi Peter,
thank you for your code snippet. After this solutions seems like a bit of a workaround, also because there is no real event happening and the readyness is only detectable by polling the state of the visual elements, maybe the disabling of interaction events is not the best solution.
Isn’t there a way to cleanly unload layers / overlays and add new ones even if the tiles of the old layers are still rendering asynchronously without getting an exception thrown? Would it be more stable if I reuse layers of the same type and assign new shapefiles to it if neccessary?
Regards,
Markus

Hi Markus,

Sorry for the delay. We can use the method I provided before to cleanly the overlays without getting exception. Attached is the sample shows how it works.

RemoveUnloadOverlaySample.zip (10.9 KB)

Hope it’s helped.

Thanks,
Peter

Hi Peter,
thank you for the code you provided, but I don’t quite understand how it works. For each overlay you check if all tiles have been loaded and in that case you don’t exchange the overlay. Is this right? I supppose the exception is caused by non-loaded tiles, so shouldn’t we exculde the overlays which are not loaded yet? In addition, I’d need to exchange all overlays, regardless if loading has finished or not.
Would it be a better way to reuse the ShapeFileFeatureLayer and simply change the properties of this object?
Regards,
Markus

Hi Markus,

Yes, you are right, it removes the overlay which is not loaded.

Sorry, I don’t understand “In addition, I’d need to exchange all overlays, regardless if loading has finished or not.” clearly. clearly.

Do you mean you want to remove the all the overlays and reuse the layers in them? If so, please try the following code instead.

private void btnRemoveUnloadOverlay_Click(object sender, RoutedEventArgs e)
    {
        for (int i = 0; i < Map1.Overlays.Count; i++)
        {
            var overlay = Map1.Overlays[i] as LayerOverlay;
            if (overlay != null)
            {
                LayerOverlay layerOverlay = new LayerOverlay();

                for (int j = 0; j < overlay.Layers.Count; j++)
                {
                    var layer = overlay.Layers[j];
                    overlay.Layers.Remove(layer);
                    layerOverlay.Layers.Add(layer);
                }

                Map1.Overlays.Add(layerOverlay);
                Map1.Overlays.RemoveAt(i);
            }

        }

      
        Map1.Refresh();
    }

If something misunderstood, Could you please provide us a sample to illustrate what you want?

Thanks
Peter