Skip to content
Document DB v12 - Improved Interceptors with Soft Delete Integration, AI protections, & Admin UI with Aspire Integration!How!?

MediaPickerButton

A button that lets the user add photos from the gallery and/or camera, compresses/re-encodes each to PNG or JPEG at a chosen quality (with optional max-dimension downscale), caps the count with MaxPhotos (added one at a time — the OS pickers are single-select), and shows the collected photos inline as a tappable carousel (opening the ImageViewer, with an optional Edit button that reuses the ImageEditor) or a compact pinch/zoom overlay. It ships inside the base packages — no extra dependency.

  • NuGet downloads for Shiny.Maui.Controls
  • NuGet downloads for Shiny.Blazor.Controls
Frameworks
.NET MAUI
Blazor
MediaPickerButton
<shiny:MediaPickerButton Photos="{Binding Photos}"
AllowGallery="True"
AllowCamera="True"
AllowPhotoEdit="True"
ShowAsCarouselInView="True"
MaxPhotos="5"
CompressionQuality="85"
OutputFormat="Jpeg"
PermissionDeniedText="Photo access was denied — enable it in Settings." />
[ObservableProperty]
ObservableCollection<MediaPickerItem> photos = new(); // Shiny.Maui.Controls.Media

OutputFormat is Shiny.Maui.Controls.ImageEditor.ImageExportFormat (Png / Jpeg).

<MediaPickerButton @bind-Photos="photos"
AllowGallery="true"
AllowCamera="true"
AllowPhotoEdit="true"
ShowAsCarouselInView="true"
MaxPhotos="5"
CompressionQuality="85"
OutputFormat="jpeg"
PermissionDeniedText="Photo access was denied." />
@code {
IReadOnlyList<Shiny.Blazor.Controls.MediaPickerItem> photos = [];
}

On Blazor OutputFormat is a string ("jpeg" / "png"), and each MediaPickerItem exposes a DataUri you can bind directly to <img src>.

Property Type Default Description
AllowGallery bool true Offer “choose from gallery”
AllowCamera bool true Offer “take photo”. When both are enabled, tapping shows a gallery/camera chooser
AllowPhotoEdit bool false Show an Edit button in the viewer that opens the ImageEditor; edits are re-saved into the collection
PermissionDeniedText string “Permission denied…” Message shown when camera/gallery access is denied
NoImagesTemplate DataTemplate? / RenderFragment? null Shown when there are no photos yet (default: “No photos yet”)
ShowAsCarouselInView bool true true → inline thumbnail carousel; false → compact preview that opens a paged pinch/zoom overlay
MaxPhotos int 1 Maximum photos; the add trigger hides once reached
CompressionQuality int 92 Encoder quality as a percentage (1–100)
MaxImageDimension int 0 If > 0, the longest edge is downscaled to this many pixels
OutputFormat ImageExportFormat / string Jpeg / "jpeg" Output encoding — PNG or JPEG
Photos IList / IReadOnlyList of MediaPickerItem empty The collected photos (two-way)
AddButtonText string “➕ Add Photo” Text on the add trigger
GalleryActionText / CameraActionText string “Choose from Gallery” / “Take Photo” Chooser labels
UseFeedback bool (MAUI) true Haptic/sound feedback on actions
  • PhotoAdded / PhotoRemoved — a photo was added or removed (MediaPickerItem).
  • PhotosChanged (MAUI event + PhotosChangedCommand; Blazor EventCallback) — the collection changed.
  • PermissionDenied — camera/gallery access was denied (message string).
  • Multi-photo is add-one-at-a-time — each tap picks/captures a single photo and appends until MaxPhotos. The OS pickers do not offer native multi-select here.
  • MAUI is a plain ContentView using the built-in Microsoft.Maui.Media.MediaPicker — no handler or builder registration. The MediaPicker drives the OS permission prompts; a denial surfaces PermissionDeniedText.
  • Blazor self-imports its JS module (no DI). Gallery/camera use a hidden <input type="file" accept="image/*"> (with capture="environment" for the camera); compression/resize/format-conversion happen on an offscreen canvas.
  • Viewing reuses the ImageViewer (pinch/zoom); editing reuses the ImageEditor.
claude plugin marketplace add shinyorg/skills
claude plugin install controls@shiny
copilot plugin marketplace add https://github.com/shinyorg/skills
copilot plugin install controls@shiny
View controls Plugin