[Testing] Feature Matrix UITest Cases for Brushes#31833
[Testing] Feature Matrix UITest Cases for Brushes#31833kubaflo merged 13 commits intodotnet:inflight/currentfrom
Conversation
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
@jsuarezruiz I have committed this snapshot in the latest changes. |
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
@jsuarezruiz I have committed this snapshot in the latest changes. |
There was a problem hiding this comment.
Pull Request Overview
This pull request adds a comprehensive new brushes feature matrix test page to the controls test app, enabling interactive testing and configuration of brush, stroke, and shadow features, including solid, linear, and radial gradients. The implementation provides both UI test automation and interactive controls for validating various brush combinations.
- Introduces a complete brushes testing framework with ViewModel, UI pages, and automated tests
- Adds comprehensive UI test coverage for brush features with 25+ test scenarios
- Implements interactive controls for configuring brush types, opacity, gradient properties, and comparing brushes
Reviewed Changes
Copilot reviewed 8 out of 135 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| BrushesFeatureTests.cs | Comprehensive NUnit test suite with 25+ automated test scenarios for brush features |
| BindableLayoutFeatureTests.cs | Basic placeholder test for BindableLayout feature matrix |
| BrushesViewModel.cs | Complete view model implementing brush logic, commands, and property management |
| BrushesOptionsPage.xaml/.cs | Configuration page for selecting brush types, colors, and properties |
| BrushesControlPage.xaml/.cs | Main test page displaying brush visualizations and controls |
| CorePageView.cs | Registration of the new Brushes Feature Matrix in the gallery |
|
|
||
| private async void OnOptionsClicked(object sender, EventArgs e) | ||
| { | ||
| BindingContext = _viewModel = new BrushesViewModel(); |
There was a problem hiding this comment.
Creating a new BrushesViewModel instance overwrites the existing state when navigating to options. This will lose any previously configured brush settings. The existing _viewModel should be reused instead of creating a new instance.
| BindingContext = _viewModel = new BrushesViewModel(); |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
bd32daf to
5e3e653
Compare
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
5e3e653 to
33a1f80
Compare
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 31833Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 31833" |
🤖 AI Summary📊 Expand Full Review🔍 Pre-Flight — Context & Validation📝 Review Session — remove unwanted files ·
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #31833 | Add brushes feature matrix test infrastructure with ViewModel, interactive pages, and 25+ automated UI tests | ⏳ PENDING (Gate) | 6 impl + 1 test + 93 snapshots | Original PR - testing infrastructure, not a bug fix |
Edge Cases to Verify
From test file review, the following scenarios are covered:
- Solid color brushes with background, stroke, shadow, and opacity combinations
- Linear gradients with start/end points, gradient stops, stroke, shadow, opacity
- Radial gradients with center, radius, gradient stops, stroke, shadow, opacity
- Adding/removing gradient stops dynamically
- Alternate brush variants
- All combinations across Android, macOS, and Windows platforms
🚦 Gate — Test Verification
📝 Review Session — remove unwanted files · d27a273
Result: ✅ PASSED
Platform: android
Test Type: New Test Infrastructure Verification
Total Tests: 37
Passed: 37
Failed: 0
Verification Mode
This PR adds new test infrastructure (not fixing a bug), so the traditional "fail without fix, pass with fix" pattern doesn't apply. Instead, verification confirms:
- ✅ New tests build successfully
- ✅ New tests run without errors
- ✅ Test infrastructure is working correctly
Test Results Summary
Build Phase:
- Build Status: ✅ SUCCESS (0 warnings, 0 errors)
- Build Time: 3 minutes 6 seconds
- All dependencies resolved correctly
Execution Phase:
- Execution Status: ✅ SUCCESS (exit code 0)
- Test Time: 2.6766 minutes
- Device: emulator-5554 (Android API 36)
- No crashes or infrastructure failures
Test Coverage Verified:
- Solid color brushes with background, shadow, stroke, opacity
- Linear gradient brushes with start/end points, gradient stops, shadow, stroke, opacity
- Radial gradient brushes with center, radius, gradient stops, shadow, stroke, opacity
- Dynamic gradient stop manipulation (add/remove)
- Advanced feature combinations (shadow + opacity, stroke + opacity, background + shadow + stroke)
- Brush comparison functionality
Full Output
Complete test logs saved to: CustomAgentLogsTmp/PRState/31833/PRAgent/gate/build-run-output.log
Conclusion
✅ Gate verification PASSED. All 37 new brush feature tests execute successfully on Android, confirming the test infrastructure is working correctly and providing comprehensive coverage of brushes functionality.
🔧 Fix — Analysis & Comparison
📝 Review Session — remove unwanted files · d27a273
Phase 3: Fix Exploration - SKIPPED (Not Applicable)
Reason: This PR adds NEW test infrastructure (not fixing a bug), so try-fix exploration doesn't apply.
Context:
- PR [Testing] Feature Matrix UITest Cases for Brushes #31833 introduces 37 new brush feature tests
- No existing bug is being fixed
- Gate verification confirmed all new tests pass successfully
- There are no "alternative fix approaches" to explore for adding test infrastructure
Decision: Skip Phase 3 (try-fix) and proceed directly to Phase 4 (Report) with code quality review.
Fix Candidates Table
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #31833 | Add brushes feature matrix test infrastructure | ✅ PASS (Gate) | 6 impl + 1 test + 93 snapshots | Original PR - comprehensive test coverage |
Exhausted: N/A (try-fix not applicable for test infrastructure additions)
Selected Fix: PR's implementation - Only implementation (test infrastructure addition)
Code Quality Observations
Potential Issue Identified (from Copilot inline review):
- File:
BrushesControlPage.xaml.cs:65 - Issue: Creating new
BrushesViewModelinstance overwrites existing state when navigating to options page - Recommendation: Reuse existing
_viewModelinstead of creating new instance to preserve brush settings - Status:
⚠️ Not addressed in current PR
Recommendation: Consider addressing the ViewModel state preservation issue in a follow-up or as part of this PR review.
📋 Report — Final Recommendation
📝 Review Session — remove unwanted files · d27a273
✅ Final Recommendation: APPROVE
Summary
PR #31833 adds comprehensive brushes feature matrix test infrastructure to TestCases.HostApp, providing both interactive testing controls and 37 automated UI tests. All tests pass successfully on Android (Gate verification ✅), and the code is well-architected following MVVM patterns with proper separation of concerns.
Key Achievements:
- ✅ 37 passing UI tests covering brushes, gradients, shadows, strokes, and opacity
- ✅ Interactive testing pages for manual validation
- ✅ Clean MVVM architecture with BrushesViewModel (569 lines)
- ✅ Cross-platform snapshot coverage (Android, macOS, Windows - 93 images)
- ✅ Non-intrusive integration (single line added to CorePageView.cs)
Title & Description Accuracy
Title: [Testing] Feature Matrix UITest Cases for Brushes ✅ ACCURATE
- Properly indicates test infrastructure addition
- Clear scope definition
Description: ✅ EXCELLENT
- Well-structured with clear sections
- Matches implementation details
- Includes class names and technical specifics
- Visual demonstration included
Verdict: No changes needed to title or description.
Code Quality Assessment
Architecture & Design: ✅ EXCELLENT
- Proper MVVM pattern with INotifyPropertyChanged
- Clean separation: UI (XAML) + Logic (ViewModel) + Tests
- Reusable feature matrix approach for configuration-based testing
Test Infrastructure: ✅ COMPREHENSIVE
- 654 lines of test code covering:
- Solid color brushes with background, shadow, stroke, opacity
- Linear gradients with start/end points, gradient stops
- Radial gradients with center, radius, gradient stops
- Dynamic gradient stop manipulation (add/remove)
- All combinations across platforms
- Proper automation IDs for Appium element identification
- Visual regression testing with 93 baseline snapshots
ViewModel Implementation: ✅ ROBUST
- 20+ ICommand properties for brush configuration
- Full property tracking for all brush parameters
- Proper binding support for UI updates
Code Review Observations
Minor Issue (from Copilot inline review):
- File:
BrushesControlPage.xaml.cs:65 - Creating new
BrushesViewModelinstance when navigating to options may lose state - Suggestion: Reuse existing
_viewModelto preserve brush settings - Status:
⚠️ Not addressed in current PR
Impact: Low - This is a minor UX issue in the test app (not production code). The test infrastructure still functions correctly.
Recommendation: Can be addressed in follow-up if needed, or accepted as-is for test infrastructure.
Gate Verification Results
Platform: Android
Result: ✅ ALL TESTS PASSED
- Total Tests: 37
- Passed: 37
- Failed: 0
- Build: ✅ SUCCESS (0 warnings, 0 errors)
- Execution: ✅ SUCCESS (no crashes)
Phase 3: Fix Exploration
Status: ⏭️ SKIPPED (Not Applicable)
Reason: This PR adds new test infrastructure (not fixing a bug). The try-fix exploration phase is designed for evaluating alternative bug fixes, which doesn't apply to test infrastructure additions.
Validation: Gate verification confirmed all 37 new tests pass successfully, demonstrating the test infrastructure works correctly.
Breaking Changes
None. This PR:
- ✅ Only adds new code (no modifications to existing APIs)
- ✅ Single non-intrusive line added to gallery navigation
- ✅ All changes in test infrastructure directories
- ✅ No impact on production code
Recommendation Details
Approve because:
- ✅ Gate verification passed - all 37 tests run successfully
- ✅ Code follows MAUI conventions and MVVM best practices
- ✅ Comprehensive test coverage for brushes functionality
- ✅ Clean architecture with proper separation of concerns
- ✅ No breaking changes or production code impact
- ✅ Title and description accurately reflect implementation
- ✅ Cross-platform snapshot coverage ensures visual consistency
Minor observation (ViewModel state preservation) has low impact on test infrastructure functionality and can be addressed separately if needed.
Before Merge Checklist
Verify:
- All 93 snapshot files are properly tracked (likely Git LFS)
-
UITestCategories.Brushcategory exists in test infrastructure - CI/CD pipeline handles snapshot image assets correctly
Content for Future Agents
Key Patterns:
- Feature Matrix Approach: This PR establishes a reusable pattern for interactive testing with configurable options
- Replicability: The ViewModel + ControlPage + OptionsPage pattern can be replicated for other controls needing configuration-based testing
- Command-Based Testing: VM-based command approach allows flexible test scenario generation without modifying page structure
📋 Expand PR Finalization Review
Title: ✅ Good
Current: [Testing] Feature Matrix UITest Cases for Brushes
Description: ✅ Excellent
Description needs updates. See details below.
✨ Suggested PR Description
[!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 pull request adds a comprehensive new brushes feature matrix test page to the controls test app, enabling interactive testing and configuration of brush, stroke, and shadow features, including solid, linear, and radial gradients. It introduces two new pages—one for visualizing and comparing brush features and another for configuring brush options—along with the necessary navigation and event handling logic.
New Brushes Feature Matrix functionality:
- Added a new entry for "Brushes Feature Matrix" to the gallery page factory list, making the new test page accessible from the app's main navigation.
- Implemented the
BrushesControlPageandBrushesControlMainPageclasses to provide a navigation page and main content page for brush feature testing, including event handlers for comparing brushes and navigating to options. - Created the
BrushesControlPage.xamlUI, which displays the current brush, stroke, and shadow settings, allows brush comparison, and shows selected color details.
Brush options and customization:
- Added a detailed
BrushesOptionsPage(XAML and code-behind) that lets users select and configure brush types (none, solid, linear, radial), shadow types, stroke types, opacity, alternate variants, and color selections, with all changes bound to a sharedBrushesViewModel. [1] [2]
Screen.Recording.2025-10-01.at.10.10.36.AM.mov
Issues Fixed
(No specific issues linked - this is a new test infrastructure addition)
Code Review: ✅ Passed
Code Review: PR #31833
Overall Assessment: ✅ Good Quality
The implementation provides comprehensive brush testing infrastructure with good architectural patterns and cross-platform coverage.
🟢 Strengths
1. Comprehensive Test Coverage
Excellent breadth and depth of brush testing:
- ✅ All brush types covered: SolidColorBrush, LinearGradientBrush, RadialGradientBrush
- ✅ Multiple contexts tested: Background, stroke, shadow properties
- ✅ Property variations: Opacity, gradient stops, start/end points, center/radius
- ✅ Dynamic operations: Addition/removal of gradient stops at runtime
- ✅ Equality testing: Brush comparison and hash code validation
Files: BrushesFeatureTests.cs (654 lines), snapshot images for all platforms
2. Cross-Platform Testing Strategy
Proper handling of platform differences:
- ✅ Snapshots for Android, iOS, MacCatalyst, Windows
- ✅ Platform-specific test exclusions using conditional compilation
- ✅ Documentation of platform limitations: Tests disabled on iOS/MacCatalyst/Windows for shadow gradients include this comment:
//Shadow gradient brushes are not rendered as gradients on iOS, MacCatalyst, and Windows;
//instead, they fall back to a solid color because the underlying native shadow APIs
//only support single-color shadows.Why this matters: Future developers will understand why certain tests don't run on specific platforms, preventing confusion and redundant investigation.
3. Clean MVVM Architecture
Proper separation of concerns:
ViewModel (BrushesViewModel.cs):
- ✅ Implements
INotifyPropertyChanged - ✅ Commands for all brush operations
- ✅ Data binding for all properties
- ✅ Business logic for brush equality/hashing
View (BrushesControlPage.xaml, BrushesOptionsPage.xaml):
- ✅ Pure declarative UI with data binding
- ✅ Minimal code-behind (just event routing)
- ✅ Clear AutomationId coverage
4. Excellent AutomationId Coverage
All interactive elements have automation IDs:
// Examples from BrushesControlPage.xaml
AutomationId="BrushesLabel"
AutomationId="CompareButton"
AutomationId="CompareResultLabel"
AutomationId="AddLinearStopButton"
AutomationId="RemoveLinearStopButton"
// ... and many moreWhy this matters: Enables reliable UI test automation and makes tests maintainable.
🟡 Suggestions for Future Enhancement
1. ViewModel: Consider ICommand.CanExecute for State Management
File: BrushesViewModel.cs (lines 345-375)
Current Approach:
RemoveLinearGradientStopCommand = new Command(() =>
{
if (BrushTarget is LinearGradientBrush lgb && lgb.GradientStops.Count > 0)
{
lgb.GradientStops.RemoveAt(lgb.GradientStops.Count - 1);
LinearGradientStopCount = lgb.GradientStops.Count;
OnPropertyChanged(nameof(LinearGradientStopCount));
}
});Suggestion: Use Command with CanExecute predicate:
RemoveLinearGradientStopCommand = new Command(
execute: () =>
{
var lgb = (LinearGradientBrush)BrushTarget;
lgb.GradientStops.RemoveAt(lgb.GradientStops.Count - 1);
LinearGradientStopCount = lgb.GradientStops.Count;
OnPropertyChanged(nameof(LinearGradientStopCount));
},
canExecute: () => BrushTarget is LinearGradientBrush lgb && lgb.GradientStops.Count > 0
);
// Also update when BrushTarget changes:
public Brush BrushTarget
{
get => brushTarget;
set
{
if (brushTarget == value) return;
brushTarget = value;
OnPropertyChanged();
UpdateDerivedProperties();
// Notify command state changed
(RemoveLinearGradientStopCommand as Command)?.ChangeCanExecute();
(RemoveRadialGradientStopCommand as Command)?.ChangeCanExecute();
}
}Benefits:
- Buttons automatically disable when action is invalid
- Better UX: Visual feedback that operation isn't available
- No need for manual null checking in execute lambda
Applies to: All 4 add/remove gradient stop commands
2. Test Class: Extract Common Navigation Pattern
File: BrushesFeatureTests.cs
Observed Pattern: Nearly every test follows this structure:
App.WaitForElement("Options");
App.Tap("Options");
App.WaitForElement("BackgroundSolidColor");
App.Tap("BackgroundSolidColor");
// ... more taps ...
App.WaitForElement("Apply");
App.Tap("Apply");
App.WaitForElement("BrushesLabel");
VerifyBrushesScreenshot();Suggestion: Extract helper method to reduce duplication:
private void ConfigureBrushAndVerify(params string[] optionIds)
{
App.WaitForElement("Options");
App.Tap("Options");
foreach (var id in optionIds)
{
App.WaitForElement(id);
App.Tap(id);
}
App.WaitForElement("Apply");
App.Tap("Apply");
App.WaitForElement("BrushesLabel");
VerifyBrushesScreenshot();
}
// Usage example:
[Test]
public void VerifySolidColorBrushWithBackgroundColor()
{
ConfigureBrushAndVerify("BackgroundSolidColor");
}
[Test]
public void VerifySolidColorBrushWithShadow()
{
ConfigureBrushAndVerify("BackgroundSolidColor", "ShadowSolidColor");
}Benefits:
- Reduces ~600 lines of duplicated navigation code
- Makes tests more maintainable
- Easier to update if navigation flow changes
Note: For tests that need to enter text or have custom steps, keep the expanded form.
3. ViewModel: Minor - Use Explicit .Equals() for Struct Comparison
File: BrushesViewModel.cs (lines 482-483)
Current:
if (a is SolidColorBrush sa && b is SolidColorBrush sb)
return sa.Color == sb.Color;Suggestion:
if (a is SolidColorBrush sa && b is SolidColorBrush sb)
return sa.Color.Equals(sb.Color);Reasoning:
Coloris a struct, and while it likely overridesoperator==, explicit.Equals()is more conventional- Makes intent clearer: structural equality comparison
- Matches the pattern used later for
Point.Equals()(line 487)
Impact: Very minor - functional behavior is likely identical, but improves code consistency.
4. Test Coverage: Entry Field Tests Use ClearText + EnterText
File: BrushesFeatureTests.cs (lines 198-199, 214-215, etc.)
Current Approach:
App.ClearText("OpacityEntry");
App.EnterText("OpacityEntry", "0.5");Observation: This is the correct pattern for Appium text entry. ✅
Suggestion: Consider adding assertions that the entered value was actually set:
App.ClearText("OpacityEntry");
App.EnterText("OpacityEntry", "0.5");
// Verify the text was entered correctly
Assert.That(App.FindElement("OpacityEntry").GetText(), Is.EqualTo("0.5"));Benefits:
- Catches if text entry failed silently
- Makes test failures clearer (did the rendering fail or did the input fail?)
Impact: Optional - current approach is acceptable for UI tests that primarily verify visual output.
✅ No Critical Issues
No blocking issues, bugs, or architectural problems detected. The implementation follows MAUI testing conventions and provides a solid foundation for brush testing.
Summary
| Aspect | Rating | Notes |
|---|---|---|
| Architecture | ✅ Good | Clean MVVM, proper separation of concerns |
| Test Coverage | ✅ Excellent | Comprehensive brush testing across platforms |
| Code Quality | ✅ Good | Clear, maintainable code |
| AutomationIds | ✅ Excellent | Complete coverage for test automation |
| Documentation | ✅ Good | Platform limitations documented in code |
| Suggestions | 🟡 Minor | Enhancements for future iterations, not blockers |
Recommendation: Approve for merge. Suggestions are enhancements for future consideration, not blockers.
eea91b6 to
ae1d3fc
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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! This pull request adds a comprehensive new brushes feature matrix test page to the controls test app, enabling interactive testing and configuration of brush, stroke, and shadow features, including solid, linear, and radial gradients. It introduces two new pages—one for visualizing and comparing brush features and another for configuring brush options—along with the necessary navigation and event handling logic. **New Brushes Feature Matrix functionality:** * Added a new entry for "Brushes Feature Matrix" to the gallery page factory list, making the new test page accessible from the app's main navigation. * Implemented the `BrushesControlPage` and `BrushesControlMainPage` classes to provide a navigation page and main content page for brush feature testing, including event handlers for comparing brushes and navigating to options. * Created the `BrushesControlPage.xaml` UI, which displays the current brush, stroke, and shadow settings, allows brush comparison, and shows selected color details. **Brush options and customization:** * Added a detailed `BrushesOptionsPage` (XAML and code-behind) that lets users select and configure brush types (none, solid, linear, radial), shadow types, stroke types, opacity, alternate variants, and color selections, with all changes bound to a shared `BrushesViewModel`. [[1]](diffhunk://#diff-a0b81253f3786054d00a4400d1fca4280fef128db5e618e0fae7bc845b7b70d8R1-R242) [[2]](diffhunk://#diff-f1180dfb2805a40c7a208076e415971e8e6639f58b9091c0a166c975671374d8R1-R130) https://github.com/user-attachments/assets/c4280d48-ebb3-45d3-a5bf-3388ea32e459
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! This pull request adds a comprehensive new brushes feature matrix test page to the controls test app, enabling interactive testing and configuration of brush, stroke, and shadow features, including solid, linear, and radial gradients. It introduces two new pages—one for visualizing and comparing brush features and another for configuring brush options—along with the necessary navigation and event handling logic. **New Brushes Feature Matrix functionality:** * Added a new entry for "Brushes Feature Matrix" to the gallery page factory list, making the new test page accessible from the app's main navigation. * Implemented the `BrushesControlPage` and `BrushesControlMainPage` classes to provide a navigation page and main content page for brush feature testing, including event handlers for comparing brushes and navigating to options. * Created the `BrushesControlPage.xaml` UI, which displays the current brush, stroke, and shadow settings, allows brush comparison, and shows selected color details. **Brush options and customization:** * Added a detailed `BrushesOptionsPage` (XAML and code-behind) that lets users select and configure brush types (none, solid, linear, radial), shadow types, stroke types, opacity, alternate variants, and color selections, with all changes bound to a shared `BrushesViewModel`. [[1]](diffhunk://#diff-a0b81253f3786054d00a4400d1fca4280fef128db5e618e0fae7bc845b7b70d8R1-R242) [[2]](diffhunk://#diff-f1180dfb2805a40c7a208076e415971e8e6639f58b9091c0a166c975671374d8R1-R130) https://github.com/user-attachments/assets/c4280d48-ebb3-45d3-a5bf-3388ea32e459
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! This pull request adds a comprehensive new brushes feature matrix test page to the controls test app, enabling interactive testing and configuration of brush, stroke, and shadow features, including solid, linear, and radial gradients. It introduces two new pages—one for visualizing and comparing brush features and another for configuring brush options—along with the necessary navigation and event handling logic. **New Brushes Feature Matrix functionality:** * Added a new entry for "Brushes Feature Matrix" to the gallery page factory list, making the new test page accessible from the app's main navigation. * Implemented the `BrushesControlPage` and `BrushesControlMainPage` classes to provide a navigation page and main content page for brush feature testing, including event handlers for comparing brushes and navigating to options. * Created the `BrushesControlPage.xaml` UI, which displays the current brush, stroke, and shadow settings, allows brush comparison, and shows selected color details. **Brush options and customization:** * Added a detailed `BrushesOptionsPage` (XAML and code-behind) that lets users select and configure brush types (none, solid, linear, radial), shadow types, stroke types, opacity, alternate variants, and color selections, with all changes bound to a shared `BrushesViewModel`. [[1]](diffhunk://#diff-a0b81253f3786054d00a4400d1fca4280fef128db5e618e0fae7bc845b7b70d8R1-R242) [[2]](diffhunk://#diff-f1180dfb2805a40c7a208076e415971e8e6639f58b9091c0a166c975671374d8R1-R130) https://github.com/user-attachments/assets/c4280d48-ebb3-45d3-a5bf-3388ea32e459
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! This pull request adds a comprehensive new brushes feature matrix test page to the controls test app, enabling interactive testing and configuration of brush, stroke, and shadow features, including solid, linear, and radial gradients. It introduces two new pages—one for visualizing and comparing brush features and another for configuring brush options—along with the necessary navigation and event handling logic. **New Brushes Feature Matrix functionality:** * Added a new entry for "Brushes Feature Matrix" to the gallery page factory list, making the new test page accessible from the app's main navigation. * Implemented the `BrushesControlPage` and `BrushesControlMainPage` classes to provide a navigation page and main content page for brush feature testing, including event handlers for comparing brushes and navigating to options. * Created the `BrushesControlPage.xaml` UI, which displays the current brush, stroke, and shadow settings, allows brush comparison, and shows selected color details. **Brush options and customization:** * Added a detailed `BrushesOptionsPage` (XAML and code-behind) that lets users select and configure brush types (none, solid, linear, radial), shadow types, stroke types, opacity, alternate variants, and color selections, with all changes bound to a shared `BrushesViewModel`. [[1]](diffhunk://#diff-a0b81253f3786054d00a4400d1fca4280fef128db5e618e0fae7bc845b7b70d8R1-R242) [[2]](diffhunk://#diff-f1180dfb2805a40c7a208076e415971e8e6639f58b9091c0a166c975671374d8R1-R130) https://github.com/user-attachments/assets/c4280d48-ebb3-45d3-a5bf-3388ea32e459
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! This pull request adds a comprehensive new brushes feature matrix test page to the controls test app, enabling interactive testing and configuration of brush, stroke, and shadow features, including solid, linear, and radial gradients. It introduces two new pages—one for visualizing and comparing brush features and another for configuring brush options—along with the necessary navigation and event handling logic. **New Brushes Feature Matrix functionality:** * Added a new entry for "Brushes Feature Matrix" to the gallery page factory list, making the new test page accessible from the app's main navigation. * Implemented the `BrushesControlPage` and `BrushesControlMainPage` classes to provide a navigation page and main content page for brush feature testing, including event handlers for comparing brushes and navigating to options. * Created the `BrushesControlPage.xaml` UI, which displays the current brush, stroke, and shadow settings, allows brush comparison, and shows selected color details. **Brush options and customization:** * Added a detailed `BrushesOptionsPage` (XAML and code-behind) that lets users select and configure brush types (none, solid, linear, radial), shadow types, stroke types, opacity, alternate variants, and color selections, with all changes bound to a shared `BrushesViewModel`. [[1]](diffhunk://#diff-a0b81253f3786054d00a4400d1fca4280fef128db5e618e0fae7bc845b7b70d8R1-R242) [[2]](diffhunk://#diff-f1180dfb2805a40c7a208076e415971e8e6639f58b9091c0a166c975671374d8R1-R130) https://github.com/user-attachments/assets/c4280d48-ebb3-45d3-a5bf-3388ea32e459
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! This pull request adds a comprehensive new brushes feature matrix test page to the controls test app, enabling interactive testing and configuration of brush, stroke, and shadow features, including solid, linear, and radial gradients. It introduces two new pages—one for visualizing and comparing brush features and another for configuring brush options—along with the necessary navigation and event handling logic. **New Brushes Feature Matrix functionality:** * Added a new entry for "Brushes Feature Matrix" to the gallery page factory list, making the new test page accessible from the app's main navigation. * Implemented the `BrushesControlPage` and `BrushesControlMainPage` classes to provide a navigation page and main content page for brush feature testing, including event handlers for comparing brushes and navigating to options. * Created the `BrushesControlPage.xaml` UI, which displays the current brush, stroke, and shadow settings, allows brush comparison, and shows selected color details. **Brush options and customization:** * Added a detailed `BrushesOptionsPage` (XAML and code-behind) that lets users select and configure brush types (none, solid, linear, radial), shadow types, stroke types, opacity, alternate variants, and color selections, with all changes bound to a shared `BrushesViewModel`. [[1]](diffhunk://#diff-a0b81253f3786054d00a4400d1fca4280fef128db5e618e0fae7bc845b7b70d8R1-R242) [[2]](diffhunk://#diff-f1180dfb2805a40c7a208076e415971e8e6639f58b9091c0a166c975671374d8R1-R130) https://github.com/user-attachments/assets/c4280d48-ebb3-45d3-a5bf-3388ea32e459
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! This pull request adds a comprehensive new brushes feature matrix test page to the controls test app, enabling interactive testing and configuration of brush, stroke, and shadow features, including solid, linear, and radial gradients. It introduces two new pages—one for visualizing and comparing brush features and another for configuring brush options—along with the necessary navigation and event handling logic. **New Brushes Feature Matrix functionality:** * Added a new entry for "Brushes Feature Matrix" to the gallery page factory list, making the new test page accessible from the app's main navigation. * Implemented the `BrushesControlPage` and `BrushesControlMainPage` classes to provide a navigation page and main content page for brush feature testing, including event handlers for comparing brushes and navigating to options. * Created the `BrushesControlPage.xaml` UI, which displays the current brush, stroke, and shadow settings, allows brush comparison, and shows selected color details. **Brush options and customization:** * Added a detailed `BrushesOptionsPage` (XAML and code-behind) that lets users select and configure brush types (none, solid, linear, radial), shadow types, stroke types, opacity, alternate variants, and color selections, with all changes bound to a shared `BrushesViewModel`. [[1]](diffhunk://#diff-a0b81253f3786054d00a4400d1fca4280fef128db5e618e0fae7bc845b7b70d8R1-R242) [[2]](diffhunk://#diff-f1180dfb2805a40c7a208076e415971e8e6639f58b9091c0a166c975671374d8R1-R130) https://github.com/user-attachments/assets/c4280d48-ebb3-45d3-a5bf-3388ea32e459
## What's Coming .NET MAUI inflight/candidate introduces significant improvements across all platforms with focus on quality, performance, and developer experience. This release includes 46 commits with various improvements, bug fixes, and enhancements. ## Button - [Android] Implemented material3 support for Button by @Dhivya-SF4094 in #33173 <details> <summary>🔧 Fixes</summary> - [Implement Material3 support for Button](#33172) </details> ## CollectionView - [Android] Fix RemainingItemsThresholdReachedCommand not firing when CollectionView has Header and Footer both defined by @SuthiYuvaraj in #29618 <details> <summary>🔧 Fixes</summary> - [Android : RemainingItemsThresholdReachedCommand not firing when CollectionVew has Header and Footer both defined](#29588) </details> - [iOS/MacCatalyst] Fix CollectionView ScrollTo for horizontal layouts by @Shalini-Ashokan in #33853 <details> <summary>🔧 Fixes</summary> - [[iOS/MacCatalyst] CollectionView ScrollTo does not work with horizontal Layout](#33852) </details> - [iOS & Mac] Fixed IndicatorView Size doesnt update dynamically by @SubhikshaSf4851 in #31129 <details> <summary>🔧 Fixes</summary> - [[iOS, Catalyst] IndicatorView.IndicatorSize does not update dynamically at runtime](#31064) </details> - [Android] Fix for CollectionView Scrolled event is triggered on the initial app load. by @BagavathiPerumal in #33558 <details> <summary>🔧 Fixes</summary> - [[Android] CollectionView Scrolled event is triggered on the initial app load.](#33333) </details> - [iOS, Android] Fix for CollectionView IsEnabled=false allows touch interactions by @praveenkumarkarunanithi in #31403 <details> <summary>🔧 Fixes</summary> - [More issues with CollectionView IsEnabled, InputTransparent, Opacity via Styles and code behind](#19771) </details> - [iOS] Fix VerticalOffset Update When Modifying CollectionView.ItemsSource While Scrolled by @devanathan-vaithiyanathan in #34153 <details> <summary>🔧 Fixes</summary> - [[iOS]VerticalOffset Not Reset to Zero After Clearing ItemSource in CollectionView](#26798) </details> ## DateTimePicker - [Android] Fix DatePicker MinimumDate/MaximumDate not updating dynamically by @HarishwaranVijayakumar in #33687 <details> <summary>🔧 Fixes</summary> - [[regression/8.0.3] [Android] DatePicker control minimum date issue](#19256) - [[Android] DatePicker does not update MinimumDate / MaximumDate in the Popup when set in the viewmodel after first opening](#33583) </details> ## Drawing - Android drawable perf by @albyrock87 in #31567 ## Editor - [Android] Implemented material3 support for Editor by @SyedAbdulAzeemSF4852 in #33478 <details> <summary>🔧 Fixes</summary> - [Implement Material3 Support for Editor](#33476) </details> ## Entry - [iOS, Mac] Fix for CursorPosition not updating when typing into Entry control by @SyedAbdulAzeemSF4852 in #30505 <details> <summary>🔧 Fixes</summary> - [Entry control CursorPosition does not update on TextChanged event [iOS Maui 8.0.7] ](#20911) - [CursorPosition not calculated correctly on behaviors events for iOS devices](#32483) </details> ## Flyoutpage - [Android, Windows] Fix for FlyoutPage toolbar button not updating on orientation change by @praveenkumarkarunanithi in #31962 <details> <summary>🔧 Fixes</summary> - [Flyout page in Android does not show flyout button (burger) consistently](#24468) </details> - Fix for First Item in CollectionView Overlaps in FlyoutPage.Flyout on iOS by @praveenkumarkarunanithi in #29265 <details> <summary>🔧 Fixes</summary> - [[iOS] CollectionView not rendering first item correctly in FlyoutPage.Flyout](#29170) </details> ## Image - [Android] Fix excessive memory usage for stream and resource-based image loading by @Shalini-Ashokan in #33590 <details> <summary>🔧 Fixes</summary> - [[Android] Unexpected high Bitmap.ByteCount when loading image via ImageSource.FromResource() or ImageSource.FromStream() in .NET MAUI](#33239) </details> - [Android] Fix for Resize method returns an image that has already been disposed by @SyedAbdulAzeemSF4852 in #29964 <details> <summary>🔧 Fixes</summary> - [In GraphicsView, the Resize method returns an image that has already been disposed](#29961) - [IIMage.Resize bugged behaviour](#31103) </details> ## Label - Fixed Label Span font property inheritance when applied via Style by @SubhikshaSf4851 in #34110 <details> <summary>🔧 Fixes</summary> - [`Span` does not inherit text styling from `Label` if that styling is applied using `Style` ](#21326) </details> - [Android] Implemented material3 support for Label by @SyedAbdulAzeemSF4852 in #33599 <details> <summary>🔧 Fixes</summary> - [Implement Material3 Support for Label](#33598) </details> ## Map - [Android] Fix Circle Stroke color is incorrectly updated as Fill color. by @NirmalKumarYuvaraj in #33643 <details> <summary>🔧 Fixes</summary> - [[Android] Circle Stroke color is incorrectly updated as Fill color.](#33642) </details> ## Mediapicker - [iOS] Fix: invoke MediaPicker completion handler after DismissViewController by @yuriikyry4enko in #34250 <details> <summary>🔧 Fixes</summary> - [[iOS] Media Picker UIImagePickerController closing issue](#21996) </details> ## Navigation - Fix ContentPage memory leak on Android when using NavigationPage modally (fixes #33918) by @brunck in #34117 <details> <summary>🔧 Fixes</summary> - [[Android] Modal TabbedPage whose tabs are NavigationPage(ContentPage) is retained after PopModalAsync()](#33918) </details> ## Picker - [Android] Implement material3 support for TimePicker by @HarishwaranVijayakumar in #33646 <details> <summary>🔧 Fixes</summary> - [Implement Material3 support for TimePicker](#33645) </details> - [Android] Implemented Material3 support for Picker by @SyedAbdulAzeemSF4852 in #33668 <details> <summary>🔧 Fixes</summary> - [Implement Material3 support for Picker](#33665) </details> ## RadioButton - [Android] Implemented material3 support for RadioButton by @SyedAbdulAzeemSF4852 in #33468 <details> <summary>🔧 Fixes</summary> - [Implement Material3 Support for RadioButton](#33467) </details> ## Setup - Clarify MA003 error message by @jeremy-visionaid in #34067 <details> <summary>🔧 Fixes</summary> - [MA003 false positive with 9.0.21](#26599) </details> ## Shell - [Android] Fix TabBar FlowDirection not updating dynamically by @SubhikshaSf4851 in #33091 <details> <summary>🔧 Fixes</summary> - [[Android, iOS] FlowDirection RTL is not updated dynamically on Shell TabBar](#32993) </details> - [Android] Fix page not disposed on Shell replace navigation by @Vignesh-SF3580 in #33426 <details> <summary>🔧 Fixes</summary> - [[Android] [Shell] replace navigation leaks current page](#25134) </details> - [Android] Fixed Shell flyout does not disable scrolling when FlyoutVerticalScrollMode is set to Disabled by @NanthiniMahalingam in #32734 <details> <summary>🔧 Fixes</summary> - [[Android] Shell.FlyoutVerticalScrollMode="Disabled" does not disable scrolling](#32477) </details> ## Single Project - Fix: Throw a clear error when an SVG lacks dimensions instead of a NullReferenceException by @Shalini-Ashokan in #33194 <details> <summary>🔧 Fixes</summary> - [MAUI Fails To Convert Valid SVG Files Into PNG Files (Object reference not set to an instance of an object)](#32460) </details> ## SwipeView - [iOS] Fix SwipeView stays open on iOS after updating content by @devanathan-vaithiyanathan in #31248 <details> <summary>🔧 Fixes</summary> - [[iOS] - Swipeview with collectionview issue](#19541) </details> ## TabbedPage - [Windows] Fixed IsEnabled Property not works on Tabs by @NirmalKumarYuvaraj in #26728 <details> <summary>🔧 Fixes</summary> - [ShellContent IsEnabledProperty does not work](#5161) - [[Windows] Shell Tab IsEnabled Not Working](#32996) </details> - [Android] Fix NavigationBar overlapping StatusBar when NavigationBar visibility changes by @Vignesh-SF3580 in #33359 <details> <summary>🔧 Fixes</summary> - [[Android] NavigationBar overlaps with StatusBar when mixing HasNavigationBar=true/false in TabbedPage on Android 15 (API 35)](#33340) </details> ## Templates - Fix for unable to open task using keyboard navigation on windows platform by @SuthiYuvaraj in #33647 <details> <summary>🔧 Fixes</summary> - [Unable to open task using keyboard: A11y_.NET maui_User can get all the insights of Dashboard_Keyboard](#30787) </details> ## TitleView - Fix for NavigationPage.TitleView does not expand with host window in iPadOS 26+ by @SuthiYuvaraj in #33088 ## Toolbar - [iOS] Fix toolbar items ignoring BarTextColor on iOS/MacCatalyst 26+ by @Shalini-Ashokan in #34036 <details> <summary>🔧 Fixes</summary> - [[iOS 26] ToolbarItem color with custom BarTextColor not working](#33970) </details> - [Android] Fix for ToolbarItem retaining the icon from the previous page on Android when using NavigationPage. by @BagavathiPerumal in #32311 <details> <summary>🔧 Fixes</summary> - [Toolbaritem keeps the icon of the previous page on Android, using NavigationPage (not shell)](#31727) </details> ## WebView - [Android] Fix WebView in a grid expands beyond it's cell by @devanathan-vaithiyanathan in #32145 <details> <summary>🔧 Fixes</summary> - [Android - WebView in a grid expands beyond it's cell](#32030) </details> ## Xaml - ContentPresenter: Propagate binding context to children with explicit TemplateBinding by @HarishwaranVijayakumar in #30880 <details> <summary>🔧 Fixes</summary> - [Binding context in ContentPresenter](#23797) </details> <details> <summary>🔧 Infrastructure (1)</summary> - [Revert] ContentPresenter: Propagate binding context to children with explicit TemplateBinding by @Ahamed-Ali in #34332 </details> <details> <summary>🧪 Testing (6)</summary> - [Testing] Feature Matrix UITest Cases for Shell Flyout Page by @NafeelaNazhir in #32525 - [Testing] Feature Matrix UITest Cases for Brushes by @LogishaSelvarajSF4525 in #31833 - [Testing] Feature Matrix UITest Cases for BindableLayout by @LogishaSelvarajSF4525 in #33108 - [Android] Add UI tests for Material 3 CheckBox by @HarishwaranVijayakumar in #34126 <details> <summary>🔧 Fixes</summary> - [[Android] Add UI tests for Material 3 CheckBox](#34125) </details> - [Testing] Feature Matrix UITest Cases for Shell Tabbed Page by @NafeelaNazhir in #33159 - [Testing] Fixed Test case failure in PR 34294 - [03/2/2026] Candidate - 1 by @TamilarasanSF4853 in #34334 </details> <details> <summary>📦 Other (2)</summary> - Bumps Syncfusion.Maui.Toolkit dependency to version 1.0.9 by @PaulAndersonS in #34178 - Fix crash when closing Windows based app when using TitleBar by @MFinkBK in #34032 <details> <summary>🔧 Fixes</summary> - [Unhandled exception "Value does not fall within the expected range" when closing Windows app](#32194) </details> </details> **Full Changelog**: main...inflight/candidate




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!
This pull request adds a comprehensive new brushes feature matrix test page to the controls test app, enabling interactive testing and configuration of brush, stroke, and shadow features, including solid, linear, and radial gradients. It introduces two new pages—one for visualizing and comparing brush features and another for configuring brush options—along with the necessary navigation and event handling logic.
New Brushes Feature Matrix functionality:
BrushesControlPageandBrushesControlMainPageclasses to provide a navigation page and main content page for brush feature testing, including event handlers for comparing brushes and navigating to options.BrushesControlPage.xamlUI, which displays the current brush, stroke, and shadow settings, allows brush comparison, and shows selected color details.Brush options and customization:
BrushesOptionsPage(XAML and code-behind) that lets users select and configure brush types (none, solid, linear, radial), shadow types, stroke types, opacity, alternate variants, and color selections, with all changes bound to a sharedBrushesViewModel. [1] [2]Screen.Recording.2025-10-01.at.10.10.36.AM.mov