Skip to content

Commit 5e69229

Browse files
authored
[2025/05/19] Candidate - In Flight Branch (#29473)
For more information about inflight process check https://github.com/dotnet/maui/wiki/Inflight-Branch-Process # .NET MAUI Release Notes ## New Release: May 21, 2025 We're excited to announce a new release of .NET MAUI with several bug fixes and improvements across various platforms. ### Bug Fixes #### iOS - **Map Control**: Fixed crash when navigating to a page containing a map more than once (#29369) - **CarouselView**: Fixed bounce-back behavior when Loop=false, ensuring proper scrolling experience (#29318) - **UIView**: Fixed NullReferenceException for UIView not being in UIWindow (#29460) #### Windows - **CarouselView**: Fixed HorizontalScrollBarVisibility="Never" not working properly (#29343) - **UI Controls**: Fixed the color not being applied to the Expand/Collapse Chevron icon (#29140) #### Windows & macOS - **Modal Navigation**: Fixed issue where Disappearing event was not triggered when closing a window with a modal page (#29129) #### Android - **Modal Pages**: Improved inheritance of StatusBar and NavigationBar background colors (#28568) - **Footer Scrolling**: Fixed footer scrolling issues in list controls (#29381) - **Modal Pages**: Improved inheritance of StatusBar and NavigationBar background colors on modal pages (#28568) #### Cross-Platform - **CarouselView**: Fixed ItemsLayout runtime updates to ensure proper layout behavior (#29447) - **CollectionView**: Fixed various issues in CollectionView implementation (#29423) ### Testing Improvements - Added feature matrix UITest cases for CollectionView dynamic changes (#29424) ### Code Quality - Fixed code formatting issues across the codebase - Minor typo corrections (#29379) ### Contributors This release was made possible by the hard work of our dedicated team and community contributors. We'd like to extend our gratitude to everyone who has contributed to this release. ### Installation This update is available through NuGet and the .NET SDK. Update your projects to get access to these fixes. ### Known Issues Please refer to our issue tracker for any known issues and their workarounds. --- For more information about .NET MAUI, visit [the official documentation](https://docs.microsoft.com/dotnet/maui/).
2 parents 79c97a0 + 9e79611 commit 5e69229

File tree

56 files changed

+2478
-39
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2478
-39
lines changed

eng/Versions.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<PatchVersion>80</PatchVersion>
66
<SdkBandVersion>9.0.100</SdkBandVersion>
77
<PreReleaseVersionLabel>ci.main</PreReleaseVersionLabel>
8-
<PreReleaseVersionLabel Condition="'$(BUILD_SOURCEBRANCHNAME)' == 'refs/heads/inflight/current'">ci.inflight</PreReleaseVersionLabel>
8+
<PreReleaseVersionLabel Condition="'$(BUILD_SOURCEBRANCH)' == 'refs/heads/inflight/current'">ci.inflight</PreReleaseVersionLabel>
99
<PreReleaseVersionIteration>
1010
</PreReleaseVersionIteration>
1111
<!-- Servicing builds have different characteristics for the way dependencies, baselines, and versions are handled. -->

src/Controls/src/Core/BindableObject.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ public void SetValue(BindableProperty property, object value)
482482
if (property == null)
483483
throw new ArgumentNullException(nameof(property));
484484

485-
if (value is BindingBase binding && !property.ReturnType.IsAssignableFrom(typeof(BindableProperty)))
485+
if (value is BindingBase binding && !property.ReturnType.IsAssignableFrom(typeof(BindingBase)))
486486
{
487487
SetBinding(property, binding);
488488
return;

src/Controls/src/Core/Handlers/Items/Android/Adapters/EmptyViewAdapter.cs

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ protected RecyclerView.ViewHolder CreateHeaderFooterViewHolder(object content, D
223223
}
224224

225225
// No template, Footer is not a Forms View, so just display Footer.ToString
226-
return SimpleViewHolder.FromText(content?.ToString(), context, false);
226+
return SimpleViewHolder.FromText(content?.ToString(), context, fill: false);
227227
}
228228

229229
protected RecyclerView.ViewHolder CreateEmptyViewHolder(object content, DataTemplate template, ViewGroup parent)
@@ -235,7 +235,7 @@ protected RecyclerView.ViewHolder CreateEmptyViewHolder(object content, DataTemp
235235
if (content is not View formsView)
236236
{
237237
// No template, EmptyView is not a Forms View, so just display EmptyView.ToString
238-
return SimpleViewHolder.FromText(content?.ToString(), context);
238+
return SimpleViewHolder.FromText(content?.ToString(), context, () => GetWidth(parent), () => GetHeight(parent), ItemsView);
239239
}
240240

241241
// EmptyView is a Forms View; display that
@@ -319,12 +319,47 @@ void UpdateHeaderFooterHeight(object item, bool isHeader)
319319
size = content.Measure(double.PositiveInfinity, double.PositiveInfinity);
320320
}
321321

322-
var itemHeight = size.Height;
322+
if (item is string text)
323+
{
324+
Label label = new Label { Text = text };
325+
TemplateHelpers.GetHandler(label, ItemsView.FindMauiContext());
326+
327+
size = label.Measure(double.PositiveInfinity, double.PositiveInfinity);
328+
}
329+
330+
if (IsVerticalItemsLayout())
331+
{
332+
var itemHeight = size.Height;
323333

324-
if (isHeader)
325-
_headerHeight = itemHeight;
326-
else
327-
_footerHeight = itemHeight;
334+
if (isHeader)
335+
{
336+
_headerHeight = itemHeight;
337+
}
338+
else
339+
{
340+
_footerHeight = itemHeight;
341+
}
342+
}
343+
}
344+
345+
bool IsVerticalItemsLayout()
346+
{
347+
if (ItemsView is CollectionView collectionView)
348+
{
349+
switch (collectionView.ItemsLayout)
350+
{
351+
case LinearItemsLayout linearLayout:
352+
{
353+
return linearLayout.Orientation == ItemsLayoutOrientation.Vertical;
354+
}
355+
case GridItemsLayout gridItemsLayout:
356+
{
357+
return gridItemsLayout.Orientation == ItemsLayoutOrientation.Vertical;
358+
}
359+
}
360+
}
361+
// Default
362+
return true;
328363
}
329364
}
330365
}

src/Controls/src/Core/Handlers/Items/Android/SimpleViewHolder.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,19 @@ public void Recycle(ItemsView itemsView)
2727
itemsView.RemoveLogicalChild(View);
2828
}
2929

30-
public static SimpleViewHolder FromText(string text, Context context, bool fill = true)
30+
public static SimpleViewHolder FromText(string text, Context context, Func<double> width = null, Func<double> height = null, ItemsView container = null, bool fill = true)
3131
{
32-
var textView = new TextView(context) { Text = text };
33-
3432
if (fill)
3533
{
36-
var layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent,
37-
ViewGroup.LayoutParams.MatchParent);
38-
textView.LayoutParameters = layoutParams;
34+
// When displaying an EmptyView with Header and Footer, we need to account for the Header and Footer sizes in layout calculations.
35+
// This prevents the EmptyView from occupying the full remaining space.
36+
Label label = new Label() { Text = text, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
37+
SizedItemContentView itemContentControl = new SizedItemContentView(context, width, height);
38+
itemContentControl.RealizeContent(label, container);
39+
return new SimpleViewHolder(itemContentControl, null);
3940
}
4041

41-
textView.Gravity = GravityFlags.Center;
42-
42+
TextView textView = new TextView(context) { Text = text, Gravity = GravityFlags.Center };
4343
return new SimpleViewHolder(textView, null);
4444
}
4545

src/Controls/src/Core/Handlers/Items/CarouselViewHandler.Android.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ public static void MapCurrentItem(CarouselViewHandler handler, CarouselView caro
5353
(handler.PlatformView as IMauiCarouselRecyclerView).UpdateFromCurrentItem();
5454
}
5555

56+
// TODO: Change the modifier to public in .NET 10.
57+
internal static void MapItemsLayout(CarouselViewHandler handler, CarouselView carouselView)
58+
{
59+
if (handler.PlatformView is IMauiRecyclerView<CarouselView> recyclerView)
60+
{
61+
recyclerView.UpdateLayoutManager();
62+
}
63+
}
64+
5665
public override Size GetDesiredSize(double widthConstraint, double heightConstraint)
5766
{
5867
_widthConstraint = widthConstraint;

src/Controls/src/Core/Handlers/Items/CarouselViewHandler.Windows.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,14 @@ protected override void OnScrollViewerFound(ScrollViewer scrollViewer)
9898
_scrollViewer.ViewChanged += OnScrollViewChanged;
9999
_scrollViewer.SizeChanged += OnScrollViewSizeChanged;
100100

101-
UpdateScrollBarVisibilityForLoop();
101+
if (Element.Loop)
102+
{
103+
UpdateScrollBarVisibilityForLoop();
104+
}
105+
else
106+
{
107+
UpdateScrollBarVisibility();
108+
}
102109
}
103110

104111
protected override ICollectionView GetCollectionView(CollectionViewSource collectionViewSource)

src/Controls/src/Core/Handlers/Items/CarouselViewHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public CarouselViewHandler(PropertyMapper mapper = null) : base(mapper ?? Mapper
1414

1515
public static PropertyMapper<CarouselView, CarouselViewHandler> Mapper = new(ItemsViewMapper)
1616
{
17-
#if TIZEN
17+
#if TIZEN || ANDROID
1818
[Controls.CarouselView.ItemsLayoutProperty.PropertyName] = MapItemsLayout,
1919
#endif
2020
[Controls.CarouselView.IsSwipeEnabledProperty.PropertyName] = MapIsSwipeEnabled,

src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,7 @@ protected virtual void UpdateItemsLayout()
351351

352352
UpdateItemTemplate();
353353
UpdateItemsSource();
354-
UpdateVerticalScrollBarVisibility();
355-
UpdateHorizontalScrollBarVisibility();
354+
UpdateScrollBarVisibility();
356355
UpdateEmptyView();
357356
}
358357

@@ -376,6 +375,12 @@ void ListViewLoaded(object sender, RoutedEventArgs e)
376375
listView.Loaded += ListViewLoaded;
377376
}
378377

378+
internal void UpdateScrollBarVisibility()
379+
{
380+
UpdateVerticalScrollBarVisibility();
381+
UpdateHorizontalScrollBarVisibility();
382+
}
383+
379384
void UpdateVerticalScrollBarVisibility()
380385
{
381386
if (Element.VerticalScrollBarVisibility != ScrollBarVisibility.Default)

src/Controls/src/Core/Handlers/Items2/CarouselViewHandler2.iOS.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ public CarouselViewHandler2(PropertyMapper mapper = null) : base(mapper ?? Mappe
2727
[Controls.CarouselView.PeekAreaInsetsProperty.PropertyName] = MapPeekAreaInsets,
2828
[Controls.CarouselView.IsBounceEnabledProperty.PropertyName] = MapIsBounceEnabled,
2929
[Controls.CarouselView.PositionProperty.PropertyName] = MapPosition,
30-
[Controls.CarouselView.CurrentItemProperty.PropertyName] = MapCurrentItem
30+
[Controls.CarouselView.CurrentItemProperty.PropertyName] = MapCurrentItem,
31+
[Controls.CarouselView.ItemsLayoutProperty.PropertyName] = MapItemsLayout,
3132
};
3233
}
3334

@@ -190,6 +191,12 @@ public static void MapIsBounceEnabled(CarouselViewHandler2 handler, CarouselView
190191
handler.Controller.CollectionView.Bounces = carouselView.IsBounceEnabled;
191192
}
192193

194+
// TODO: Change the modifier to public in .NET 10.
195+
internal static void MapItemsLayout(CarouselViewHandler2 handler, CarouselView carouselView)
196+
{
197+
handler?.UpdateLayout();
198+
}
199+
193200
public static void MapPeekAreaInsets(CarouselViewHandler2 handler, CarouselView carouselView)
194201
{
195202
handler.UpdateLayout();

src/Controls/src/Core/Handlers/Items2/iOS/LoopObservableItemsSource2.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public int LoopCount
5959
get
6060
{
6161
var newCount = ItemCount;
62-
if (newCount > 0)
62+
if (Loop && newCount > 0)
6363
{
6464
newCount = ItemCount + 2;
6565
}

0 commit comments

Comments
 (0)