Carlos, one option for you is to replace your map with an instance of this class and hook into its DrawingProgressChanged event. Since map uses main dispatcher, it will be hard to say when it is busy as other parts of your UI are also sharing same dispatcher. BTW, is it not about 9 PM out there?
public class ExtendedWpfMap : WpfMap
{
/// <summary>
/// Occurs when drawing progress changed.
/// </summary>
public event EventHandler<DrawingProgressChangedExtendedWpfMapEventArgs> DrawingProgressChanged;
public ExtendedWpfMap()
: base()
{
Overlays.CollectionChanged += Overlays_CollectionChanged;
this.ComputeCurrentProgressUsingBuffer = true;
}
/// <summary>
/// Set this to true if you want draw progress to
/// include progress of buffer tiles. Default is true.
/// Setting this property to false requires an expensive
/// Intersects operation to find out which tiles are within
/// visible map extent. While this works, it is not recommended.
/// </summary>
public bool ComputeCurrentProgressUsingBuffer { get; set; }
protected virtual void OnDrawingProgressChanged(DrawingProgressChangedExtendedWpfMapEventArgs e)
{
if (DrawingProgressChanged != null)
{
DrawingProgressChanged(this, e);
}
}
private void Overlays_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
int newCount = e.NewItems.Count;
TileOverlay tileOverlay = null;
foreach (Overlay overlay in e.NewItems)
{
tileOverlay = overlay as TileOverlay;
if (tileOverlay != null && tileOverlay.TileType != TileType.SingleTile)
tileOverlay.DrawTilesProgressChanged += tileOverlay_DrawTilesProgressChanged;
else
{
if (newCount == 1 && tileOverlay != null)
{
tileOverlay.Drawn += OnSingleTileDrawn;
}
}
}
break;
case NotifyCollectionChangedAction.Remove:
newCount = e.OldItems.Count;
foreach (Overlay overlay in e.OldItems)
{
tileOverlay = overlay as TileOverlay;
if (tileOverlay != null && tileOverlay.TileType != TileType.SingleTile)
tileOverlay.DrawTilesProgressChanged -= tileOverlay_DrawTilesProgressChanged;
tileOverlay.Drawn -= OnSingleTileDrawn;
var layerO = overlay as LayerOverlay;
if (layerO != null)
{
foreach (var layer in layerO.Layers)
{
layer.IsVisible = false;
layer.Close();
}
layerO.Layers.Clear();
}
overlay.Dispose();
}
break;
default:
break;
}
}
void OnSingleTileDrawn(object sender, DrawnOverlayEventArgs e)
{
OnDrawingProgressChanged(new DrawingProgressChangedExtendedWpfMapEventArgs(100, null));
}
int previousPercentage = 0;
private void tileOverlay_DrawTilesProgressChanged(object sender, DrawTilesProgressChangedTileOverlayEventArgs e)
{
TileOverlay currentTileOverlay = (TileOverlay)sender;
currentTileOverlay.OverlayCanvas.Tag = e.ProgressPercentage;
IEnumerable<TileOverlay> tileOverlays = Overlays.OfType<TileOverlay>()
.Where((to => to.TileType != TileType.SingleTile))
.Where(to => to.OverlayCanvas.Tag != null);
if (ComputeCurrentProgressUsingBuffer)
ComputeCurrentDrawProgressUsingBuffer(tileOverlays);
else
ComputeCurrenDrawProgressWithoutBuffer(tileOverlays);
}
private void ComputeCurrenDrawProgressWithoutBuffer(IEnumerable<TileOverlay> tileOverlays)
{
var tilesInVisibleExtent = tileOverlays.SelectMany(o => ((Canvas)o.OverlayCanvas.Children[0]).Children
.OfType<ThinkGeo.MapSuite.WpfDesktopEdition.Tile>()
.Where(tile => o.MapArguments.CurrentExtent.Intersects(tile.TargetExtent)));
var totalTiles = tileOverlays.SelectMany(o => ((Canvas)o.OverlayCanvas.Children[0]).Children
.OfType<ThinkGeo.MapSuite.WpfDesktopEdition.Tile>());
int total = tilesInVisibleExtent.Count();
int currentProgress = 100;
if (total != 0)
{
var tilesLoaded = tilesInVisibleExtent.Where(tile => tile.IsOpened);
currentProgress = tilesLoaded.Count() * 100 / total;
}
if (Math.Abs(currentProgress - previousPercentage) >= 5 || currentProgress == 100 && previousPercentage != 100)
{
previousPercentage = currentProgress;
OnDrawingProgressChanged(new DrawingProgressChangedExtendedWpfMapEventArgs(currentProgress, null));
}
}
private void ComputeCurrentDrawProgressUsingBuffer(IEnumerable<TileOverlay> tileOverlays)
{
int total = tileOverlays.Count();
int currentProgress = 100;
if (total != 0)
{
int progress = 0;
foreach (TileOverlay tileOverlay in tileOverlays)
{
if (tileOverlay.OverlayCanvas.Tag != null)
{
var overlayProgress = (int)tileOverlay.OverlayCanvas.Tag;
progress += overlayProgress;
}
}
currentProgress = progress / total;
if (Math.Abs(currentProgress - previousPercentage) >= 5 || currentProgress == 100 && previousPercentage != 100)
{
previousPercentage = currentProgress;
OnDrawingProgressChanged(new DrawingProgressChangedExtendedWpfMapEventArgs(currentProgress, null));
}
}
}
#region Map extensions
public bool ContainsLayer(string layerName)
{
return this.Overlays.FirstOrDefault(o => string.CompareOrdinal(o.Name, layerName) == 0) != null;
}
public bool SafelyRefresh(Overlay overlay)
{
bool successfullyRefreshed = false;
try
{
this.Refresh(overlay);
successfullyRefreshed = true;
}
catch (Exception ex)
{
ExceptionPolicy.HandleException(ex, ExceptionHandlingPolicyNames.LogPolicy);
}
return successfullyRefreshed;
}
public bool SafelyRefresh()
{
bool successfullyRefreshed = false;
try
{
this.Refresh();
successfullyRefreshed = true;
}
catch (Exception ex)
{
ExceptionPolicy.HandleException(ex, ExceptionHandlingPolicyNames.LogPolicy);
}
return successfullyRefreshed;
}
public bool SafelyRefresh(IEnumerable<Overlay> overlays)
{
bool successfullyRefreshed = false;
try
{
this.Refresh(overlays);
successfullyRefreshed = true;
}
catch (Exception ex)
{
ExceptionPolicy.HandleException(ex, ExceptionHandlingPolicyNames.LogPolicy);
}
return successfullyRefreshed;
}
public IEnumerable<FeatureLayer> GetFeatureLayers()
{
return GetFeatureLayers(null);
}
public IEnumerable<FeatureLayer> GetFeatureLayers( IEnumerable<string> overlaysToExclude)
{
var featureLayers = new Collection<FeatureLayer>();
IEnumerable<LayerOverlay> layerOverlays = null;
layerOverlays = this.Overlays.Where(o => !o.IsEmpty && o.IsVisible).OfType<LayerOverlay>();
if (overlaysToExclude != null)
layerOverlays = layerOverlays.Where(lo => lo != null && !overlaysToExclude.Contains(lo.Name));
else
layerOverlays = layerOverlays.Where(lo => lo != null);
var _featureLayers = layerOverlays.SelectMany(l => l.Layers).OfType<FeatureLayer>();
featureLayers.AddRange(_featureLayers);
featureLayers.Add(this.EditOverlay.EditShapesLayer);
return featureLayers;
}
#endregion
}