Table of Contents

Class S100DynamicSourceHost

Namespace
EncDotNet.S100.Renderers.Mapsui.DynamicSources
Assembly
EncDotNet.S100.Renderers.Mapsui.dll

Reusable host that draws IDynamicFeatureSource instances on a map's overlay tier and exposes them as an IS100DynamicSourceRegistry.

public sealed class S100DynamicSourceHost : IDisposable, IS100DynamicSourceRegistry
Inheritance
S100DynamicSourceHost
Implements
Inherited Members

Remarks

For each registered source the host: (1) resolves an IDynamicFeatureRenderer via the caller-supplied resolver keyed by RendererKey, falling back to DefaultDynamicFeatureRenderer when the key is null or unresolved; (2) attaches a backing Mapsui.Layers.MemoryLayer to AddOverlayLayer(ILayer); (3) subscribes to Changed and marshals updates onto the map thread; and (4) rebuilds the layer's features on each (debounced) change.

This is the reusable extraction of the Viewer's dynamic-source overlay glue (issue #512, step 8). It depends only on Mapsui and the renderer-neutral IDynamicFeatureSource contract — not on Avalonia, a view model, or a DI container:

  • Marshalling is a caller-injected Action<T>. The default runs inline (synchronously), suitable for headless or single-threaded hosts; a UI host passes a dispatcher marshal (e.g. one that posts to the UI thread).
  • Renderer resolution is a caller-injected Func<T, TResult> so the host needs no IServiceProvider; a DI host passes a resolver over its keyed services.

v1 deliberately ignores the global time slider.

Constructors

S100DynamicSourceHost(IMapsuiOverlayLayerHost, Func<string?, IDynamicFeatureRenderer?>?, Action<Action>?, ILogger<S100DynamicSourceHost>?, TimeSpan?)

Creates a new dynamic-source host.

public S100DynamicSourceHost(IMapsuiOverlayLayerHost overlayHost, Func<string?, IDynamicFeatureRenderer?>? rendererResolver = null, Action<Action>? marshal = null, ILogger<S100DynamicSourceHost>? logger = null, TimeSpan? coalesceWindow = null)

Parameters

overlayHost IMapsuiOverlayLayerHost

Target overlay band. The map must already be initialised (basemap added) before any source is registered when the host's overlay-insert policy depends on it.

rendererResolver Func<string, IDynamicFeatureRenderer>

Resolves an IDynamicFeatureRenderer for a source's RendererKey. Returns null to fall back to the default renderer. null for the whole delegate always uses the default renderer.

marshal Action<Action>

Optional marshal onto the map thread. Defaults to inline (synchronous) execution. A UI host passes a dispatcher-backed marshal.

logger ILogger<S100DynamicSourceHost>

Optional logger.

coalesceWindow TimeSpan?

Minimum interval between full rebuilds of a single source's layer. null uses the default 250 ms. Pass Zero to disable the throttle and keep rebuilds synchronous (used by tests).

Properties

Sources

Currently registered sources in registration order. Stable across visibility toggles; updated on register / dispose.

public IReadOnlyList<DynamicSourceRegistrationInfo> Sources { get; }

Property Value

IReadOnlyList<DynamicSourceRegistrationInfo>

Methods

Dispose()

Unregisters all sources and detaches their overlay layers. Safe to call from any thread.

public void Dispose()

GetVisible(string)

Returns the current visibility for the source identified by sourceId. Defaults to true for unregistered ids so seeding a not-yet-registered id is a no-op that still round-trips its eventual default.

public bool GetVisible(string sourceId)

Parameters

sourceId string

Returns

bool

GetVisibleSourceInstances()

Snapshot of currently registered, currently visible source instances, in registration order. Hidden sources are excluded. Returns source instances (rather than the DynamicSourceRegistrationInfo projection) so a pick path can read CurrentFeatures directly.

public IReadOnlyList<IDynamicFeatureSource> GetVisibleSourceInstances()

Returns

IReadOnlyList<IDynamicFeatureSource>

HitTest(MPoint, double)

Hit-tests every currently-visible source at a geographic click point and returns the matches ordered by ascending distance (a click inside a rendered vessel hull reports distance 0). Hidden sources are excluded, so a click on a hidden target never appears in the result.

public IReadOnlyList<DynamicSourceHit> HitTest(MPoint mapPoint, double resolution)

Parameters

mapPoint MPoint

Click position in Spherical Mercator world units.

resolution double

Map units per device pixel at the current zoom.

Returns

IReadOnlyList<DynamicSourceHit>

Hits ordered by ascending distance from the click (possibly empty).

Register(IDynamicFeatureSource)

Registers a source. Resolves IDynamicFeatureRenderer keyed by source.Metadata.RendererKey; falls back to the default renderer when the key is null or unresolved. The returned IDisposable unregisters the source and detaches its overlay layer when disposed.

public IDisposable Register(IDynamicFeatureSource source)

Parameters

source IDynamicFeatureSource

Returns

IDisposable

SetVisible(string, bool)

Sets the visibility for the source identified by sourceId. May be called before the source registers (seeding from persisted settings). Idempotent; fires SourcesChanged only on a real transition.

public void SetVisible(string sourceId, bool visible)

Parameters

sourceId string
visible bool

Events

SourcesChanged

Raised when Sources changes (register / dispose) or when SetVisible(string, bool) transitions a source's visibility. Raised on the host's map thread through the host's marshal.

public event Action? SourcesChanged

Event Type

Action