diff --git a/Directory.Build.props b/Directory.Build.props
index 078ff0522111..da990ecdffe3 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -2,7 +2,9 @@
- <_MauiDotNetVersion Condition="'$(_MauiDotNetVersion)' == ''">6.0
+ <_MauiDotNetVersionMajor Condition="'$(_MauiDotNetVersionMajor)' == ''">6
+ <_MauiDotNetVersionMinor Condition="'$(_MauiDotNetVersionMinor)' == ''">0
+ <_MauiDotNetVersion Condition="'$(_MauiDotNetVersion)' == ''">$(_MauiDotNetVersionMajor).$(_MauiDotNetVersionMinor)
<_MauiDotNetTfm Condition="'$(_MauiDotNetTfm)' == ''">net$(_MauiDotNetVersion)
<_MauiTargetPlatformIdentifier>$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))
<_MauiNoTargetPlatform Condition="'$(_MauiTargetPlatformIdentifier)' == ''">True
diff --git a/Directory.Build.targets b/Directory.Build.targets
index dc0e3527e735..893e41bc2546 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -64,7 +64,7 @@
-
+
diff --git a/GitInfo.txt b/GitInfo.txt
index 7839c8834842..1319e68283f7 100644
--- a/GitInfo.txt
+++ b/GitInfo.txt
@@ -1 +1 @@
-6.0.400-preview.1
+6.0.500-preview.1
diff --git a/NuGet.config b/NuGet.config
index ac6afde6cd68..00cc8fc6d3fe 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -6,6 +6,7 @@
+
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 60d0f2a4153a..6538eb7e486d 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,32 +1,32 @@
-
+
https://github.com/dotnet/installer
- 3fed194c0b277b0ac0986f92401a50dd6c34f43d
+ 23d623452dda371b6d364b29a200e0856b45ec20
-
+
https://github.com/dotnet/runtime
- a21b9a2dd4c31cf5bd37626562b7612faf21cee6
+ 15626cf7e26af1c3800127242e47237698faed61
-
+
https://github.com/xamarin/xamarin-android
- 4c460a89cb070ee8dfd731842f36bc3dc68dc75c
+ 052bfb661739066b8598f5b0b066cee5a99a1e15
-
+
https://github.com/xamarin/xamarin-macios
- ce10c913a2921673b0caedcd268778b46d52c392
+ 4c190f21e2577c7071d47ab5f183a4cb65148b6f
-
+
https://github.com/xamarin/xamarin-macios
- ce10c913a2921673b0caedcd268778b46d52c392
+ 4c190f21e2577c7071d47ab5f183a4cb65148b6f
-
+
https://github.com/xamarin/xamarin-macios
- ce10c913a2921673b0caedcd268778b46d52c392
+ 4c190f21e2577c7071d47ab5f183a4cb65148b6f
-
+
https://github.com/xamarin/xamarin-macios
- ce10c913a2921673b0caedcd268778b46d52c392
+ 4c190f21e2577c7071d47ab5f183a4cb65148b6f
https://github.com/dotnet/emsdk
@@ -71,9 +71,9 @@
https://github.com/dotnet/templating
3f4da9ced34942d83054e647f3b1d9d7dde281e8
-
+
https://github.com/dotnet/Microsoft.Maui.Graphics
- e15f2d552d851c28771e7fe092895e908395f8a4
+ 691c654ff69df33f16f43b390ad6ef9b4ec03e6e
https://github.com/dotnet/xharness
diff --git a/eng/Versions.props b/eng/Versions.props
index 82d4b6e10b4f..38af24df30d7 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -1,26 +1,27 @@
- 6.0.301-rtm.22254.17
+ 6.0.400-preview.22302.1
- 6.0.5
+ 6.0.6
6.0.0
6.0.1
6.0.0
- 32.0.301
+ 32.0.415
- 15.4.303
- 15.4.303
- 12.3.303
- 15.4.303
- 7.0.303
+ 15.4.408
+ 15.4.408
+ 12.3.408
+ 15.4.408
+
+ 7.0.400-preview.1.0
6.0.4
$(MicrosoftNETWorkloadEmscriptenManifest60300PackageVersion)
- 1.0.3
+ 1.1.0
10.0.22000.194
1.0.3.1
@@ -36,7 +37,7 @@
7.0.0-preview1.22302.1
3.3.3
3.3.3
- 6.0.400-preview.1.1367
+ 6.0.403
4.5.0
<_MicrosoftWebWebView2Version>1.0.1210.39
@@ -64,13 +65,12 @@
- 6.0.300
-
- $(DotNetVersionBand)
- $(DotNetVersionBand)
- $(DotNetVersionBand)
- $(DotNetVersionBand)
- $(DotNetVersionBand)
- $(DotNetVersionBand)
+ 6.0.400
+ 6.0.300
+ 6.0.300
+ 6.0.300
+ 6.0.300
+ 6.0.400
+ 6.0.400
diff --git a/eng/pipelines/common/insertion.yml b/eng/pipelines/common/insertion.yml
index a0a8e58abb3e..38348463e0d8 100644
--- a/eng/pipelines/common/insertion.yml
+++ b/eng/pipelines/common/insertion.yml
@@ -21,7 +21,7 @@ stages:
- stage: sdk_insertion
displayName: 'SDK Insertion'
dependsOn: nuget_signing
- condition: and(succeeded(), or(eq(variables['Sign'], 'true'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), or(startsWith(variables['Build.SourceBranch'],'refs/tags/'), startsWith(variables['Build.SourceBranch'],'refs/heads/release/') ))))
+ condition: and(succeeded(), or(eq(variables['Sign'], 'true'), or(eq(variables['Build.SourceBranch'], 'refs/heads/net6.0'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), or(startsWith(variables['Build.SourceBranch'],'refs/tags/'), startsWith(variables['Build.SourceBranch'],'refs/heads/release/') )))))
jobs:
- template: sdk-insertion.yml
parameters:
@@ -31,7 +31,7 @@ stages:
- stage: sbom
displayName: 'Software Bill of Materials'
dependsOn: nuget_signing
- condition: and(succeeded(), or(eq(variables['Sign'], 'true'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), or(startsWith(variables['Build.SourceBranch'],'refs/tags/'), startsWith(variables['Build.SourceBranch'],'refs/heads/release/') ))))
+ condition: and(succeeded(), or(eq(variables['Sign'], 'true'), or(eq(variables['Build.SourceBranch'], 'refs/heads/net6.0'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), or(startsWith(variables['Build.SourceBranch'],'refs/tags/'), startsWith(variables['Build.SourceBranch'],'refs/heads/release/') )))))
jobs:
- template: compliance/sbom/job.v1.yml@xamarin-templates
parameters:
@@ -39,4 +39,4 @@ stages:
artifactMap: [ nuget/signed ] # Use artifacts that match the filter from the signed directory and not the top-level directory for the nuget artifact
packageName: 'Microsoft Maui'
packageFilter: '*.msi;*.nupkg'
- condition: and(succeeded(), or(eq(variables['Sign'], 'true'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), or(startsWith(variables['Build.SourceBranch'],'refs/tags/'), startsWith(variables['Build.SourceBranch'],'refs/heads/release/') ))))
+ condition: and(succeeded(), or(eq(variables['Sign'], 'true'), or(eq(variables['Build.SourceBranch'], 'refs/heads/net6.0'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), or(startsWith(variables['Build.SourceBranch'],'refs/tags/'), startsWith(variables['Build.SourceBranch'],'refs/heads/release/') )))))
diff --git a/eng/pipelines/common/sign.yml b/eng/pipelines/common/sign.yml
index 6f9b784f5afd..93a0088d6513 100644
--- a/eng/pipelines/common/sign.yml
+++ b/eng/pipelines/common/sign.yml
@@ -12,7 +12,7 @@ stages:
signedArtifactName: nuget
signedArtifactPath: signed
displayName: Sign Phase
- condition: and(succeeded(), or(eq(variables['Sign'], 'true'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), or(startsWith(variables['Build.SourceBranch'],'refs/tags/'), startsWith(variables['Build.SourceBranch'],'refs/heads/release/') ))))
+ condition: and(succeeded(), or(eq(variables['Sign'], 'true'), or(eq(variables['Build.SourceBranch'], 'refs/heads/net6.0'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), or(startsWith(variables['Build.SourceBranch'],'refs/tags/'), startsWith(variables['Build.SourceBranch'],'refs/heads/release/') )))))
- template: nuget-msi-convert/job/v2.yml@xamarin-templates
parameters:
diff --git a/src/Compatibility/Core/src/RendererToHandlerShim.Tizen.cs b/src/Compatibility/Core/src/RendererToHandlerShim.Tizen.cs
index dab4452aaab2..691b94b57da1 100644
--- a/src/Compatibility/Core/src/RendererToHandlerShim.Tizen.cs
+++ b/src/Compatibility/Core/src/RendererToHandlerShim.Tizen.cs
@@ -1,5 +1,6 @@
#pragma warning disable CS0612 // Type or member is obsolete
using Microsoft.Maui.Controls.Compatibility.Platform.Tizen;
+using static Microsoft.Maui.Controls.Compatibility.Platform.Tizen.Platform;
#pragma warning disable CS0612 // Type or member is obsolete
using Microsoft.Maui.Graphics;
using Rect = Microsoft.Maui.Graphics.Rect;
@@ -25,8 +26,9 @@ public override Size GetDesiredSize(double widthConstraint, double heightConstra
if (VisualElementRenderer == null)
return Size.Zero;
- // TODO. It is workaroud code, Controls.VisualElement.MeasureOverride implementation is wrong. it does not apply Height/WidthRequest
- return VisualElementRenderer.Element.Measure(widthConstraint, heightConstraint).Request;
+ widthConstraint = widthConstraint < 0 ? double.PositiveInfinity : widthConstraint;
+ heightConstraint = heightConstraint < 0 ? double.PositiveInfinity : heightConstraint;
+ return VisualElementRenderer.GetDesiredSize(widthConstraint, heightConstraint);
}
public override void UpdateValue(string property)
diff --git a/src/Controls/samples/Controls.Sample/Controls/Rate/Rate.cs b/src/Controls/samples/Controls.Sample/Controls/Rate/Rate.cs
new file mode 100644
index 000000000000..6db16bd63975
--- /dev/null
+++ b/src/Controls/samples/Controls.Sample/Controls/Rate/Rate.cs
@@ -0,0 +1,293 @@
+using System;
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Controls.Shapes;
+using Microsoft.Maui.Graphics;
+using System.Runtime.CompilerServices;
+using Microsoft.Maui;
+
+namespace Maui.Controls.Sample.Controls
+{
+ public class Rate : TemplatedView
+ {
+ const string ElementPanel = "PART_Panel";
+
+ StackLayout _rateLayout;
+
+ public static readonly BindableProperty IconProperty =
+ BindableProperty.Create(nameof(Icon), typeof(Geometry), typeof(Rate), GetDefaultIcon());
+
+ public Geometry Icon
+ {
+ get => (Geometry)GetValue(IconProperty);
+ set => SetValue(IconProperty, value);
+ }
+
+ static Geometry GetDefaultIcon()
+ {
+ Application.Current.Resources.TryGetValue("StarGeometry", out object resource);
+ PathGeometry pathGeometry = (PathGeometry)resource;
+
+ return pathGeometry;
+ }
+
+ public static readonly BindableProperty ItemSizeProperty =
+ BindableProperty.Create(nameof(ItemSize), typeof(double), typeof(Rate), 30.0d);
+
+ public double ItemSize
+ {
+ get => (double)GetValue(ItemSizeProperty);
+ set => SetValue(ItemSizeProperty, value);
+ }
+
+ public static readonly BindableProperty ItemCountProperty =
+ BindableProperty.Create(nameof(ItemCount), typeof(int), typeof(Rate), 5);
+
+ public int ItemCount
+ {
+ get => (int)GetValue(ItemCountProperty);
+ set => SetValue(ItemCountProperty, value);
+ }
+
+ public static readonly BindableProperty SelectedFillProperty =
+ BindableProperty.Create(nameof(SelectedFill), typeof(Color), typeof(Rate), Color.FromArgb("#F6C602"));
+
+ public Color SelectedFill
+ {
+ get => (Color)GetValue(SelectedFillProperty);
+ set => SetValue(SelectedFillProperty, value);
+ }
+
+ public static readonly BindableProperty UnSelectedFillProperty =
+ BindableProperty.Create(nameof(UnSelectedFill), typeof(Color), typeof(Rate), Colors.Transparent);
+
+ public Color UnSelectedFill
+ {
+ get => (Color)GetValue(UnSelectedFillProperty);
+ set => SetValue(UnSelectedFillProperty, value);
+ }
+
+ public static readonly BindableProperty SelectedStrokeProperty =
+ BindableProperty.Create(nameof(SelectedStroke), typeof(Color), typeof(Rate), Color.FromArgb("#F6C602"));
+
+ public Color SelectedStroke
+ {
+ get => (Color)GetValue(SelectedStrokeProperty);
+ set => SetValue(SelectedStrokeProperty, value);
+ }
+
+ public static readonly BindableProperty UnSelectedStrokeProperty =
+ BindableProperty.Create(nameof(UnSelectedStroke), typeof(Color), typeof(Rate), Colors.Black);
+
+ public Color UnSelectedStroke
+ {
+ get => (Color)GetValue(UnSelectedStrokeProperty);
+ set => SetValue(UnSelectedStrokeProperty, value);
+ }
+
+ public static readonly BindableProperty SelectedStrokeWidthProperty =
+ BindableProperty.Create(nameof(SelectedStrokeWidth), typeof(double), typeof(Rate), 1.0d);
+
+ public double SelectedStrokeWidth
+ {
+ get => (double)GetValue(SelectedStrokeWidthProperty);
+ set => SetValue(SelectedStrokeWidthProperty, value);
+ }
+
+ public static readonly BindableProperty UnSelectedStrokeWidthProperty =
+ BindableProperty.Create(nameof(UnSelectedStrokeWidth), typeof(double), typeof(Rate), 1.0d);
+
+ public double UnSelectedStrokeWidth
+ {
+ get => (double)GetValue(UnSelectedStrokeWidthProperty);
+ set => SetValue(UnSelectedStrokeWidthProperty, value);
+ }
+
+ public static readonly BindableProperty TextProperty =
+ BindableProperty.Create(nameof(Text), typeof(string), typeof(Rate), default(string));
+
+ public string Text
+ {
+ get => (string)GetValue(TextProperty);
+ set => SetValue(TextProperty, value);
+ }
+
+ public static readonly BindableProperty ShowTextProperty =
+ BindableProperty.Create(nameof(ShowText), typeof(bool), typeof(Rate), false);
+
+ public bool ShowText
+ {
+ get => (bool)GetValue(ShowTextProperty);
+ set => SetValue(ShowTextProperty, value);
+ }
+
+ public static readonly BindableProperty IsReadOnlyProperty =
+ BindableProperty.Create(nameof(IsReadOnly), typeof(bool), typeof(Rate), false,
+ propertyChanged: OnIsReadOnlyChanged);
+
+ static void OnIsReadOnlyChanged(BindableObject bindable, object oldValue, object newValue)
+ {
+ (bindable as Rate)?.UpdateIsReadOnly();
+ }
+
+ public bool IsReadOnly
+ {
+ get => (bool)GetValue(IsReadOnlyProperty);
+ set => SetValue(IsReadOnlyProperty, value);
+ }
+
+ public static readonly BindableProperty ValueProperty =
+ BindableProperty.Create(nameof(Value), typeof(int), typeof(Rate), default(int));
+
+ public int Value
+ {
+ get => (int)GetValue(ValueProperty);
+ set => SetValue(ValueProperty, value);
+ }
+
+ public event EventHandler ValueChanged;
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ _rateLayout = GetTemplateChild(ElementPanel) as StackLayout;
+
+ UpdateRateItems();
+ }
+
+ protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
+ {
+ base.OnPropertyChanged(propertyName);
+
+ if (propertyName == ValueProperty.PropertyName)
+ UpdateValue();
+ else if (propertyName == IconProperty.PropertyName)
+ UpdateIcon();
+ else if (propertyName == ItemCountProperty.PropertyName)
+ UpdateItemCount();
+ else if (propertyName == ItemSizeProperty.PropertyName)
+ UpdateItemSize();
+ else if (propertyName == SelectedFillProperty.PropertyName)
+ UpdateSelectedFill();
+ else if (propertyName == UnSelectedFillProperty.PropertyName)
+ UpdateUnSelectedFill();
+ else if (propertyName == SelectedStrokeProperty.PropertyName)
+ UpdateSelectedStroke();
+ else if (propertyName == UnSelectedStrokeProperty.PropertyName)
+ UpdateUnSelectedStroke();
+ else if (propertyName == SelectedStrokeWidthProperty.PropertyName)
+ UpdateSelectedStrokeWidth();
+ else if (propertyName == UnSelectedStrokeWidthProperty.PropertyName)
+ UpdateUnSelectedStrokeWidth();
+ }
+
+ void UpdateRateItems()
+ {
+ _rateLayout.Children.Clear();
+
+ for (var i = 1; i <= ItemCount; i++)
+ {
+ var rateItem = new RateItem();
+
+ _rateLayout.Children.Add((IView)rateItem);
+ }
+
+ UpdateIsReadOnly();
+ UpdateIcon();
+ UpdateItemSize();
+ UpdateSelectedFill();
+ UpdateUnSelectedFill();
+ UpdateSelectedStroke();
+ UpdateUnSelectedStroke();
+ UpdateSelectedStrokeWidth();
+ UpdateUnSelectedStrokeWidth();
+ }
+
+ void UpdateIsReadOnly()
+ {
+ if (IsReadOnly)
+ {
+ foreach (var rateItem in _rateLayout.Children)
+ (rateItem as View)?.GestureRecognizers.Clear();
+ }
+ else
+ {
+ foreach (var rateItem in _rateLayout.Children)
+ {
+ var tapGestureRecognizer = new TapGestureRecognizer();
+ tapGestureRecognizer.Tapped += OnTapped;
+ (rateItem as View)?.GestureRecognizers.Add(tapGestureRecognizer);
+ }
+ }
+ }
+
+ void UpdateIcon()
+ {
+ foreach (var child in _rateLayout.Children)
+ ((RateItem)child).Icon = Icon;
+ }
+
+ void UpdateItemCount()
+ {
+ UpdateRateItems();
+ }
+
+ void UpdateItemSize()
+ {
+ foreach (var child in _rateLayout.Children)
+ ((RateItem)child).ItemSize = ItemSize;
+ }
+
+ void UpdateSelectedFill()
+ {
+ foreach (var child in _rateLayout.Children)
+ ((RateItem)child).SelectedFill = SelectedFill;
+ }
+
+ void UpdateUnSelectedFill()
+ {
+ foreach (var child in _rateLayout.Children)
+ ((RateItem)child).UnSelectedFill = UnSelectedFill;
+ }
+
+ void UpdateSelectedStroke()
+ {
+ foreach (var child in _rateLayout.Children)
+ ((RateItem)child).SelectedFill = SelectedFill;
+ }
+
+ void UpdateUnSelectedStroke()
+ {
+ foreach (var child in _rateLayout.Children)
+ ((RateItem)child).UnSelectedFill = UnSelectedFill;
+ }
+
+ void UpdateSelectedStrokeWidth()
+ {
+ foreach (var child in _rateLayout.Children)
+ ((RateItem)child).SelectedStrokeWidth = SelectedStrokeWidth;
+ }
+
+ void UpdateUnSelectedStrokeWidth()
+ {
+ foreach (var child in _rateLayout.Children)
+ ((RateItem)child).UnSelectedStrokeWidth = UnSelectedStrokeWidth;
+ }
+
+ void UpdateValue()
+ {
+ for (int i = 0; i < ItemCount; i++)
+ ((RateItem)_rateLayout.Children[i]).IsSelected = i < Value;
+
+ ValueChanged?.Invoke(this, new ValueChangedEventArgs(Value));
+ }
+
+ void OnTapped(object sender, EventArgs e)
+ {
+ var star = (IView)sender;
+ var index = _rateLayout.Children.IndexOf(star);
+
+ Value = index + 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/samples/Controls.Sample/Controls/Rate/Rate.xaml b/src/Controls/samples/Controls.Sample/Controls/Rate/Rate.xaml
new file mode 100644
index 000000000000..6a359ca4b54a
--- /dev/null
+++ b/src/Controls/samples/Controls.Sample/Controls/Rate/Rate.xaml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Controls/samples/Controls.Sample/Controls/Rate/Rate.xaml.cs b/src/Controls/samples/Controls.Sample/Controls/Rate/Rate.xaml.cs
new file mode 100644
index 000000000000..c5076524ddd5
--- /dev/null
+++ b/src/Controls/samples/Controls.Sample/Controls/Rate/Rate.xaml.cs
@@ -0,0 +1,12 @@
+using Microsoft.Maui.Controls;
+
+namespace Maui.Controls.Sample.Themes
+{
+ public partial class Rate : ResourceDictionary
+ {
+ public Rate()
+ {
+ InitializeComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/samples/Controls.Sample/Controls/Rate/RateItem.cs b/src/Controls/samples/Controls.Sample/Controls/Rate/RateItem.cs
new file mode 100644
index 000000000000..02632d08218c
--- /dev/null
+++ b/src/Controls/samples/Controls.Sample/Controls/Rate/RateItem.cs
@@ -0,0 +1,111 @@
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Controls.Shapes;
+using Microsoft.Maui.Graphics;
+
+namespace Maui.Controls.Sample.Controls
+{
+ public class RateItem : TemplatedView
+ {
+ const string ElementIcon = "PART_Icon";
+
+ View _icon;
+
+ public static readonly BindableProperty ItemSizeProperty =
+ BindableProperty.Create(nameof(ItemSize), typeof(double), typeof(RateItem), 30.0d);
+
+ public double ItemSize
+ {
+ get => (double)GetValue(ItemSizeProperty);
+ set => SetValue(ItemSizeProperty, value);
+ }
+
+ public static readonly BindableProperty SelectedFillProperty =
+ BindableProperty.Create(nameof(SelectedFill), typeof(Color), typeof(RateItem), Color.FromArgb("#F6C602"));
+
+ public Color SelectedFill
+ {
+ get => (Color)GetValue(SelectedFillProperty);
+ set => SetValue(SelectedFillProperty, value);
+ }
+
+ public static readonly BindableProperty UnSelectedFillProperty =
+ BindableProperty.Create(nameof(UnSelectedFill), typeof(Color), typeof(RateItem), Colors.Transparent);
+
+ public Color UnSelectedFill
+ {
+ get => (Color)GetValue(UnSelectedFillProperty);
+ set => SetValue(UnSelectedFillProperty, value);
+ }
+
+ public static readonly BindableProperty SelectedStrokeProperty =
+ BindableProperty.Create(nameof(SelectedStroke), typeof(Color), typeof(RateItem), Color.FromArgb("#F6C602"));
+
+ public Color SelectedStroke
+ {
+ get => (Color)GetValue(SelectedStrokeProperty);
+ set => SetValue(SelectedStrokeProperty, value);
+ }
+
+ public static readonly BindableProperty UnSelectedStrokeProperty =
+ BindableProperty.Create(nameof(UnSelectedStroke), typeof(Color), typeof(RateItem), Colors.Black);
+
+ public Color UnSelectedStroke
+ {
+ get => (Color)GetValue(UnSelectedStrokeProperty);
+ set => SetValue(UnSelectedStrokeProperty, value);
+ }
+
+ public static readonly BindableProperty SelectedStrokeWidthProperty =
+ BindableProperty.Create(nameof(SelectedStrokeWidth), typeof(double), typeof(RateItem), 1.0d);
+
+ public double SelectedStrokeWidth
+ {
+ get => (double)GetValue(SelectedStrokeWidthProperty);
+ set => SetValue(SelectedStrokeWidthProperty, value);
+ }
+
+ public static readonly BindableProperty UnSelectedStrokeWidthProperty =
+ BindableProperty.Create(nameof(UnSelectedStrokeWidth), typeof(double), typeof(RateItem), 1.0d);
+
+ public double UnSelectedStrokeWidth
+ {
+ get => (double)GetValue(UnSelectedStrokeWidthProperty);
+ set => SetValue(UnSelectedStrokeWidthProperty, value);
+ }
+
+ public static readonly BindableProperty IconProperty =
+ BindableProperty.Create(nameof(Icon), typeof(Geometry), typeof(RateItem), null);
+
+ public Geometry Icon
+ {
+ get => (Geometry)GetValue(IconProperty);
+ set => SetValue(IconProperty, value);
+ }
+
+ public static readonly BindableProperty IsReadOnlyProperty =
+ BindableProperty.Create(nameof(IsReadOnly), typeof(bool), typeof(RateItem), false);
+
+ public bool IsReadOnly
+ {
+ get => (bool)GetValue(IsReadOnlyProperty);
+ set => SetValue(IsReadOnlyProperty, value);
+ }
+
+ public static readonly BindableProperty IsSelectedProperty =
+ BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(RateItem), false);
+
+ public bool IsSelected
+ {
+ get => (bool)GetValue(IsSelectedProperty);
+ set => SetValue(IsSelectedProperty, value);
+ }
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ _icon = GetTemplateChild(ElementIcon) as View;
+ _icon.WidthRequest = Width;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/samples/Controls.Sample/Controls/Rate/ValueChangedEventArgs.cs b/src/Controls/samples/Controls.Sample/Controls/Rate/ValueChangedEventArgs.cs
new file mode 100644
index 000000000000..4bff418fa8b6
--- /dev/null
+++ b/src/Controls/samples/Controls.Sample/Controls/Rate/ValueChangedEventArgs.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Maui.Controls.Sample.Controls
+{
+ public class ValueChangedEventArgs : EventArgs
+ {
+ public ValueChangedEventArgs(double value)
+ {
+ Value = value;
+ }
+
+ public double Value { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/samples/Controls.Sample/Pages/Layouts/TemplatedViewPage.xaml b/src/Controls/samples/Controls.Sample/Pages/Layouts/TemplatedViewPage.xaml
index 0949ca931c19..3da5a11f32b9 100644
--- a/src/Controls/samples/Controls.Sample/Pages/Layouts/TemplatedViewPage.xaml
+++ b/src/Controls/samples/Controls.Sample/Pages/Layouts/TemplatedViewPage.xaml
@@ -35,7 +35,11 @@
-
+
+
+
@@ -78,6 +82,22 @@
IconBackgroundColor="SlateGray"
IconImageSource="dotnet_bot.png"
ControlTemplate="{StaticResource CardViewCompressed}" />
+
+
\ No newline at end of file
diff --git a/src/Controls/samples/Controls.Sample/XamlApp.xaml b/src/Controls/samples/Controls.Sample/XamlApp.xaml
index 5ce66addea29..564f3cc1f1cd 100644
--- a/src/Controls/samples/Controls.Sample/XamlApp.xaml
+++ b/src/Controls/samples/Controls.Sample/XamlApp.xaml
@@ -9,6 +9,7 @@
+
diff --git a/src/Controls/src/Core/Compatibility/Handlers/Android/ViewRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Android/ViewRenderer.cs
index 7230f0ce1079..329d20940976 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/Android/ViewRenderer.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/Android/ViewRenderer.cs
@@ -20,8 +20,19 @@ public abstract partial class ViewRenderer : VisualElem
TPlatformView? _platformView;
AViewGroup? _container;
- public TPlatformView? Control => ((IElementHandler)this).PlatformView as TPlatformView ?? _platformView;
- object? IElementHandler.PlatformView => _platformView;
+ public TPlatformView? Control
+ {
+ get
+ {
+ var value = ((IElementHandler)this).PlatformView as TPlatformView;
+ if (value != this && value != null)
+ return value;
+
+ return _platformView;
+ }
+ }
+
+ object? IElementHandler.PlatformView => (_platformView as object) ?? this;
public ViewRenderer(Context context) : this(context, VisualElementRendererMapper, VisualElementRendererCommandMapper)
{
diff --git a/src/Controls/src/Core/Compatibility/Handlers/Android/VisualElementRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Android/VisualElementRenderer.cs
index 80ae9137cec3..aaa7b9752edb 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/Android/VisualElementRenderer.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/Android/VisualElementRenderer.cs
@@ -12,7 +12,10 @@ namespace Microsoft.Maui.Controls.Handlers.Compatibility
public abstract partial class VisualElementRenderer : AViewGroup, IPlatformViewHandler
where TElement : Element, IView
{
- object? IElementHandler.PlatformView => ChildCount > 0 ? GetChildAt(0) : null;
+ object? IElementHandler.PlatformView
+ {
+ get => ChildCount > 0 ? GetChildAt(0) : this;
+ }
static partial void ProcessAutoPackage(Maui.IElement element)
{
diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFragmentStateAdapter.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFragmentStateAdapter.cs
index 83ee94b9a1cb..a98ea265c8a6 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFragmentStateAdapter.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFragmentStateAdapter.cs
@@ -27,11 +27,10 @@ public ShellFragmentStateAdapter(
{
_mauiContext = mauiContext;
_shellSection = shellSection;
- SectionController.ItemsCollectionChanged += OnItemsCollectionChanged;
_items = SectionController.GetItems();
}
- protected virtual void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ public void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
_items = SectionController.GetItems();
var removeList = new List();
@@ -42,8 +41,6 @@ protected virtual void OnItemsCollectionChanged(object sender, NotifyCollectionC
foreach (var remove in removeList)
_createdShellContent.Remove(remove);
-
- NotifyDataSetChanged();
}
public int CountOverride { get; set; }
@@ -70,6 +67,14 @@ public override long GetItemId(int position)
public override bool ContainsItem(long itemId)
{
+ if (_createdShellContent.TryGetValue(itemId, out var shellContent) &&
+ !_items.Contains(shellContent))
+ {
+ // This means a data set change was triggered but the INCC change hasn't
+ // propagated from our xplat code to here yet
+ _createdShellContent.Remove(itemId);
+ }
+
return _createdShellContent.ContainsKey(itemId);
}
@@ -82,7 +87,6 @@ protected override void Dispose(bool disposing)
if (disposing)
{
- SectionController.ItemsCollectionChanged -= OnItemsCollectionChanged;
_shellSection = null;
_items = null;
diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs
index 7e9e54d99e73..834b8b3eb963 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs
@@ -12,6 +12,7 @@
using AndroidX.ViewPager.Widget;
using AndroidX.ViewPager2.Widget;
using Google.Android.Material.Tabs;
+using Microsoft.Extensions.Logging;
using AToolbar = AndroidX.AppCompat.Widget.Toolbar;
using AView = Android.Views.View;
@@ -226,6 +227,45 @@ protected virtual void OnAnimationFinished(EventArgs e)
protected virtual void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
UpdateTablayoutVisibility();
+
+ if (_viewPager?.Adapter is ShellFragmentStateAdapter adapter)
+ {
+ adapter.OnItemsCollectionChanged(sender, e);
+ SafeNotifyDataSetChanged();
+ }
+ }
+
+ void SafeNotifyDataSetChanged(int iteration = 0)
+ {
+ if (_disposed)
+ return;
+
+ if (!_viewPager.IsAlive())
+ return;
+
+ if (iteration >= 10)
+ {
+ // It's very unlikely this will happen but just in case there's a scenario
+ // where we might hit an infinite loop we're adding an exit strategy
+ MauiContext.CreateLogger()
+ .LogWarning("ViewPager2 stuck in layout, unable to NotifyDataSetChanged;");
+
+ return;
+ }
+
+ if (_viewPager?.Adapter is ShellFragmentStateAdapter adapter)
+ {
+ // https://stackoverflow.com/questions/43221847/cannot-call-this-method-while-recyclerview-is-computing-a-layout-or-scrolling-wh
+ // ViewPager2 is based on RecyclerView which really doesn't like NotifyDataSetChanged when a layout is happening
+ if (!_viewPager.IsInLayout)
+ {
+ adapter.NotifyDataSetChanged();
+ }
+ else
+ {
+ _viewPager.Post(() => SafeNotifyDataSetChanged(++iteration));
+ }
+ }
}
void UpdateTablayoutVisibility()
@@ -258,7 +298,9 @@ protected virtual void OnShellItemPropertyChanged(object sender, PropertyChanged
var newIndex = SectionController.GetItems().IndexOf(ShellSection.CurrentItem);
if (SectionController.GetItems().Count != _viewPager.ChildCount)
- _viewPager.Adapter.NotifyDataSetChanged();
+ {
+ SafeNotifyDataSetChanged();
+ }
if (newIndex >= 0)
{
@@ -299,7 +341,15 @@ protected virtual void OnPageSelected(int position)
return;
var shellSection = ShellSection;
- var shellContent = SectionController.GetItems()[position];
+ var visibleItems = SectionController.GetItems();
+
+ // This mainly happens if all of the items that are part of this shell section
+ // vanish. Android calls `OnPageSelected` with position zero even though the view pager is
+ // empty
+ if (visibleItems.Count >= position)
+ return;
+
+ var shellContent = visibleItems[position];
if (shellContent == shellSection.CurrentItem)
return;
@@ -314,7 +364,7 @@ protected virtual void OnPageSelected(int position)
}
else if (shellSection?.CurrentItem != null)
{
- var currentPosition = SectionController.GetItems().IndexOf(shellSection.CurrentItem);
+ var currentPosition = visibleItems.IndexOf(shellSection.CurrentItem);
_selecting = true;
// Android doesn't really appreciate you calling SetCurrentItem inside a OnPageSelected callback.
diff --git a/src/Controls/src/Core/Compatibility/Handlers/VisualElementRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/VisualElementRenderer.cs
index a477d2958b1e..70829f5f4161 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/VisualElementRenderer.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/VisualElementRenderer.cs
@@ -213,7 +213,10 @@ protected virtual void SetImportantForAccessibility()
IMauiContext? IElementHandler.MauiContext => _mauiContext;
- PlatformView? IPlatformViewHandler.PlatformView => (Element?.Handler as IElementHandler)?.PlatformView as PlatformView;
+ PlatformView? IPlatformViewHandler.PlatformView
+ {
+ get => ((Element?.Handler)?.PlatformView as PlatformView) ?? this;
+ }
PlatformView? IPlatformViewHandler.ContainerView => this;
diff --git a/src/Controls/src/Core/Compatibility/Handlers/Windows/VisualElementRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Windows/VisualElementRenderer.cs
index e077e587d3b8..d012931064a9 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/Windows/VisualElementRenderer.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/Windows/VisualElementRenderer.cs
@@ -18,8 +18,22 @@ public abstract partial class VisualElementRenderer
TPlatformElement? _nativeView;
public FrameworkElement ContainerElement => this;
- public TPlatformElement? Control => ((IElementHandler)this).PlatformView as TPlatformElement ?? _nativeView;
- object? IElementHandler.PlatformView => _nativeView;
+ public TPlatformElement? Control
+ {
+ get
+ {
+ var value = ((IElementHandler)this).PlatformView as TPlatformElement;
+ if (value != this && value != null)
+ return value;
+
+ return _nativeView;
+ }
+ }
+
+ object? IElementHandler.PlatformView
+ {
+ get => (_nativeView as object) ?? this;
+ }
public UIElement? GeTPlatformElement() => Control;
diff --git a/src/Controls/src/Core/Compatibility/Handlers/iOS/ViewRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/iOS/ViewRenderer.cs
index 140a4c7d0103..c07a95434f54 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/iOS/ViewRenderer.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/iOS/ViewRenderer.cs
@@ -1,8 +1,5 @@
#nullable enable
-using System;
using CoreGraphics;
-using Microsoft.Maui.Graphics;
-using ObjCRuntime;
using UIKit;
using PlatformView = UIKit.UIView;
@@ -21,8 +18,19 @@ public abstract partial class ViewRenderer : VisualElem
{
TPlatformView? _nativeView;
- public TPlatformView? Control => ((IElementHandler)this).PlatformView as TPlatformView ?? _nativeView;
- object? IElementHandler.PlatformView => _nativeView;
+ public TPlatformView? Control
+ {
+ get
+ {
+ var value = ((IElementHandler)this).PlatformView as TPlatformView;
+ if (value != this && value != null)
+ return value;
+
+ return _nativeView;
+ }
+ }
+
+ object? IElementHandler.PlatformView => (_nativeView as object) ?? this;
public ViewRenderer() : this(VisualElementRendererMapper, VisualElementRendererCommandMapper)
{
diff --git a/src/Controls/src/Core/Compatibility/Handlers/iOS/VisualElementRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/iOS/VisualElementRenderer.cs
index cd7e4f1dc5b1..6a22ad51da66 100644
--- a/src/Controls/src/Core/Compatibility/Handlers/iOS/VisualElementRenderer.cs
+++ b/src/Controls/src/Core/Compatibility/Handlers/iOS/VisualElementRenderer.cs
@@ -10,7 +10,7 @@ namespace Microsoft.Maui.Controls.Handlers.Compatibility
public abstract partial class VisualElementRenderer : UIView, IPlatformViewHandler, IElementHandler
where TElement : Element, IView
{
- object? IElementHandler.PlatformView => Subviews.Length > 0 ? Subviews[0] : null;
+ object? IElementHandler.PlatformView => Subviews.Length > 0 ? Subviews[0] : this;
public virtual UIViewController? ViewController => null;
diff --git a/src/Controls/src/Core/ContentPresenter.cs b/src/Controls/src/Core/ContentPresenter.cs
index 2dd042dca692..189e9cdf4407 100644
--- a/src/Controls/src/Core/ContentPresenter.cs
+++ b/src/Controls/src/Core/ContentPresenter.cs
@@ -99,11 +99,24 @@ static async void OnContentChanged(BindableObject bindable, object oldValue, obj
}
}
+ protected override Size MeasureOverride(double widthConstraint, double heightConstraint)
+ {
+ DesiredSize = this.ComputeDesiredSize(widthConstraint, heightConstraint);
+ return DesiredSize;
+ }
+
Size IContentView.CrossPlatformMeasure(double widthConstraint, double heightConstraint)
{
return this.MeasureContent(widthConstraint, heightConstraint);
}
+ protected override Size ArrangeOverride(Rect bounds)
+ {
+ Frame = this.ComputeFrame(bounds);
+ Handler?.PlatformArrange(Frame);
+ return Frame.Size;
+ }
+
Size IContentView.CrossPlatformArrange(Rect bounds)
{
this.ArrangeContent(bounds);
diff --git a/src/Controls/src/Core/ContentView.cs b/src/Controls/src/Core/ContentView.cs
index 672d9f247542..1c7a9705732b 100644
--- a/src/Controls/src/Core/ContentView.cs
+++ b/src/Controls/src/Core/ContentView.cs
@@ -42,29 +42,5 @@ internal override void OnControlTemplateChanged(ControlTemplate oldValue, Contro
SetInheritedBindingContext(content, BindingContext);
}
}
-
- protected override Size MeasureOverride(double widthConstraint, double heightConstraint)
- {
- DesiredSize = this.ComputeDesiredSize(widthConstraint, heightConstraint);
- return DesiredSize;
- }
-
- Size IContentView.CrossPlatformMeasure(double widthConstraint, double heightConstraint)
- {
- return this.MeasureContent(widthConstraint, heightConstraint);
- }
-
- protected override Size ArrangeOverride(Rect bounds)
- {
- Frame = this.ComputeFrame(bounds);
- Handler?.PlatformArrange(Frame);
- return Frame.Size;
- }
-
- Size IContentView.CrossPlatformArrange(Rect bounds)
- {
- this.ArrangeContent(bounds);
- return bounds.Size;
- }
}
}
\ No newline at end of file
diff --git a/src/Controls/src/Core/HandlerImpl/ContentView/ContentView.Impl.cs b/src/Controls/src/Core/HandlerImpl/ContentView/ContentView.Impl.cs
index 4c44965267a4..46ca9922cdb9 100644
--- a/src/Controls/src/Core/HandlerImpl/ContentView/ContentView.Impl.cs
+++ b/src/Controls/src/Core/HandlerImpl/ContentView/ContentView.Impl.cs
@@ -3,12 +3,7 @@
public partial class ContentView : IContentView
{
object IContentView.Content => Content;
- IView IContentView.PresentedContent => ((this as IControlTemplated).TemplateRoot as IView) ?? Content;
- protected override void OnApplyTemplate()
- {
- base.OnApplyTemplate();
- Handler?.UpdateValue(nameof(Content));
- }
+ IView IContentView.PresentedContent => ((this as IControlTemplated).TemplateRoot as IView) ?? Content;
}
}
diff --git a/src/Controls/src/Core/HandlerImpl/Page.Impl.cs b/src/Controls/src/Core/HandlerImpl/Page.Impl.cs
index 656f6d7d49a7..ba9624a40f1d 100644
--- a/src/Controls/src/Core/HandlerImpl/Page.Impl.cs
+++ b/src/Controls/src/Core/HandlerImpl/Page.Impl.cs
@@ -7,6 +7,8 @@ namespace Microsoft.Maui.Controls
///
public partial class Page : IView, ITitledElement, IToolbarElement
{
+ internal bool HasNavigatedTo { get; private set; }
+
Paint IView.Background
{
get
@@ -40,6 +42,7 @@ internal Toolbar Toolbar
internal void SendNavigatedTo(NavigatedToEventArgs args)
{
+ HasNavigatedTo = true;
NavigatedTo?.Invoke(this, args);
OnNavigatedTo(args);
}
@@ -52,6 +55,7 @@ internal void SendNavigatingFrom(NavigatingFromEventArgs args)
internal void SendNavigatedFrom(NavigatedFromEventArgs args)
{
+ HasNavigatedTo = false;
NavigatedFrom?.Invoke(this, args);
OnNavigatedFrom(args);
}
diff --git a/src/Controls/src/Core/HandlerImpl/RadioButton/RadioButton.Impl.cs b/src/Controls/src/Core/HandlerImpl/RadioButton/RadioButton.Impl.cs
index 0feef6ac5ecf..4bfacdbe4430 100644
--- a/src/Controls/src/Core/HandlerImpl/RadioButton/RadioButton.Impl.cs
+++ b/src/Controls/src/Core/HandlerImpl/RadioButton/RadioButton.Impl.cs
@@ -12,30 +12,6 @@ public partial class RadioButton : IRadioButton
object IContentView.Content => ContentAsString();
#endif
- protected override Size MeasureOverride(double widthConstraint, double heightConstraint)
- {
- DesiredSize = this.ComputeDesiredSize(widthConstraint, heightConstraint);
- return DesiredSize;
- }
-
- Size IContentView.CrossPlatformMeasure(double widthConstraint, double heightConstraint)
- {
- return this.MeasureContent(widthConstraint, heightConstraint);
- }
-
- protected override Size ArrangeOverride(Rect bounds)
- {
- Frame = this.ComputeFrame(bounds);
- Handler?.PlatformArrange(Frame);
- return Frame.Size;
- }
-
- Size IContentView.CrossPlatformArrange(Rect bounds)
- {
- this.ArrangeContent(bounds);
- return bounds.Size;
- }
-
IView IContentView.PresentedContent => ((this as IControlTemplated).TemplateRoot as IView) ?? (Content as IView);
double IButtonStroke.StrokeThickness => (double)GetValue(BorderWidthProperty);
diff --git a/src/Controls/src/Core/HandlerImpl/TemplatedView/TemplatedView.Impl.cs b/src/Controls/src/Core/HandlerImpl/TemplatedView/TemplatedView.Impl.cs
new file mode 100644
index 000000000000..9ad2a42fc041
--- /dev/null
+++ b/src/Controls/src/Core/HandlerImpl/TemplatedView/TemplatedView.Impl.cs
@@ -0,0 +1,43 @@
+#nullable enable
+using Microsoft.Maui.Graphics;
+using Microsoft.Maui.Layouts;
+
+namespace Microsoft.Maui.Controls
+{
+ public partial class TemplatedView : IContentView
+ {
+ object? IContentView.Content => null;
+
+ IView? IContentView.PresentedContent =>
+ (this as IControlTemplated).TemplateRoot as IView;
+
+ partial void OnApplyTemplateImpl()
+ {
+ Handler?.UpdateValue(nameof(IContentView.Content));
+ }
+
+ protected override Size MeasureOverride(double widthConstraint, double heightConstraint)
+ {
+ DesiredSize = this.ComputeDesiredSize(widthConstraint, heightConstraint);
+ return DesiredSize;
+ }
+
+ Size IContentView.CrossPlatformMeasure(double widthConstraint, double heightConstraint)
+ {
+ return this.MeasureContent(widthConstraint, heightConstraint);
+ }
+
+ protected override Size ArrangeOverride(Rect bounds)
+ {
+ Frame = this.ComputeFrame(bounds);
+ Handler?.PlatformArrange(Frame);
+ return Frame.Size;
+ }
+
+ Size IContentView.CrossPlatformArrange(Rect bounds)
+ {
+ this.ArrangeContent(bounds);
+ return bounds.Size;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/src/Core/Handlers/Items/Android/Adapters/SelectableItemsViewAdapter.cs b/src/Controls/src/Core/Handlers/Items/Android/Adapters/SelectableItemsViewAdapter.cs
index f94f9c328b63..0c66205ba662 100644
--- a/src/Controls/src/Core/Handlers/Items/Android/Adapters/SelectableItemsViewAdapter.cs
+++ b/src/Controls/src/Core/Handlers/Items/Android/Adapters/SelectableItemsViewAdapter.cs
@@ -136,7 +136,6 @@ void UpdateMauiSelection(int adapterPosition)
return;
case SelectionMode.Single:
ItemsView.SelectedItem = ItemsSource.GetItem(adapterPosition);
- RefreshViewHolderSelection();
return;
case SelectionMode.Multiple:
var item = ItemsSource.GetItem(adapterPosition);
@@ -150,17 +149,8 @@ void UpdateMauiSelection(int adapterPosition)
{
selectedItems.Add(item);
}
- RefreshViewHolderSelection();
return;
}
-
- void RefreshViewHolderSelection()
- {
- for (int position = 0; position < _currentViewHolders.Count; position++)
- {
- _currentViewHolders[position].IsSelected = PositionIsSelected(position);
- }
- }
}
}
}
diff --git a/src/Controls/src/Core/Platform/Android/Extensions/RecyclerViewExtensions.cs b/src/Controls/src/Core/Platform/Android/Extensions/RecyclerViewExtensions.cs
index 5df82956ea61..37cac12c2d16 100644
--- a/src/Controls/src/Core/Platform/Android/Extensions/RecyclerViewExtensions.cs
+++ b/src/Controls/src/Core/Platform/Android/Extensions/RecyclerViewExtensions.cs
@@ -11,8 +11,8 @@ public static class RecyclerViewExtensions
public static void UpdateSelection(this RecyclerView recyclerView, SelectableItemsView selectableItemsView)
{
var mode = selectableItemsView.SelectionMode;
-
- var adapter = (recyclerView.GetAdapter() as SelectableItemsViewAdapter);
+ //TODO: on NET7 implement a ISelectableItemsViewAdapter interface on the adapter
+ var adapter = recyclerView.GetAdapter() as ReorderableItemsViewAdapter;
adapter?.ClearPlatformSelection();
switch (mode)
diff --git a/src/Controls/src/Core/PublicAPI/net6.0-android/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net6.0-android/PublicAPI.Unshipped.txt
index 125438c42bc0..42d678e050bb 100644
--- a/src/Controls/src/Core/PublicAPI/net6.0-android/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net6.0-android/PublicAPI.Unshipped.txt
@@ -1,4 +1,11 @@
#nullable enable
-override Microsoft.Maui.Controls.ContentView.OnApplyTemplate() -> void
+override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.ContentPresenter.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
override Microsoft.Maui.Controls.Grid.OnBindingContextChanged() -> void
+override Microsoft.Maui.Controls.TemplatedView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.TemplatedView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
~override Microsoft.Maui.Controls.Handlers.Compatibility.ViewCellRenderer.DisconnectHandler(Android.Views.View platformView) -> void
+*REMOVED*override Microsoft.Maui.Controls.ContentView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
diff --git a/src/Controls/src/Core/PublicAPI/net6.0-ios/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net6.0-ios/PublicAPI.Unshipped.txt
index c3e49b1dbc41..85d73a4f1460 100644
--- a/src/Controls/src/Core/PublicAPI/net6.0-ios/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net6.0-ios/PublicAPI.Unshipped.txt
@@ -1,4 +1,11 @@
#nullable enable
-override Microsoft.Maui.Controls.ContentView.OnApplyTemplate() -> void
+override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.ContentPresenter.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
override Microsoft.Maui.Controls.Grid.OnBindingContextChanged() -> void
override Microsoft.Maui.Controls.Handlers.Compatibility.FrameRenderer.SetNeedsLayout() -> void
+override Microsoft.Maui.Controls.TemplatedView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.TemplatedView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
diff --git a/src/Controls/src/Core/PublicAPI/net6.0-maccatalyst/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net6.0-maccatalyst/PublicAPI.Unshipped.txt
index c3e49b1dbc41..85d73a4f1460 100644
--- a/src/Controls/src/Core/PublicAPI/net6.0-maccatalyst/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net6.0-maccatalyst/PublicAPI.Unshipped.txt
@@ -1,4 +1,11 @@
#nullable enable
-override Microsoft.Maui.Controls.ContentView.OnApplyTemplate() -> void
+override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.ContentPresenter.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
override Microsoft.Maui.Controls.Grid.OnBindingContextChanged() -> void
override Microsoft.Maui.Controls.Handlers.Compatibility.FrameRenderer.SetNeedsLayout() -> void
+override Microsoft.Maui.Controls.TemplatedView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.TemplatedView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
diff --git a/src/Controls/src/Core/PublicAPI/net6.0-tizen/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net6.0-tizen/PublicAPI.Unshipped.txt
index 14dd0f16ac43..fba73e9ef223 100644
--- a/src/Controls/src/Core/PublicAPI/net6.0-tizen/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net6.0-tizen/PublicAPI.Unshipped.txt
@@ -1,3 +1,10 @@
#nullable enable
-override Microsoft.Maui.Controls.ContentView.OnApplyTemplate() -> void
+override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.ContentPresenter.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
override Microsoft.Maui.Controls.Grid.OnBindingContextChanged() -> void
+override Microsoft.Maui.Controls.TemplatedView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.TemplatedView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
diff --git a/src/Controls/src/Core/PublicAPI/net6.0-windows10.0.19041/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net6.0-windows10.0.19041/PublicAPI.Unshipped.txt
index 14dd0f16ac43..fba73e9ef223 100644
--- a/src/Controls/src/Core/PublicAPI/net6.0-windows10.0.19041/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net6.0-windows10.0.19041/PublicAPI.Unshipped.txt
@@ -1,3 +1,10 @@
#nullable enable
-override Microsoft.Maui.Controls.ContentView.OnApplyTemplate() -> void
+override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.ContentPresenter.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
override Microsoft.Maui.Controls.Grid.OnBindingContextChanged() -> void
+override Microsoft.Maui.Controls.TemplatedView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.TemplatedView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
diff --git a/src/Controls/src/Core/PublicAPI/net6.0-windows10.0.20348/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net6.0-windows10.0.20348/PublicAPI.Unshipped.txt
index 14dd0f16ac43..fba73e9ef223 100644
--- a/src/Controls/src/Core/PublicAPI/net6.0-windows10.0.20348/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net6.0-windows10.0.20348/PublicAPI.Unshipped.txt
@@ -1,3 +1,10 @@
#nullable enable
-override Microsoft.Maui.Controls.ContentView.OnApplyTemplate() -> void
+override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.ContentPresenter.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
override Microsoft.Maui.Controls.Grid.OnBindingContextChanged() -> void
+override Microsoft.Maui.Controls.TemplatedView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.TemplatedView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
diff --git a/src/Controls/src/Core/PublicAPI/net6.0/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net6.0/PublicAPI.Unshipped.txt
index 14dd0f16ac43..fba73e9ef223 100644
--- a/src/Controls/src/Core/PublicAPI/net6.0/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net6.0/PublicAPI.Unshipped.txt
@@ -1,3 +1,10 @@
#nullable enable
-override Microsoft.Maui.Controls.ContentView.OnApplyTemplate() -> void
+override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.ContentPresenter.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
override Microsoft.Maui.Controls.Grid.OnBindingContextChanged() -> void
+override Microsoft.Maui.Controls.TemplatedView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.TemplatedView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
diff --git a/src/Controls/src/Core/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
index 14dd0f16ac43..fba73e9ef223 100644
--- a/src/Controls/src/Core/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
@@ -1,3 +1,10 @@
#nullable enable
-override Microsoft.Maui.Controls.ContentView.OnApplyTemplate() -> void
+override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.ContentPresenter.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
override Microsoft.Maui.Controls.Grid.OnBindingContextChanged() -> void
+override Microsoft.Maui.Controls.TemplatedView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.TemplatedView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
diff --git a/src/Controls/src/Core/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt
index 14dd0f16ac43..fba73e9ef223 100644
--- a/src/Controls/src/Core/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt
@@ -1,3 +1,10 @@
#nullable enable
-override Microsoft.Maui.Controls.ContentView.OnApplyTemplate() -> void
+override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.ContentPresenter.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
override Microsoft.Maui.Controls.Grid.OnBindingContextChanged() -> void
+override Microsoft.Maui.Controls.TemplatedView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+override Microsoft.Maui.Controls.TemplatedView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.ContentView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
+*REMOVED*override Microsoft.Maui.Controls.RadioButton.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
diff --git a/src/Controls/src/Core/Shell/ShellContent.cs b/src/Controls/src/Core/Shell/ShellContent.cs
index 0a00b7c4bb45..c1f7ec624fca 100644
--- a/src/Controls/src/Core/Shell/ShellContent.cs
+++ b/src/Controls/src/Core/Shell/ShellContent.cs
@@ -209,6 +209,11 @@ Page ContentCache
public static implicit operator ShellContent(TemplatedPage page)
{
+ if (page.Parent != null)
+ {
+ return (ShellContent)page.Parent;
+ }
+
var shellContent = new ShellContent();
var pageRoute = Routing.GetRoute(page);
diff --git a/src/Controls/src/Core/TemplatedView.cs b/src/Controls/src/Core/TemplatedView.cs
index bfc6ef7a8dcb..18730a771201 100644
--- a/src/Controls/src/Core/TemplatedView.cs
+++ b/src/Controls/src/Core/TemplatedView.cs
@@ -87,8 +87,11 @@ void IControlTemplated.OnApplyTemplate()
protected virtual void OnApplyTemplate()
{
+ OnApplyTemplateImpl();
}
+ partial void OnApplyTemplateImpl();
+
protected override void OnChildRemoved(Element child, int oldLogicalIndex)
{
base.OnChildRemoved(child, oldLogicalIndex);
diff --git a/src/Controls/tests/Core.UnitTests/HostBuilderHandlerTests.cs b/src/Controls/tests/Core.UnitTests/HostBuilderHandlerTests.cs
index 4488b6458f67..138d82290630 100644
--- a/src/Controls/tests/Core.UnitTests/HostBuilderHandlerTests.cs
+++ b/src/Controls/tests/Core.UnitTests/HostBuilderHandlerTests.cs
@@ -1,4 +1,5 @@
-using Microsoft.Extensions.DependencyInjection;
+using System;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui.Controls.Hosting;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;
@@ -22,7 +23,7 @@ public void DefaultHandlersAreRegistered()
var handler = handlers.GetHandler(typeof(Button));
Assert.NotNull(handler);
- Assert.AreEqual(handler.GetType(), typeof(ButtonHandler));
+ Assert.AreEqual(typeof(ButtonHandler), handler.GetType());
}
[Test]
@@ -40,7 +41,33 @@ public void CanSpecifyHandler()
var specificHandler = handlers.GetHandler(typeof(Button));
Assert.NotNull(specificHandler);
- Assert.AreEqual(specificHandler.GetType(), typeof(ButtonHandlerStub));
+ Assert.AreEqual(typeof(ButtonHandlerStub), specificHandler.GetType());
+ }
+
+ [Test]
+ [TestCase(typeof(Label), typeof(LabelHandler))]
+ [TestCase(typeof(Button), typeof(ButtonHandler))]
+ [TestCase(typeof(ContentPage), typeof(PageHandler))]
+ [TestCase(typeof(Page), typeof(PageHandler))]
+ [TestCase(typeof(TemplatedView), typeof(ContentViewHandler))]
+ [TestCase(typeof(ContentView), typeof(ContentViewHandler))]
+ [TestCase(typeof(MyTestCustomTemplatedView), typeof(ContentViewHandler))]
+ public void VariousControlsGetCorrectHandler(Type viewType, Type handlerType)
+ {
+ var mauiApp = MauiApp.CreateBuilder()
+ .UseMauiApp()
+ .Build();
+
+ var handlers = mauiApp.Services.GetRequiredService();
+
+ var specificHandler = handlers.GetHandler(viewType);
+
+ Assert.NotNull(specificHandler);
+ Assert.AreEqual(handlerType, specificHandler.GetType());
+ }
+
+ class MyTestCustomTemplatedView : TemplatedView
+ {
}
}
}
diff --git a/src/Controls/tests/Core.UnitTests/ShellTests.cs b/src/Controls/tests/Core.UnitTests/ShellTests.cs
index 8721ac8e2b93..c559077148cd 100644
--- a/src/Controls/tests/Core.UnitTests/ShellTests.cs
+++ b/src/Controls/tests/Core.UnitTests/ShellTests.cs
@@ -71,6 +71,34 @@ public void SetCurrentItemWithImplicitlyWrappedShellContent(bool useShellContent
}
+ [Test]
+ public void SettingCurrentItemOnShellViaContentPage()
+ {
+ var page1 = new ContentPage();
+ var page2 = new ContentPage();
+ var shell = new TestShell()
+ {
+ Items =
+ {
+ new TabBar()
+ {
+ Items =
+ {
+ new ShellContent() { Content = page1 },
+ new ShellContent() { Content = page2 },
+ }
+ }
+ }
+ };
+
+ shell.CurrentItem = page2;
+ Assert.AreEqual(1, shell.Items.Count);
+ Assert.AreEqual(2, shell.Items[0].Items.Count);
+ Assert.AreEqual(1, shell.Items[0].Items[0].Items.Count);
+ Assert.AreEqual(1, shell.Items[0].Items[1].Items.Count);
+ Assert.AreEqual(shell.CurrentItem.CurrentItem, shell.Items[0].Items[1]);
+ }
+
[Test]
public void SetCurrentItemAddsToShellCollection()
{
diff --git a/src/Controls/tests/Core.UnitTests/TemplatedViewUnitTests.cs b/src/Controls/tests/Core.UnitTests/TemplatedViewUnitTests.cs
index 6cbca68537fd..b8740cc4afad 100644
--- a/src/Controls/tests/Core.UnitTests/TemplatedViewUnitTests.cs
+++ b/src/Controls/tests/Core.UnitTests/TemplatedViewUnitTests.cs
@@ -56,6 +56,28 @@ public void GetContentViewTemplateChildShouldWork()
Assert.AreEqual(internalChildren[0], contentView.TemplateChildObtained);
}
+ [Test]
+ public void GetTemplatedViewTemplateChildShouldWork()
+ {
+ var xaml =
+ @"
+
+
+
+
+
+ ";
+
+ var contentView = new MyTestTemplatedView();
+ contentView.LoadFromXaml(xaml);
+
+ IList internalChildren = contentView.InternalChildren;
+ Assert.AreEqual(internalChildren[0], contentView.TemplateChildObtained);
+ }
+
[Test]
public void GetContentPageTemplateChildShouldWork()
{
@@ -96,6 +118,27 @@ public void OnContentViewApplyTemplateShouldBeCalled()
Assert.IsTrue(contentView.WasOnApplyTemplateCalled);
}
+ [Test]
+ public void OnTemplatedViewApplyTemplateShouldBeCalled()
+ {
+ var xaml =
+ @"
+
+
+
+
+
+ ";
+
+ var contentView = new MyTestTemplatedView();
+ contentView.LoadFromXaml(xaml);
+
+ Assert.IsTrue(contentView.WasOnApplyTemplateCalled);
+ }
+
[Test]
public void OnContentPageApplyTemplateShouldBeCalled()
{
@@ -150,6 +193,19 @@ public void BindingsShouldBeAppliedOnTemplateChange()
}
}
+ class MyTestTemplatedView : TemplatedView
+ {
+ public bool WasOnApplyTemplateCalled { get; private set; }
+
+ public Element TemplateChildObtained { get; private set; }
+
+ protected override void OnApplyTemplate()
+ {
+ WasOnApplyTemplateCalled = true;
+ TemplateChildObtained = (Element)GetTemplateChild("label0");
+ }
+ }
+
class MyTestContentView : ContentView
{
public bool WasOnApplyTemplateCalled { get; private set; }
diff --git a/src/Controls/tests/DeviceTests/Elements/Compatibility/VisualElementRendererTests.cs b/src/Controls/tests/DeviceTests/Elements/Compatibility/VisualElementRendererTests.cs
new file mode 100644
index 000000000000..268b6a8286c3
--- /dev/null
+++ b/src/Controls/tests/DeviceTests/Elements/Compatibility/VisualElementRendererTests.cs
@@ -0,0 +1,56 @@
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Controls.Handlers.Compatibility;
+using Microsoft.Maui.Handlers;
+using Microsoft.Maui.Hosting;
+using Microsoft.Maui.Platform;
+using Xunit;
+
+namespace Microsoft.Maui.DeviceTests
+{
+ [Category(TestCategory.Compatibility)]
+ public partial class VisualElementRendererTests : HandlerTestBase
+ {
+ class LegacyComponent : View
+ {
+
+ }
+
+#if WINDOWS
+ class LegacyComponentRenderer : ViewRenderer
+#else
+ class LegacyComponentRenderer : VisualElementRenderer
+#endif
+ {
+#if ANDROID
+ public LegacyComponentRenderer(Android.Content.Context context) : base(context)
+ {
+
+ }
+#endif
+ }
+
+
+ void SetupBuilder()
+ {
+ EnsureHandlerCreated(builder =>
+ {
+ builder.ConfigureMauiHandlers(handlers =>
+ {
+ handlers.AddHandler();
+ });
+ });
+ }
+
+ [Fact]
+ public async Task CompatibilityRendererWorksWithNoInnerContrlSpecified()
+ {
+ SetupBuilder();
+ var renderer = await InvokeOnMainThreadAsync(() => new LegacyComponent().ToPlatform(MauiContext));
+
+ Assert.Equal(renderer, (renderer as IPlatformViewHandler).PlatformView);
+ Assert.NotNull(renderer);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/DeviceTests/Elements/Frame/FrameTests.cs b/src/Controls/tests/DeviceTests/Elements/Frame/FrameTests.cs
new file mode 100644
index 000000000000..18745506687c
--- /dev/null
+++ b/src/Controls/tests/DeviceTests/Elements/Frame/FrameTests.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Controls.Handlers.Compatibility;
+using Microsoft.Maui.Handlers;
+using Microsoft.Maui.Hosting;
+using Microsoft.Maui.Platform;
+using Xunit;
+
+namespace Microsoft.Maui.DeviceTests
+{
+ [Category(TestCategory.Frame)]
+ public partial class FrameTests : HandlerTestBase
+ {
+ void SetupBuilder()
+ {
+ EnsureHandlerCreated(builder =>
+ {
+ builder.ConfigureMauiHandlers(handlers =>
+ {
+ handlers.AddHandler();
+ handlers.AddHandler