Skip to content
Shiny Controls v1.0 - The Ultra Control Suite for .NET MAUI & BlazorO...M...G!

ShinyImage

An image that always shows something: placeholder artwork, a loading ring, the image itself, or error artwork. On MAUI it loads through an IImageService that caches to memory and disk, caps how many downloads run at once, and collapses concurrent requests for the same URI into a single download — and it renders SVG as vectors rather than as a rasterized bitmap. On Blazor it streams through fetch so the ring can report a real percentage.

  • NuGet downloads for Shiny.Maui.Controls
  • NuGet downloads for Shiny.Blazor.Controls
Frameworks
.NET MAUI
Blazor

MAUI (iOS)

Loaded, error artwork, placeholder Custom loading template Queued downloads
A loaded photo, the built-in error glyph for a 404, and the placeholder section A LoadingTemplate replacing the ring, bound to the live progress Thirty images sharing a small download budget

Blazor

The ring Placeholder behind the ring Error artwork Browser-loaded thumbnails
The progress ring while a photo streams in Placeholder artwork staying put under the ring, plus a custom LoadingContent Error artwork after an HTTP 404 DisableProgress handing thumbnails straight to the browser

MAUI

<shiny:ShinyImage Uri="{Binding AvatarUrl}"
PlaceholderImage="avatar_placeholder.png"
ErrorImage="broken_image.png"
Aspect="AspectFill"
HeightRequest="120" />

Blazor

<ShinyImage Uri="@PhotoUrl"
PlaceholderUri="/images/placeholder.svg"
Alt="Profile photo"
ObjectFit="cover" />

The placeholder sits behind the loading ring rather than being swapped out for it, so a blurred thumbnail with a progress ring over it is two properties.

There is no IsIndeterminate to set. Percent is null in exactly the cases where a percentage would be a lie:

  • the request is queued, waiting for a download slot — nothing has been measured yet
  • the response carried no Content-Length (chunked transfer, or a proxy that stripped it)
  • the source is local, so there is nothing to stream and nothing to measure
  • the browser is loading the image itself (the Blazor CORS fallback)

Null means the ring spins; anything else means it fills and counts. Bind Uri and let the control decide.

Uri is the only thing most pages bind. It takes a remote URL, a file path, a bundled asset, an embedded resource via resource://, or an inline data: URI — and the control decides what to do with each. Raster or vector is decided by looking at the payload, not the file extension.

<shiny:ShinyImage Uri="https://cdn.example.com/photo.jpg" />
<shiny:ShinyImage Uri="resource://MyApp.Assets.logo.svg" />
<shiny:ShinyImage Uri="art/diagram.svg" />

See Image Sources for what each form means and how it is resolved.

Page What it covers
Image Sources Every Uri form — remote, file, bundled asset, resource://, data: — and the explicit Source
SVG Vector rendering on MAUI, per-placement tinting, the parse cache, and exactly what is and is not drawn
Progress & Templates ImageLoadProgress, and replacing the ring or the error artwork on either host
Caching & ImageService The MAUI memory/disk tiers, the download queue, de-duplication, and bringing your own HttpClient
Blazor Why there is no cache layer, streamed progress, the CORS fallback, and authenticated images
Properties & Events The full property tables for both hosts
claude plugin marketplace add shinyorg/skills
claude plugin install shiny@shiny

One plugin installs all 35 Shiny skills. Your agent loads only the skill relevant to what you're building, so there's no cost to having them all available.

copilot plugin marketplace add https://github.com/shinyorg/skills
copilot plugin install shiny@shiny

One plugin installs all 35 Shiny skills. Your agent loads only the skill relevant to what you're building, so there's no cost to having them all available.

View shiny-controls Skill