-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
Background & Use Case
Currently, disabling the RefreshView via IsEnabled=false disables not only the pull-to-refresh gesture but also all child controls within the RefreshView. This behavior is inconsistent across platforms (Android vs iOS) and differs from Xamarin.Forms, where only the refresh gesture was impacted. In Blazor Hybrid apps on Android, for example, disabling RefreshView disables all input on the login screen, making the app unusable (see linked issues below).
Users routinely have scenarios—such as login screens, loading spinners, or certain workflow states—where they want to temporarily disable pull-to-refresh but keep the contents of the view interactive.
Pain Points
- Setting
IsEnabled=falsedisables the entire UI subtree, not just the pull-to-refresh. - iOS and Android behave differently: iOS disables only pull-to-refresh, Android disables all children (breaking forms, buttons, etc).
- Developers migrating from Xamarin.Forms expect to be able to disable only the gesture, not their content.
- This creates blocking issues for Blazor Hybrid, MAUI, and any complex interactive screens.
- Workarounds (such as conditionally wrapping/unwrapping RefreshView, or custom renderers/handlers) are clunky, error-prone, or not possible for all users.
- Critically, the current implementation disables WebViews and HybridWebViews on Android, which is not intended and must be fixed.
Platform-Specific Behavior
The current IsEnabled and RefreshView behavior varies by platform:
| Platform | Current Observed Behavior | Notes / Issue References |
|---|---|---|
| Android | Disables gesture and all child controls (including WebViews/HybridWebViews) | #29901, #19091 |
| iOS | Disables only pull-to-refresh gesture; children remain interactive | #29901, #22699 |
| Mac Catalyst | Not specifically documented; likely follows iOS (disables gesture only, children interactive). Needs confirmation and alignment. | |
| Windows | Refresh indicator or RefreshView can block input in some scenarios (esp. with BlazorWebView); IsEnabled-specific inconsistencies not widely reported, but at least one issue highlights interaction problems |
#19715 |
Community Feedback & Discussion
- Several users have confirmed the pain point and provided workarounds in both RefreshView IsEnabled Disables All Blazor Hybrid Elements on Android, Works Properly on iOS #29901 and IsEnabled=False in RefreshView is inherited by child controls. (Was not the case with Xamarin) #22699.
- Workarounds discussed include always keeping
IsEnabled=true(but then the gesture is never blocked), or removing RefreshView entirely when not needed, but these are not scalable or ergonomic solutions. - Some have suggested making
IsEnabledonly affect the gesture, but this would be a breaking change for existing users who rely on current behavior.
Proposed Solution
1. Add IsRefreshEnabled for Granular Control
Introduce a new property on RefreshView:
public bool IsRefreshEnabled { get; set; }Behavior:
- When
IsRefreshEnabled = false: The pull-to-refresh gesture is disabled, and the refresh indicator cannot be triggered by user interaction. All child controls remain interactive and enabled. - When
IsRefreshEnabled = true: The pull-to-refresh gesture works as normal, and child controls are unaffected.
Benefits:
- Developers gain granular, explicit control over gesture enablement, separate from general view interactivity.
- Parity with Xamarin.Forms' typical usage patterns and user expectations.
- Consistent behavior across platforms (Android, iOS, Windows, Mac Catalyst).
- No breaking change—existing
IsEnabledsemantics are preserved. - Makes Blazor Hybrid and other MAUI scenarios much more robust and user-friendly.
2. Make IsEnabled Consistent Across All Platforms
Current Behavior by Platform
- Android: Setting
IsEnabled=falsedisables the RefreshView and all its child controls (including WebViews/HybridWebViews). - iOS: Setting
IsEnabled=falsedisables only the pull-to-refresh gesture; child controls remain enabled and interactive. - Mac Catalyst: Not specifically documented; likely mirrors iOS behavior but needs confirmation.
- Windows: Some issues with input blocking when RefreshView or refresh indicator is present;
IsEnabledmay not consistently disable all children in all cases.
Proposed Change
- Make
IsEnabled=falsedisable the entire RefreshView subtree (including all child controls), consistent with standard .NET and MAUI control semantics. - All platforms (Android, iOS, Mac Catalyst, Windows) should match this behavior.
- This update will require changes to iOS, Mac Catalyst, and possibly Windows so that disabling the RefreshView also disables all child controls, matching Android’s behavior.
Rationale:
- Aligns RefreshView’s
IsEnabledproperty with the expectations for standard .NET UI controls. - Ensures predictable, cross-platform behavior for all MAUI users.
- Avoids confusion and platform-specific code.
Note: The addition of IsRefreshEnabled allows developers to disable only the gesture while keeping the content interactive, so this change to IsEnabled does not remove any flexibility.
3. IsEnabled, IsRefreshEnabled, and Command.CanExecute Interconnection
In .NET MAUI and Xamarin.Forms, IsEnabled is commonly connected to Command.CanExecute for interactive controls. When a control is bound to a Command, changes to CanExecute will update IsEnabled accordingly. For consistency and developer clarity, RefreshView should maintain or strengthen this connection:
- If a
Commandis assigned toRefreshView, itsCanExecutestate should affect the gesture enablement. - When
CanExecuteisfalse, bothIsRefreshEnabledand the gesture should be disabled (and potentiallyIsEnabledas well, if appropriate). - Setting
IsRefreshEnabled = falseshould also update the state of the gesture in a way that is consistent with howIsEnabledandCanExecuteinteract on other controls. - All three properties (
IsEnabled,IsRefreshEnabled, andCommand.CanExecute) should work together, so that disabling any of them results in the gesture being disabled and the intended user experience.
This ensures a seamless and predictable developer experience, especially for MVVM scenarios where command logic drives control state.
Example Usage
<RefreshView IsRefreshEnabled="false">
<!-- All child controls are still enabled and interactive -->
<BlazorWebView ... />
</RefreshView>
<RefreshView IsEnabled="false">
<!-- All child controls, including BlazorWebView, are disabled -->
<BlazorWebView ... />
</RefreshView>Migration Guidance
- Existing projects using
IsEnabledfor gesture control can migrate toIsRefreshEnabledfor more precise behavior, and preserve child interactivity. - Projects that rely on disabling the entire RefreshView and its children should continue using
IsEnabled=falseand will now have consistent behavior across all supported platforms. - Developers leveraging
Command.CanExecutefor enabling/disabling gesture behavior should find the new interconnection withIsRefreshEnabledandIsEnabledto be consistent and predictable.
Related Issues
Metadata
Metadata
Assignees
Labels
Type
Projects
Status