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(); + }); + }); + } + + [Fact(DisplayName = "Basic Frame Test")] + public async Task BasicFrameTest() + { + SetupBuilder(); + + var frame = new Frame() + { + HeightRequest = 300, + WidthRequest = 300, + Content = new Label() + { + VerticalOptions = LayoutOptions.Center, + HorizontalOptions = LayoutOptions.Center, + Text = "Hello Frame" + } + }; + + var labelFrame = + await InvokeOnMainThreadAsync(() => + frame.ToHandler(MauiContext).PlatformView.AttachAndRun(async () => + { + (frame as IView).Measure(300, 300); + (frame as IView).Arrange(new Graphics.Rect(0, 0, 300, 300)); + + await OnFrameSetToNotEmpty(frame.Content); + + return frame.Content.Frame; + + }) + ); + + + // validate label is centered in the frame + Assert.True(Math.Abs(((300 - labelFrame.Width) / 2) - labelFrame.X) < 1); + Assert.True(Math.Abs(((300 - labelFrame.Height) / 2) - labelFrame.Y) < 1); + } + } +} \ No newline at end of file diff --git a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs index 65175022f5e7..07ef048e7045 100644 --- a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs @@ -190,6 +190,45 @@ await CreateHandlerAndAddToWindow(shell, async (handler) => }); } + + + [Fact(DisplayName = "Correctly Adjust to Making Currently Visible Shell Page Invisible")] + public async Task CorrectlyAdjustToMakingCurrentlyVisibleShellPageInvisible() + { + SetupBuilder(); + + var page1 = new ContentPage(); + var page2 = new ContentPage(); + + var shell = await CreateShellAsync((shell) => + { + var tabBar = new TabBar() + { + Items = + { + new ShellContent(){ Content = page1 }, + new ShellContent(){ Content = page2 }, + } + }; + + shell.Items.Add(tabBar); + }); + + await CreateHandlerAndAddToWindow(shell, async (handler) => + { + await OnNavigatedToAsync(page1); + shell.CurrentItem = page2; + await OnNavigatedToAsync(page2); + page2.IsVisible = false; + await OnNavigatedToAsync(page1); + Assert.Equal(shell.CurrentPage, page1); + page2.IsVisible = true; + shell.CurrentItem = page2; + await OnNavigatedToAsync(page2); + Assert.Equal(shell.CurrentPage, page2); + }); + } + [Fact(DisplayName = "Empty Shell")] public async Task DetailsViewUpdates() { diff --git a/src/Controls/tests/DeviceTests/Elements/TemplatedView/TemplatedViewTests.Android.cs b/src/Controls/tests/DeviceTests/Elements/TemplatedView/TemplatedViewTests.Android.cs new file mode 100644 index 000000000000..5271b304853b --- /dev/null +++ b/src/Controls/tests/DeviceTests/Elements/TemplatedView/TemplatedViewTests.Android.cs @@ -0,0 +1,15 @@ +using Android.Views; +using Microsoft.Maui.Handlers; +using Microsoft.Maui.Platform; + +namespace Microsoft.Maui.DeviceTests +{ + public partial class TemplatedViewTests + { + static int GetChildCount(ContentViewHandler contentViewHandler) => + contentViewHandler.PlatformView.ChildCount; + + static View GetChild(ContentViewHandler contentViewHandler, int index = 0) => + contentViewHandler.PlatformView.GetChildAt(index); + } +} diff --git a/src/Controls/tests/DeviceTests/Elements/TemplatedView/TemplatedViewTests.Windows.cs b/src/Controls/tests/DeviceTests/Elements/TemplatedView/TemplatedViewTests.Windows.cs new file mode 100644 index 000000000000..1b19ff2300ba --- /dev/null +++ b/src/Controls/tests/DeviceTests/Elements/TemplatedView/TemplatedViewTests.Windows.cs @@ -0,0 +1,15 @@ +using Microsoft.Maui.Handlers; +using Microsoft.Maui.Platform; +using Microsoft.UI.Xaml; + +namespace Microsoft.Maui.DeviceTests +{ + public partial class TemplatedViewTests + { + static int GetChildCount(ContentViewHandler contentViewHandler) => + contentViewHandler.PlatformView.Children.Count; + + static UIElement GetChild(ContentViewHandler contentViewHandler, int index = 0) => + contentViewHandler.PlatformView.Children[index]; + } +} diff --git a/src/Controls/tests/DeviceTests/Elements/TemplatedView/TemplatedViewTests.cs b/src/Controls/tests/DeviceTests/Elements/TemplatedView/TemplatedViewTests.cs new file mode 100644 index 000000000000..3a8b4437d85f --- /dev/null +++ b/src/Controls/tests/DeviceTests/Elements/TemplatedView/TemplatedViewTests.cs @@ -0,0 +1,68 @@ +using System.Threading.Tasks; +using Microsoft.Maui.Controls; +using Microsoft.Maui.Handlers; +using Microsoft.Maui.Hosting; +using Xunit; + +namespace Microsoft.Maui.DeviceTests +{ + [Category(TestCategory.TemplatedView)] + public partial class TemplatedViewTests : HandlerTestBase + { + public TemplatedViewTests() + { + EnsureHandlerCreated(builder => + { + builder.ConfigureMauiHandlers(handlers => + { + handlers.AddHandler(); + handlers.AddHandler(); + handlers.AddHandler(); + }); + }); + } + + [Fact] + public async Task ControlTemplateInitializesCorrectly() + { + var content = new Label { Text = "Content 1" }; + var templatedView = new TemplatedView + { + ControlTemplate = new ControlTemplate(() => content) + }; + + var handler = await CreateHandlerAsync(templatedView); + + await InvokeOnMainThreadAsync(() => + { + Assert.Equal(1, GetChildCount(handler)); + Assert.Equal(content.Handler.PlatformView, GetChild(handler)); + }); + } + + [Fact] + public async Task ControlTemplateCanBeReplacedCorrectly() + { + var content1 = new Label { Text = "Content 1" }; + var controlTemplate1 = new ControlTemplate(() => content1); + + var content2 = new Label { Text = "Content 2" }; + var controlTemplate2 = new ControlTemplate(() => content2); + + var templatedView = new TemplatedView { ControlTemplate = controlTemplate1 }; + + var handler = await CreateHandlerAsync(templatedView); + + await InvokeOnMainThreadAsync(() => + { + Assert.Equal(1, GetChildCount(handler)); + Assert.Equal(content1.Handler.PlatformView, GetChild(handler)); + + templatedView.ControlTemplate = controlTemplate2; + + Assert.Equal(1, GetChildCount(handler)); + Assert.Equal(content2.Handler.PlatformView, GetChild(handler)); + }); + } + } +} diff --git a/src/Controls/tests/DeviceTests/Elements/TemplatedView/TemplatedViewTests.iOS.cs b/src/Controls/tests/DeviceTests/Elements/TemplatedView/TemplatedViewTests.iOS.cs new file mode 100644 index 000000000000..60a607f7f92b --- /dev/null +++ b/src/Controls/tests/DeviceTests/Elements/TemplatedView/TemplatedViewTests.iOS.cs @@ -0,0 +1,14 @@ +using Microsoft.Maui.Handlers; +using UIKit; + +namespace Microsoft.Maui.DeviceTests +{ + public partial class TemplatedViewTests + { + static int GetChildCount(ContentViewHandler contentViewHandler) => + contentViewHandler.PlatformView.Subviews.Length; + + static UIView GetChild(ContentViewHandler contentViewHandler, int index = 0) => + contentViewHandler.PlatformView.Subviews[index]; + } +} diff --git a/src/Controls/tests/DeviceTests/HandlerTestBase.cs b/src/Controls/tests/DeviceTests/HandlerTestBase.cs index edd38eda25f2..b11b65aee26e 100644 --- a/src/Controls/tests/DeviceTests/HandlerTestBase.cs +++ b/src/Controls/tests/DeviceTests/HandlerTestBase.cs @@ -290,14 +290,19 @@ protected Task OnLoadedAsync(VisualElement frameworkElement, TimeSpan? timeOut = return taskCompletionSource.Task.WaitAsync(timeOut.Value); } - protected Task OnNavigatedToAsync(Page page, TimeSpan? timeOut = null) + protected async Task OnNavigatedToAsync(Page page, TimeSpan? timeOut = null) { + await OnLoadedAsync(page, timeOut); + + if (page.HasNavigatedTo) + return; + timeOut = timeOut ?? TimeSpan.FromSeconds(2); TaskCompletionSource taskCompletionSource = new TaskCompletionSource(); page.NavigatedTo += NavigatedTo; - return taskCompletionSource.Task.WaitAsync(timeOut.Value); + await taskCompletionSource.Task.WaitAsync(timeOut.Value); void NavigatedTo(object sender, NavigatedToEventArgs e) { taskCompletionSource.SetResult(true); @@ -305,7 +310,6 @@ void NavigatedTo(object sender, NavigatedToEventArgs e) } } - protected Task OnFrameSetToNotEmpty(VisualElement frameworkElement, TimeSpan? timeOut = null) { if (frameworkElement.Frame.Height > 0 && diff --git a/src/Controls/tests/DeviceTests/TestCategory.cs b/src/Controls/tests/DeviceTests/TestCategory.cs index 8616444e1a33..e382fd9daef2 100644 --- a/src/Controls/tests/DeviceTests/TestCategory.cs +++ b/src/Controls/tests/DeviceTests/TestCategory.cs @@ -4,11 +4,13 @@ public static class TestCategory { public const string Behavior = "Behavior"; public const string Button = "Button"; + public const string Compatibility = "Compatibility"; public const string ContentView = "ContentView"; public const string Dispatcher = "Dispatcher"; public const string Editor = "Editor"; public const string Element = "Element"; public const string Entry = "Entry"; + public const string Frame = "Frame"; public const string FlyoutPage = "FlyoutPage"; public const string Gesture = "Gesture"; public const string Label = "Label"; @@ -20,6 +22,7 @@ public static class TestCategory public const string SearchBar = "SearchBar"; public const string Shell = "Shell"; public const string TabbedPage = "TabbedPage"; + public const string TemplatedView = "TemplatedView"; public const string VisualElement = "VisualElement"; public const string Window = "Window"; } diff --git a/src/Core/src/Platform/Android/ViewExtensions.cs b/src/Core/src/Platform/Android/ViewExtensions.cs index 59cde5ced943..e3258ca8b22a 100644 --- a/src/Core/src/Platform/Android/ViewExtensions.cs +++ b/src/Core/src/Platform/Android/ViewExtensions.cs @@ -193,6 +193,10 @@ public static void UpdateBackground(this AView platformView, Paint? background) platformView.Background = drawable; } } + else if(platformView is LayoutViewGroup) + { + platformView.Background = null; + } } public static void UpdateOpacity(this AView platformView, IView view) diff --git a/src/Core/src/Platform/iOS/ViewExtensions.cs b/src/Core/src/Platform/iOS/ViewExtensions.cs index b127581b064a..53adda5ee399 100644 --- a/src/Core/src/Platform/iOS/ViewExtensions.cs +++ b/src/Core/src/Platform/iOS/ViewExtensions.cs @@ -76,7 +76,13 @@ public static void UpdateBackground(this UIView platformView, Paint? paint) platformView.RemoveBackgroundLayer(); if (paint.IsNullOrEmpty()) - return; + { + if (platformView is LayoutView) + platformView.BackgroundColor = null; + else + return; + } + if (paint is SolidPaint solidPaint) { diff --git a/src/Core/tests/DeviceTests/Handlers/Window/WindowHandlerTests.cs b/src/Core/tests/DeviceTests/Handlers/Window/WindowHandlerTests.cs index b976f295a878..d8c95de73561 100644 --- a/src/Core/tests/DeviceTests/Handlers/Window/WindowHandlerTests.cs +++ b/src/Core/tests/DeviceTests/Handlers/Window/WindowHandlerTests.cs @@ -7,6 +7,8 @@ namespace Microsoft.Maui.DeviceTests [Category(TestCategory.Window)] public partial class WindowHandlerTests : HandlerTestBase { + //TODO: Fix this test on Android, it fails a lot of times +#if !ANDROID [Fact] public async Task WindowHasReasonableDisplayDensity() { @@ -25,5 +27,6 @@ public async Task WindowHasReasonableDisplayDensity() Assert.Equal(density, req.Result); Assert.InRange(density, 0.1f, 4f); } +#endif } } \ No newline at end of file diff --git a/src/Templates/src/Microsoft.Maui.Templates.csproj b/src/Templates/src/Microsoft.Maui.Templates.csproj index 7ca5cc236f56..ce6f5980d365 100644 --- a/src/Templates/src/Microsoft.Maui.Templates.csproj +++ b/src/Templates/src/Microsoft.Maui.Templates.csproj @@ -31,7 +31,7 @@ $(_MauiDotNetTfm) Template - Microsoft.Maui.Templates + Microsoft.Maui.Templates-$(_MauiDotNetVersion) .NET MAUI Templates Microsoft Templates for .NET MAUI. @@ -71,8 +71,8 @@ + MatchExpression="WINDOWSAPPSDK_VERSION_VALUE;WIN2D_VERSION_VALUE;DOTNET_TFM_VALUE;DOTNET_TFM_VERSION_VALUE;DOTNET_TFM_VERSION_MAJOR_VALUE" + ReplacementText="$(MicrosoftWindowsAppSDKPackageVersion);$(MicrosoftGraphicsWin2DPackageVersion);$(_MauiDotNetTfm);$(_MauiDotNetVersion);$(_MauiDotNetVersionMajor)000" /> diff --git a/src/Templates/src/templates/maui-blazor/.template.config/ide.host.json b/src/Templates/src/templates/maui-blazor/.template.config/ide.host.json index 163ef456f98b..b033d675bf1d 100644 --- a/src/Templates/src/templates/maui-blazor/.template.config/ide.host.json +++ b/src/Templates/src/templates/maui-blazor/.template.config/ide.host.json @@ -1,5 +1,5 @@ { - "$schema": "http://json.schemastore.org/vs-2017.3.host", + "$schema": "http://json.schemastore.org/ide.host", "icon": "ide/icon.ico", "unsupportedHosts": [ { diff --git a/src/Templates/src/templates/maui-blazor/.template.config/template.in.json b/src/Templates/src/templates/maui-blazor/.template.config/template.in.json index b227a9db1d40..9a3e4f480ada 100644 --- a/src/Templates/src/templates/maui-blazor/.template.config/template.in.json +++ b/src/Templates/src/templates/maui-blazor/.template.config/template.in.json @@ -2,8 +2,9 @@ "$schema": "http://json.schemastore.org/template", "author": "Microsoft", "classifications": [ "MAUI", "Android", "iOS", "macOS", "Mac Catalyst", "Windows", "Tizen", "Blazor" ], - "identity": "Microsoft.Maui.BlazorApp", + "identity": "Microsoft.Maui.BlazorApp.CSharp.DOTNET_TFM_VERSION_VALUE", "groupIdentity": "Microsoft.Maui.BlazorApp", + "precedence": "DOTNET_TFM_VERSION_MAJOR_VALUE", "name": ".NET MAUI Blazor App", "description": "A project for creating a .NET MAUI application for iOS, Android, Mac Catalyst, WinUI, and Tizen using Blazor", "shortName": "maui-blazor", @@ -70,9 +71,16 @@ "replaces": "WIN2D_VERSION", "defaultValue": "WIN2D_VERSION_VALUE" }, - "DotNetTfm": { + "Framework": { "type": "parameter", - "dataType": "string", + "description": "The target framework for the project.", + "datatype": "choice", + "choices": [ + { + "choice": "DOTNET_TFM_VALUE", + "description": "Target DOTNET_TFM_VALUE" + } + ], "replaces": "DOTNET_TFM", "defaultValue": "DOTNET_TFM_VALUE" }, diff --git a/src/Templates/src/templates/maui-contentpage-csharp/.template.config/ide.host.json b/src/Templates/src/templates/maui-contentpage-csharp/.template.config/ide.host.json index 6fb095bb7590..5417de7c6308 100644 --- a/src/Templates/src/templates/maui-contentpage-csharp/.template.config/ide.host.json +++ b/src/Templates/src/templates/maui-contentpage-csharp/.template.config/ide.host.json @@ -1,5 +1,5 @@ { - "$schema": "http://json.schemastore.org/vs-2017.3.host", + "$schema": "http://json.schemastore.org/ide.host", "appliesTo": "UseMaui", "defaultItemExtension": "cs", "itemHierarchyPaths": [ ".NET MAUI" ], diff --git a/src/Templates/src/templates/maui-contentpage-csharp/.template.config/template.json b/src/Templates/src/templates/maui-contentpage-csharp/.template.config/template.json index 913d2dfe004f..523061d62d3b 100644 --- a/src/Templates/src/templates/maui-contentpage-csharp/.template.config/template.json +++ b/src/Templates/src/templates/maui-contentpage-csharp/.template.config/template.json @@ -2,7 +2,9 @@ "$schema": "http://json.schemastore.org/template", "author": "Microsoft", "classifications": [ "MAUI", "Android", "iOS", "macOS", "Mac Catalyst", "WinUI", "Tizen", "Xaml", "Code" ], - "identity": "Microsoft.Maui.CSharpContentPage", + "identity": "Microsoft.Maui.CSharpContentPage.DOTNET_TFM_VERSION_VALUE", + "groupIdentity": "Microsoft.Maui.CSharpContentPage", + "precedence": "DOTNET_TFM_VERSION_MAJOR_VALUE", "name": ".NET MAUI ContentPage (C#)", "shortName": "maui-page-csharp", "tags": { diff --git a/src/Templates/src/templates/maui-contentpage-xaml/.template.config/ide.host.json b/src/Templates/src/templates/maui-contentpage-xaml/.template.config/ide.host.json index d4fe14f7faf9..7794de5caf2a 100644 --- a/src/Templates/src/templates/maui-contentpage-xaml/.template.config/ide.host.json +++ b/src/Templates/src/templates/maui-contentpage-xaml/.template.config/ide.host.json @@ -1,5 +1,5 @@ { - "$schema": "http://json.schemastore.org/vs-2017.3.host", + "$schema": "http://json.schemastore.org/ide.host", "appliesTo": "UseMaui", "defaultItemExtension": "xaml", "itemHierarchyPaths": [ ".NET MAUI" ], diff --git a/src/Templates/src/templates/maui-contentpage-xaml/.template.config/template.json b/src/Templates/src/templates/maui-contentpage-xaml/.template.config/template.json index 52b3cc5d7b71..9ff72b84dc02 100644 --- a/src/Templates/src/templates/maui-contentpage-xaml/.template.config/template.json +++ b/src/Templates/src/templates/maui-contentpage-xaml/.template.config/template.json @@ -2,7 +2,9 @@ "$schema": "http://json.schemastore.org/template", "author": "Microsoft", "classifications": [ "MAUI", "Android", "iOS", "macOS", "Mac Catalyst", "WinUI", "Tizen", "Xaml", "Code" ], - "identity": "Microsoft.Maui.XamlContentPage", + "identity": "Microsoft.Maui.XamlContentPage.DOTNET_TFM_VERSION_VALUE", + "groupIdentity": "Microsoft.Maui.XamlContentPage", + "precedence": "DOTNET_TFM_VERSION_MAJOR_VALUE", "name": ".NET MAUI ContentPage (XAML)", "shortName": "maui-page-xaml", "tags": { diff --git a/src/Templates/src/templates/maui-contentview-csharp/.template.config/ide.host.json b/src/Templates/src/templates/maui-contentview-csharp/.template.config/ide.host.json index 9c2ebbe95f7e..66647fc9d264 100644 --- a/src/Templates/src/templates/maui-contentview-csharp/.template.config/ide.host.json +++ b/src/Templates/src/templates/maui-contentview-csharp/.template.config/ide.host.json @@ -1,5 +1,5 @@ { - "$schema": "http://json.schemastore.org/vs-2017.3.host", + "$schema": "http://json.schemastore.org/ide.host", "appliesTo": "UseMaui", "defaultItemExtension": "cs", "itemHierarchyPaths": [ ".NET MAUI" ], diff --git a/src/Templates/src/templates/maui-contentview-csharp/.template.config/template.json b/src/Templates/src/templates/maui-contentview-csharp/.template.config/template.json index 3c99416e9dfb..7839c907866b 100644 --- a/src/Templates/src/templates/maui-contentview-csharp/.template.config/template.json +++ b/src/Templates/src/templates/maui-contentview-csharp/.template.config/template.json @@ -2,7 +2,9 @@ "$schema": "http://json.schemastore.org/template", "author": "Microsoft", "classifications": [ "MAUI", "Android", "iOS", "macOS", "Mac Catalyst", "WinUI", "Tizen", "Xaml", "Code" ], - "identity": "Microsoft.Maui.CSharpContentView", + "identity": "Microsoft.Maui.CSharpContentView.DOTNET_TFM_VERSION_VALUE", + "groupIdentity": "Microsoft.Maui.CSharpContentView", + "precedence": "DOTNET_TFM_VERSION_MAJOR_VALUE", "name": ".NET MAUI ContentView (C#)", "shortName": "maui-view-csharp", "tags": { diff --git a/src/Templates/src/templates/maui-contentview-xaml/.template.config/ide.host.json b/src/Templates/src/templates/maui-contentview-xaml/.template.config/ide.host.json index e1af386a2392..414835ffbed6 100644 --- a/src/Templates/src/templates/maui-contentview-xaml/.template.config/ide.host.json +++ b/src/Templates/src/templates/maui-contentview-xaml/.template.config/ide.host.json @@ -1,5 +1,5 @@ { - "$schema": "http://json.schemastore.org/vs-2017.3.host", + "$schema": "http://json.schemastore.org/ide.host", "appliesTo": "UseMaui", "defaultItemExtension": "xaml", "itemHierarchyPaths": [ ".NET MAUI" ], diff --git a/src/Templates/src/templates/maui-contentview-xaml/.template.config/template.json b/src/Templates/src/templates/maui-contentview-xaml/.template.config/template.json index 2ed08942ce07..3f3b4823d3a9 100644 --- a/src/Templates/src/templates/maui-contentview-xaml/.template.config/template.json +++ b/src/Templates/src/templates/maui-contentview-xaml/.template.config/template.json @@ -2,7 +2,9 @@ "$schema": "http://json.schemastore.org/template", "author": "Microsoft", "classifications": [ "MAUI", "Android", "iOS", "macOS", "Mac Catalyst", "WinUI", "Tizen", "Xaml", "Code" ], - "identity": "Microsoft.Maui.XamlContentView", + "identity": "Microsoft.Maui.XamlContentView.DOTNET_TFM_VERSION_VALUE", + "groupIdentity": "Microsoft.Maui.XamlContentView", + "precedence": "DOTNET_TFM_VERSION_MAJOR_VALUE", "name": ".NET MAUI ContentView (XAML)", "shortName": "maui-view-xaml", "tags": { diff --git a/src/Templates/src/templates/maui-lib/.template.config/ide.host.json b/src/Templates/src/templates/maui-lib/.template.config/ide.host.json index e32df423f2ab..05c4fed4f8be 100644 --- a/src/Templates/src/templates/maui-lib/.template.config/ide.host.json +++ b/src/Templates/src/templates/maui-lib/.template.config/ide.host.json @@ -1,5 +1,5 @@ { - "$schema": "http://json.schemastore.org/vs-2017.3.host", + "$schema": "http://json.schemastore.org/ide.host", "icon": "ide/icon.ico", "unsupportedHosts": [ { diff --git a/src/Templates/src/templates/maui-lib/.template.config/template.in.json b/src/Templates/src/templates/maui-lib/.template.config/template.in.json index 1fda2e793199..7f0d8793c66b 100644 --- a/src/Templates/src/templates/maui-lib/.template.config/template.in.json +++ b/src/Templates/src/templates/maui-lib/.template.config/template.in.json @@ -2,8 +2,9 @@ "$schema": "http://json.schemastore.org/template", "author": "Microsoft", "classifications": [ "MAUI", "Android", "iOS", "macOS", "Mac Catalyst", "Windows", "Tizen" ], - "identity": "Microsoft.Maui.MauiLib", + "identity": "Microsoft.Maui.MauiLib.CSharp.DOTNET_TFM_VERSION_VALUE", "groupIdentity": "Microsoft.Maui.Library", + "precedence": "DOTNET_TFM_VERSION_MAJOR_VALUE", "name": ".NET MAUI Class Library", "description": "A project for creating a .NET MAUI class library", "shortName": "mauilib", @@ -34,9 +35,16 @@ ], "preferNameDirectory": true, "symbols": { - "DotNetTfm": { + "Framework": { "type": "parameter", - "dataType": "string", + "description": "The target framework for the project.", + "datatype": "choice", + "choices": [ + { + "choice": "DOTNET_TFM_VALUE", + "description": "Target DOTNET_TFM_VALUE" + } + ], "replaces": "DOTNET_TFM", "defaultValue": "DOTNET_TFM_VALUE" } diff --git a/src/Templates/src/templates/maui-mobile/.template.config/ide.host.json b/src/Templates/src/templates/maui-mobile/.template.config/ide.host.json index e32df423f2ab..05c4fed4f8be 100644 --- a/src/Templates/src/templates/maui-mobile/.template.config/ide.host.json +++ b/src/Templates/src/templates/maui-mobile/.template.config/ide.host.json @@ -1,5 +1,5 @@ { - "$schema": "http://json.schemastore.org/vs-2017.3.host", + "$schema": "http://json.schemastore.org/ide.host", "icon": "ide/icon.ico", "unsupportedHosts": [ { diff --git a/src/Templates/src/templates/maui-mobile/.template.config/template.in.json b/src/Templates/src/templates/maui-mobile/.template.config/template.in.json index 7cc615cb5312..1def57755895 100644 --- a/src/Templates/src/templates/maui-mobile/.template.config/template.in.json +++ b/src/Templates/src/templates/maui-mobile/.template.config/template.in.json @@ -2,8 +2,9 @@ "$schema": "http://json.schemastore.org/template", "author": "Microsoft", "classifications": [ "MAUI", "Android", "iOS", "macOS", "Mac Catalyst", "Windows", "Tizen" ], - "identity": "Microsoft.Maui.MauiApp", + "identity": "Microsoft.Maui.MauiApp.CSharp.DOTNET_TFM_VERSION_VALUE", "groupIdentity": "Microsoft.Maui.App", + "precedence": "DOTNET_TFM_VERSION_MAJOR_VALUE", "name": ".NET MAUI App", "description": "A project for creating a .NET MAUI application for iOS, Android, Mac Catalyst, WinUI and Tizen", "shortName": "maui", @@ -74,9 +75,16 @@ "replaces": "WIN2D_VERSION", "defaultValue": "WIN2D_VERSION_VALUE" }, - "DotNetTfm": { + "Framework": { "type": "parameter", - "dataType": "string", + "description": "The target framework for the project.", + "datatype": "choice", + "choices": [ + { + "choice": "DOTNET_TFM_VALUE", + "description": "Target DOTNET_TFM_VALUE" + } + ], "replaces": "DOTNET_TFM", "defaultValue": "DOTNET_TFM_VALUE" }, diff --git a/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/ide.host.json b/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/ide.host.json index 6a65123e7e2c..17c283fa2002 100644 --- a/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/ide.host.json +++ b/src/Templates/src/templates/maui-resourcedictionary-xaml/.template.config/ide.host.json @@ -1,5 +1,5 @@ { - "$schema": "http://json.schemastore.org/vs-2017.3.host", + "$schema": "http://json.schemastore.org/ide.host", "appliesTo": "UseMaui", "defaultItemExtension": "xaml", "itemHierarchyPaths": [ ".NET MAUI" ], diff --git a/src/Workload/Microsoft.NET.Sdk.Maui/Microsoft.NET.Sdk.Maui.csproj b/src/Workload/Microsoft.NET.Sdk.Maui/Microsoft.NET.Sdk.Maui.csproj index 82f0658110e5..d1ec39c73a47 100644 --- a/src/Workload/Microsoft.NET.Sdk.Maui/Microsoft.NET.Sdk.Maui.csproj +++ b/src/Workload/Microsoft.NET.Sdk.Maui/Microsoft.NET.Sdk.Maui.csproj @@ -38,6 +38,11 @@ <_VersionsToReplace Include="MicrosoftmacOSSdkPackageVersion" /> <_VersionsToReplace Include="MicrosofttvOSSdkPackageVersion" /> <_VersionsToReplace Include="MicrosoftNETWorkloadEmscriptenPackageVersion" /> + <_VersionsToReplace Include="DotNetMauiManifestVersionBand" /> + <_VersionsToReplace Include="DotNetMonoManifestVersionBand" /> + <_VersionsToReplace Include="DotNetEmscriptenManifestVersionBand" /> + <_VersionsToReplace Include="DotNetAndroidManifestVersionBand" /> + <_VersionsToReplace Include="DotNetMaciOSManifestVersionBand" /> <_VersionsToReplace Include="MicrosoftAspNetCoreAuthorizationPackageVersion" /> <_VersionsToReplace Include="MicrosoftAspNetCoreComponentsAnalyzersPackageVersion" /> <_VersionsToReplace Include="MicrosoftAspNetCoreComponentsFormsPackageVersion" /> @@ -69,6 +74,12 @@ OldValue="@MAUI_GRAPHICS_VERSION@" NewValue="$(MicrosoftMauiGraphicsVersion)" /> +