Hello Khalil, and thanks for your answer.
1/ This exception was not due to a multithread operation. Actually, I noticed the following :
private void DrawCoreInternal(GeoCanvas canvas, Collection<SimpleCandidate> labelsInAllLayers, RectangleShape worldExtent, WriteableBitmap image, Collection<Feature> features)
{
if (!image.Dispatcher.CheckAccess())
throw new KubaTechException(“Invalid UI Thread ! Consider using Dispatcher.BeginInvoke() instead !”);
lock (image)
{
canvas.BeginDrawing(image, worldExtent, GeographyUnit.Meter);
this.OpenLayer();
try
{
// Let’s write a little trick to have the right features in the GetFeaturesForDrawingCore() method
// We will save the feature to draw in a dictionary in the FeatureSource, and the key of the dictionary is the worldExtent object.
CustomWfsFeatureSource.FeaturesToDraw = features;
base.DrawCore(canvas, labelsInAllLayers);
CustomWfsFeatureSource.FeaturesToDraw = null;
}
finally
{
this.CloseLayer();
canvas.EndDrawing();
}
}
}
protected override void DrawCore(GeoCanvas canvas, Collection<SimpleCandidate> labelsInAllLayers)
{
var worldExtent = canvas.CurrentWorldExtent;
var image = (WriteableBitmap)canvas.NativeImage;
GetFeaturesInsideBoundingBoxCore(
delegate(Collection<Feature> features, AsynchronServiceOperationResult result)
{
// canvas.CurrentWorldExtent and canvas.NativeImage are not valid anymore when coming back from the asynch call.
// I don’t understand why, but the canvas object is modified.
// => To solve this we have to use the original objects to draw the features on the map
if (result.Sucessful && features.Count > 0)
{
image.Dispatcher.BeginInvoke(() => DrawCoreInternal(canvas, labelsInAllLayers, worldExtent, image, features));
}
}, worldExtent);
}
Before the call of the GetFeaturesInsideBoundingBoxCore asynchron method, the canvas object seems to be valid. But when we enter the callback method, the canvas.CurrentWorldExetnt throws an exception, and the canvas.NativeImage is null. Thus I cannot call the canvas.BeginDrawing() method with those parameters. In the previous code, I tried to remember the original values and use them to call BeginDraw(), but I’m having another problem.
2/ I override the DrawCore method ni order to insert an asynchron call to load features from a server. Overriding the GetFeaturesForDrawingCore() method was a good tip, the GetAllFeaturesCore() method is not called any more.
But the load of the features is made by the DrawCore() method. So I have the loaded features in the delegate. Then when I call base.DrawCore(canvas, labelsInAllLayers), the GetFeaturesForDrawingCore() method of the featureSource is called, and must send a list of features…
I think it should be to the GetFeaturesForDrawingCore() to load the daat synchron, but this is not possible, because it has a erturn value, and no callback.
Si what I’m doing is :
- override Layer.DrawCore in order to load feature.
- In the callback, I somehow set into the FeatureSource the Feature list.
- Then I call the base.DrawCore() method.
- The overriden FeatureSource.GetFeaturesForDrawingCore() sends as return value the list of the loaded features.
- And then… here is the problem… I get these ArgumentException :
"Ein Element mit dem gleichen Schlüssel wurde bereits hinzugefügt."
Translation : An element with the same Id already exists.
StackTrace :
bei System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
bei System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
bei System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
bei ThinkGeo.MapSuite.SilverlightCore.FeatureSource.GetFeaturesForDrawing(RectangleShape boundingBox, Double screenWidth, Double screenHeight, IEnumerable`1 returningColumnNames)
bei ThinkGeo.MapSuite.SilverlightCore.FeatureLayer.DrawCore(GeoCanvas canvas, Collection`1 labelsInAllLayers)
bei CadRz.Kuba.Framework.Presentation.Web.Gis.Wfs.CustomWfsFeatureLayer.DrawCoreInternal(GeoCanvas canvas, Collection`1 labelsInAllLayers, RectangleShape worldExtent, WriteableBitmap image, Collection`1 features)
I think I’m doing something wrong, but I cannot notice exaclty why.
The first problem for me is :
- Am i overriding the right methods in order to do what I’m trying to do ?
If yes :
- Why is the canvas.NativeImage null and why does Canvas.CurrentWorldExtent throw an Exception in the callback ?
- Is it right to remeber the original values for those properties, and to work with them ?
- Why do I get the ArgumentException ? I tried with only 1 feature loaded from the server, and I get the same exception. I really don’t understand.
I know there is a WfsOverlay, but at start I didn’t want to use it, because even if I called this a “WFS”, it hasn’t any of the standard of a right WFS Service. It’ simply a custom service that sends serialized data, and those data are desiarialized client side, and featuers are created clientside too.
Furthermore, I used a solution overriding a FeatureLayer for the WpfClient, and it worked perfectly. Some code is shared between the 2 client (Wpf and Silverlight), and I wanted to make it simple.
Therefore I would prefer implementing a solution with FeatureLayer. But if you says me your WFS Overlay can handle a total custom server with custom request like mine, I will consider using it.
Thanks again for you answer,
Guillaume.