-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[.NET 10] Implement multi-select for MediaPicker #30002
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements multi-select support for MediaPicker in .NET MAUI by adding new async methods and extending MediaPickerOptions with a SelectionLimit property. Key changes include:
- New async methods (PickPhotosAsync, PickVideosAsync) returning lists of FileResult objects and obsolete single-selection methods.
- Platform-specific updates in Android, iOS, and UWP to support multiple file selections.
- Updates to sample ViewModel and XAML to demonstrate multi-select functionality.
Reviewed Changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| PublicAPI.Unshipped.txt (netstandard, net, net-windows, net-maccatalyst, net-ios, net-android) | Updated public API definitions to include multi-select methods and the new SelectionLimit property. |
| Platform/PickMultipleVisualMediaForResult.android.cs | Introduced a new helper class to handle multi-select on Android. |
| MediaPicker.uwp.cs, MediaPicker.ios.cs, MediaPicker.android.cs | Modified platform-specific implementations to support multiple media picks. |
| Samples (ViewModel and XAML) | Adapted sample code to use multi-select methods and display multiple photos. |
Comments suppressed due to low confidence (2)
src/Essentials/src/MediaPicker/MediaPicker.ios.cs:176
- Returning null in the multiple-selection method for iOS when the OS version is less than 14 can lead to potential null reference issues; consider returning an empty list instead for consistency with other implementations.
if (!OperatingSystem.IsIOSVersionAtLeast(14, 0)) { return null; }
src/Essentials/samples/Samples/ViewModel/MediaPickerViewModel.cs:131
- [nitpick] The sample now reuses the PhotoSource property for both photo and video operations, which could be confusing; consider introducing a separate property for video to clarify intent and usage.
var video = await MediaPicker.CaptureVideoAsync();
|
Maybe this is the subject of future work, but how do you feel about simplifying the API even further and having just a single Something like: Definition/// <summary>
/// Represents the type of media that can be picked using the MediaPicker API.
/// </summary>
public enum PickableMediaType
{
/// <summary>
/// Represents all types of media that can be selected.
/// </summary>
All = 0,
/// <summary>
/// Represents image media that can be selected.
/// </summary>
Image = 1,
/// <summary>
/// Represents video media that can be selected.
/// </summary>
Video = 2,
}
/// <summary>
/// Pick options for picking media from the device.
/// </summary>
public class MediaPickerOptions
{
/// <summary>
/// Gets or sets the type of media that can be picked.
/// Default value is <see cref="PickableMediaType.All"/>.
/// </summary>
public PickableMediaType PickableMediaType { get; set; } = PickableMediaType.All;
/// <summary>
/// Gets or sets the title that is displayed when picking media.
/// </summary>
/// <remarks>This title is not guaranteed to be shown on all operating systems.</remarks>
public string? Title { get; set; }
/// <summary>
/// Gets or sets the maximum number of items that can be selected. Default value is 1.
/// </summary>
/// <remarks>
/// A value of 0 means no limit.
/// </remarks>
public int SelectionLimit { get; set; } = 1;
}
/// <summary>
/// The MediaPicker API lets a user pick or take a photo or video on the device.
/// </summary>
public interface IMediaPicker
{
/// <summary>
/// Gets a value indicating whether capturing media is supported on this device.
/// </summary>
bool IsCaptureSupported { get; }
// NEW
Task<IEnumerable<FileResult>> PickAsync(MediaPickerOptions? options = null);
/// <summary>
/// Opens the media browser to select a photo.
/// </summary>
/// <param name="options">Pick options to use.</param>
/// <returns>A <see cref="FileResult"/> object containing details of the picked photo. When the operation was cancelled by the user, this will return <see langword="null"/>.</returns>
/// <remarks>When using <see cref="MediaPickerOptions.SelectionLimit"/> on this overload, it will <b>not</b> have effect.</remarks>
[Obsolete($"Use {nameof(PickAsync)} instead.")]
Task<FileResult?> PickPhotoAsync(MediaPickerOptions? options = null);
/// <summary>
/// Opens the camera to take a photo.
/// </summary>
/// <param name="options">Pick options to use.</param>
/// <returns>A <see cref="FileResult"/> object containing details of the captured photo. When the operation was cancelled by the user, this will return <see langword="null"/>.</returns>
Task<FileResult?> CapturePhotoAsync(MediaPickerOptions? options = null);
/// <summary>
/// Opens the media browser to select a video.
/// </summary>
/// <param name="options">Pick options to use.</param>
/// <returns>A <see cref="FileResult"/> object containing details of the picked video. When the operation was cancelled by the user, this will return <see langword="null"/>.</returns>
/// <remarks>When using <see cref="MediaPickerOptions.SelectionLimit"/> on this overload, it will <b>not</b> have effect.</remarks>
[Obsolete($"Use {nameof(PickAsync)} instead.")]
Task<FileResult?> PickVideoAsync(MediaPickerOptions? options = null);
/// <summary>
/// Opens the camera to take a video.
/// </summary>
/// <param name="options">Pick options to use.</param>
/// <returns>A <see cref="FileResult"/> object containing details of the captured video. When the operation was cancelled by the user, this will return <see langword="null"/>.</returns>
Task<FileResult?> CaptureVideoAsync(MediaPickerOptions? options = null);
}UsageIEnumerable<FileResult> singleImage = await MediaPicker.PickAsync(new MediaPickerOptions
{
Title = "Pick an image",
SelectionLimit = 1,
PickableMediaType = PickableMediaType.Image
});
IEnumerable<FileResult> images = await MediaPicker.PickAsync(new MediaPickerOptions
{
Title = "Pick images",
SelectionLimit = 5,
PickableMediaType = PickableMediaType.Image
});
IEnumerable<FileResult> singleVideo = await MediaPicker.PickAsync(new MediaPickerOptions
{
Title = "Pick a video",
SelectionLimit = 1,
PickableMediaType = PickableMediaType.Video
});
IEnumerable<FileResult> videos = await MediaPicker.PickAsync(new MediaPickerOptions
{
Title = "Pick videos",
SelectionLimit = 5,
PickableMediaType = PickableMediaType.Video
});
IEnumerable<FileResult> media = await MediaPicker.PickAsync(new MediaPickerOptions
{
Title = "Pick image or video",
SelectionLimit = 1,
PickableMediaType = PickableMediaType.All
});
IEnumerable<FileResult> medias = await MediaPicker.PickAsync(new MediaPickerOptions
{
Title = "Pick images and/or videos",
SelectionLimit = 5,
PickableMediaType = PickableMediaType.All
});Seems like an easy win, but maybe there's something with FileResult that makes it a bit more complex. |
|
Oh I kinda like that idea... Are we sure this is possible for all platforms? Mainly mixing between images and videos? |
6514b74 to
5dda8f1
Compare
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Description of Change
This PR adds the ability to pick multiple files at once through MediaPicker. The single pick methods are obsoleted in favor of the multi pick ones. This prevents the need to have a separate options objects or parameter etc. Now the
MediaPickerOptionsobject has a new fieldSelectionLimitwith a default value of 1. So default is still a single pick action. Then 0 means unlimited and any other number is the actual limit.There are a few notes:
Issues Fixed
Fixes #29079