Bringing touch-effect up to date with main (#1383)

* Popup v6 windows (#1086)

Co-authored-by: Brandon Minnick <13558917+brminnick@users.noreply.github.com>
Co-authored-by: Pedro Jesus <pedrojesus.cefet@gmail.com>
Co-authored-by: Shaun Lawrence <shaunrlawrence@gmail.com>

* ♻️ [Housekeeping] Fixed  GravatarImageSourceTests.TestDefaultStream (#1335)

* [housekeeping] Automated PR to fix formatting errors (#1327)

* Fix popup margin on iOS (#1329)

* Bump NuGet.Protocol from 6.6.1 to 6.7.0 in /samples (#1330)

* Use fully qualified namespace for Color reference in TextToColorGenerator (#1332)

* Use fully qualified namespace for Color reference in TextToColorGenerator to prevent collisions

This change should prevent "ambiguous reference" error to occur when other packages are included in a MAUI project that provide their own Color objects

* added global prefix to be safer

---------

Co-authored-by: Pedro Jesus <pedrojesus.cefet@gmail.com>
Co-authored-by: Brandon Minnick <13558917+brminnick@users.noreply.github.com>

* Code cleanup and preparation for the next release (breaking changes) (#1324)

* Code cleanup and preparation for .net 8

* Update CompareConverter.shared.cs

* Revert global.json

* More CleanUps

* Remove redundant TrySetCanceled and rely on speech recognition result

* Update Formatting

---------

Co-authored-by: Brandon Minnick <13558917+brminnick@users.noreply.github.com>

* Fix Gestures on Popup on ios (#1342)

* Fix Gestures on Popup on ios

* don't query type cast directly

* Code for AddLogicalChild (.NET 8)

* reduce changes

* setting the parent fixes the BindingContext of the view

* Revert "setting the parent fixes the BindingContext of the view"

This reverts commit 0a64b56ca5.

* reduce changes

* simplify code

* fixing build

* assigned Element to contentPage.Parent

---------

Co-authored-by: pedrojesus <pedrojesus.cefet@gmail.com>

* `global.json`: Change `"rollForward": "latestMajor",` -> `"rollForward": "latestFeature"`. (#1338)

Update global.json

* Bump Microsoft.NET.Test.Sdk from 17.7.0 to 17.7.1 in /samples (#1348)

Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.7.0 to 17.7.1.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.7.0...v17.7.1)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* 632 bug avatar view clipping on windows (#1344)

* Resolves issue on Windows where the splash screen icon is not found.

* Resolves an issue with the 'Ratings' sample for AvatarView.

* Spaces and not tabs

* Spaces and not tabs

* Changed MauiImage to point to Images folder.

* Changed splash for Windows to be Resize=False

* Typo in name of MauiImage

* Try to prevent locking.

* Bump Microsoft.CodeAnalysis from 4.6.0 to 4.7.0 in /samples (#1355)

* Bump Microsoft.CodeAnalysis.CSharp.Workspaces from 4.6.0 to 4.7.0 in /samples (#1357)

* Bump FluentAssertions from 6.11.0 to 6.12.0 in /samples (#1365)

* fix  IconTintColorBehavior  for Windows (#1370)

fix  IconTintColorBehavior  for windows

Co-authored-by: Oleksii <sokol@managed-code.com>

* Add `MemoryAnalyzer` roslyn analyzer (#1371)

* Add NuGet Package + Update `WarningsAsErrors`

* Fix MA0002

* Fix `MauiDrawingView`

* Fix `MauiPopup`

* Fix Naming

* return `null` for nullable references

* Use Ternary Operator

* `dotnet format`

* iOS popup fix with Shell or TabbedPage (#1343)

* Fix Issue #1256


Better fix

* Fixed Popup on Multiple Level Pages (#822)

---------

Co-authored-by: Vladislav Antonyuk <33021114+VladislavAntonyuk@users.noreply.github.com>
Co-authored-by: Brandon Minnick <13558917+brminnick@users.noreply.github.com>

* [housekeeping] Automated PR to fix formatting errors (#1373)

* Bump Microsoft.NET.Test.Sdk from 17.7.1 to 17.7.2 in /samples (#1378)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Vladislav Antonyuk <33021114+VladislavAntonyuk@users.noreply.github.com>
Co-authored-by: Brandon Minnick <13558917+brminnick@users.noreply.github.com>
Co-authored-by: Pedro Jesus <pedrojesus.cefet@gmail.com>
Co-authored-by: Shaun Lawrence <shaunrlawrence@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: cat0363 <125236133+cat0363@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Wolf <132034537+wolfgang-ironsoftware@users.noreply.github.com>
Co-authored-by: Thomas Stocker <thomas.stocker@gmail.com>
Co-authored-by: George Leithead <github@internetwideworld.com>
Co-authored-by: Sokol2001 <53799292+Sokol2001@users.noreply.github.com>
Co-authored-by: Oleksii <sokol@managed-code.com>
Co-authored-by: Andrey Onishchenko <100789522+cucumber-sp@users.noreply.github.com>
This commit is contained in:
Kym Phillpotts 2023-09-04 21:09:36 +02:00 коммит произвёл GitHub
Родитель d69d0b3f2a
Коммит 8d9386744d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
60 изменённых файлов: 481 добавлений и 608 удалений

Просмотреть файл

@ -36,13 +36,16 @@ Please see our [Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
As should be clear by now: we assume everyone tries to do their best, everyone should be treated with respect and equally.
In the unfortunate event that doesn't happen, please feel free to report it to any of the team members or reach out to [Gerald](maillo:gerald.versluis@microsoft.com) directly.
In the unfortunate event that doesn't happen, please feel free to report it to any of the team members or reach out to [Gerald](mailto:gerald.versluis@microsoft.com) directly.
We will take appropriate actions and measures if necessary.
## Prerequisites
You will need to complete a Contribution License Agreement before any pull request can be accepted. Complete the CLA at https://cla.dotnetfoundation.org/. This will also be triggered whenever you open a PR and the link should guide you through it.
1. Install latest stable [.NET SDK](https://dotnet.microsoft.com/en-us/download)
1. Install .NET MAUI workloads (we recommend using Visual Studio installer)
> You will need to complete a Contribution License Agreement before any pull request can be accepted. Complete the CLA at https://cla.dotnetfoundation.org/. This will also be triggered whenever you open a PR and the link should guide you through it.
## Reporting a bug

Просмотреть файл

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Project>
<PropertyGroup>
<NetVersion>net7.0</NetVersion>
<!-- Fixes https://github.com/dotnet/maui/pull/12114 -->
<PublishReadyToRun>false</PublishReadyToRun>
<LangVersion>latest</LangVersion>
@ -26,8 +27,11 @@
CS1592: Badly formed XML in included comments file
CS1598: XML parser could not be loaded. The XML documentation file will not be generated.
CS1658: Identifier expected; 'true' is a keyword
CS1734: XML comment has a paramref tag, but there is no parameter by that name -->
<WarningsAsErrors>nullable,CS0419,CS1570,CS1571,CS1572,CS1573,CS1574,CS1580,CS1581,CS1584,CS1589,CS1590,CS1592,CS1598,CS1658,CS1734</WarningsAsErrors>
CS1734: XML comment has a paramref tag, but there is no parameter by that name
MA0001: Don't define public events in NSObject subclasses
MA0002: Don't declare members in NSObject subclasses unless they are WeakReference, WeakReference<T>, or Value types
MA0003: Don't subscribe to events inside NSObject subclasses unless it's your event (via this.MyEvent) or inherited from a base type, or the method is static -->
<WarningsAsErrors>nullable,CS0419,CS1570,CS1571,CS1572,CS1573,CS1574,CS1580,CS1581,CS1584,CS1589,CS1590,CS1592,CS1598,CS1658,CS1734,MA0001,MA0002,MA0003</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>

Просмотреть файл

@ -1,24 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<Project>
<ItemGroup Condition="$(TargetFramework.StartsWith('Xamarin.iOS')) != true AND $(TargetFramework.StartsWith('net7.0-ios')) != true">
<ItemGroup Condition="$(TargetFramework.StartsWith('Xamarin.iOS')) != true AND $(TargetFramework.StartsWith('$(NetVersion)-ios')) != true">
<Compile Remove="**\**\*.ios.cs" />
<None Include="**\**\*.ios.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
<Compile Remove="**\ios\**\*.cs" />
<None Include="**\ios\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('Xamarin.Mac')) != true AND $(TargetFramework.StartsWith('net7.0-maccatalyst')) != true">
<ItemGroup Condition="$(TargetFramework.StartsWith('Xamarin.Mac')) != true AND $(TargetFramework.StartsWith('$(NetVersion)-maccatalyst')) != true">
<Compile Remove="**\*.macos.cs" />
<None Include="**\*.macos.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
<Compile Remove="**\macos\**\*.cs" />
<None Include="**\macos\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('Xamarin.Mac')) != true AND $(TargetFramework.StartsWith('Xamarin.iOS')) != true AND $(TargetFramework.StartsWith('net7.0-ios')) != true AND $(TargetFramework.StartsWith('net7.0-maccatalyst')) != true">
<ItemGroup Condition="$(TargetFramework.StartsWith('Xamarin.Mac')) != true AND $(TargetFramework.StartsWith('Xamarin.iOS')) != true AND $(TargetFramework.StartsWith('$(NetVersion)-ios')) != true AND $(TargetFramework.StartsWith('$(NetVersion)-maccatalyst')) != true">
<Compile Remove="**\*.macios.cs" />
<None Include="**\*.macios.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
<Compile Remove="**\macios\**\*.cs" />
<None Include="**\macios\**\*.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('MonoAndroid')) != true AND $(TargetFramework.StartsWith('net7.0-android')) != true ">
<ItemGroup Condition="$(TargetFramework.StartsWith('MonoAndroid')) != true AND $(TargetFramework.StartsWith('$(NetVersion)-android')) != true ">
<Compile Remove="**\**\*.android.cs" />
<None Include="**\**\*.android.cs" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
<Compile Remove="**\android\**\*.cs" />

Просмотреть файл

@ -1,7 +1,7 @@
{
"sdk": {
"version": "7.0.200",
"rollForward": "latestMajor",
"rollForward": "latestFeature",
"allowPrerelease": false
}
}

Просмотреть файл

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0-ios;net7.0-android;net7.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);net7.0-tizen</TargetFrameworks>
<TargetFrameworks>$(NetVersion)-ios;$(NetVersion)-android;$(NetVersion)-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);$(NetVersion)-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);$(NetVersion)-tizen</TargetFrameworks>
<OutputType>Exe</OutputType>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
@ -42,6 +42,7 @@
<!-- Images -->
<MauiImage Include="Resources\Images\*" />
<MauiImage Update="Resources\Images\splash.svg" BaseSize="128,128" Color="#512BD4" Resize="false" />
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
@ -49,7 +50,7 @@
<EmbeddedResource Include="Resources\Embedded\*" />
<!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" />
<MauiFont Include="Resources\Fonts\*" />
<PackageReference Include="CommunityToolkit.Maui.Markup" Version="3.2.0" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
@ -83,4 +84,4 @@
<RuntimeIdentifiers>maccatalyst-arm64;maccatalyst-x64</RuntimeIdentifiers>
</PropertyGroup>
</Project>
</Project>

Просмотреть файл

@ -30,7 +30,7 @@
<Picker
Grid.Row="2"
ItemsSource="{Binding Locales}"
SelectedItem="{Binding Locale}"
SelectedItem="{Binding CurrentLocale}"
ItemDisplayBinding="{Binding ., Converter={StaticResource PickerLocaleDisplayConverter}}"
Margin="0,0,0,20">
</Picker>

Просмотреть файл

@ -53,8 +53,6 @@
</Setter>
<Setter Property="FontSize" Value="Default" />
<Setter Property="TextColor" Value="Silver" />
<Setter Property="WidthRequest" Value="48" />
<Setter Property="HeightRequest" Value="48" />
</Style>
</ResourceDictionary>
</VerticalStackLayout.Resources>
@ -66,7 +64,7 @@
Grid.Column="0"
HeightRequest="48"
SemanticProperties.Description="Sample AvatarView idea using a polyline stroke shape to override the corder radius to draw a star."
StrokeShape="Polyline 70,16 76,32 94,32 80,44 84,60 70,50 55,60 60,42 46,32 64,32"
StrokeShape="Polyline 24,0 29,16 48,18 34,30 38,48 24,37 10,48 14,30 0,18 19,16"
Style="{StaticResource Rating}"
Text="1"
WidthRequest="48" />
@ -74,7 +72,7 @@
Grid.Column="1"
HeightRequest="48"
SemanticProperties.Description="Sample AvatarView idea using a polyline stroke shape to override the corder radius to draw a star."
StrokeShape="Polyline 70,16 76,32 94,32 80,44 84,60 70,50 55,60 60,42 46,32 64,32"
StrokeShape="Polyline 24,0 29,16 48,18 34,30 38,48 24,37 10,48 14,30 0,18 19,16"
Style="{StaticResource Rating}"
Text="2"
WidthRequest="48" />
@ -82,7 +80,7 @@
Grid.Column="2"
HeightRequest="48"
SemanticProperties.Description="Sample AvatarView idea using a polyline stroke shape to override the corder radius to draw a star."
StrokeShape="Polyline 70,16 76,32 94,32 80,44 84,60 70,50 55,60 60,42 46,32 64,32"
StrokeShape="Polyline 24,0 29,16 48,18 34,30 38,48 24,37 10,48 14,30 0,18 19,16"
Style="{StaticResource Rating}"
Text="3"
WidthRequest="48" />
@ -90,7 +88,7 @@
Grid.Column="3"
HeightRequest="48"
SemanticProperties.Description="Sample AvatarView idea using a polyline stroke shape to override the corder radius to draw a star."
StrokeShape="Polyline 70,16 76,32 94,32 80,44 84,60 70,50 55,60 60,42 46,32 64,32"
StrokeShape="Polyline 24,0 29,16 48,18 34,30 38,48 24,37 10,48 14,30 0,18 19,16"
Style="{StaticResource Rating}"
Text="4"
WidthRequest="48" />
@ -98,7 +96,7 @@
Grid.Column="4"
HeightRequest="48"
SemanticProperties.Description="Sample AvatarView idea using a polyline stroke shape to override the corder radius to draw a star, cliped by parent size."
StrokeShape="Polyline 70,16 76,32 94,32 80,44 84,60 70,50 55,60 60,42 46,32 64,32"
StrokeShape="Polyline 24,0 29,16 48,18 34,30 38,48 24,37 10,48 14,30 0,18 19,16"
Style="{StaticResource Rating}"
Text="5"
WidthRequest="48">
@ -112,7 +110,7 @@
HeightRequest="48"
ImageSource="avatar_icon.png"
SemanticProperties.Description="Sample AvatarView idea using a polyline stroke shape to override the corder radius to draw a star."
StrokeShape="Polyline 70,16 76,32 94,32 80,44 84,60 70,50 55,60 60,42 46,32 64,32"
StrokeShape="Polyline 24,0 29,16 48,18 34,30 38,48 24,37 10,48 14,30 0,18 19,16"
Style="{StaticResource Rating}"
Text="1"
WidthRequest="48" />
@ -122,7 +120,7 @@
HeightRequest="48"
ImageSource="https://aka.ms/campus.jpg"
SemanticProperties.Description="Sample AvatarView idea using a polyline stroke shape to override the corder radius to draw a star."
StrokeShape="Polyline 70,16 76,32 94,32 80,44 84,60 70,50 55,60 60,42 46,32 64,32"
StrokeShape="Polyline 24,0 29,16 48,18 34,30 38,48 24,37 10,48 14,30 0,18 19,16"
Style="{StaticResource Rating}"
Text="2"
WidthRequest="48" />
@ -132,7 +130,7 @@
HeightRequest="48"
ImageSource="avatar_icon.png"
SemanticProperties.Description="Sample AvatarView idea using a polyline stroke shape to override the corder radius to draw a star, cliped by parent size."
StrokeShape="Polyline 70,16 76,32 94,32 80,44 84,60 70,50 55,60 60,42 46,32 64,32"
StrokeShape="Polyline 24,0 29,16 48,18 34,30 38,48 24,37 10,48 14,30 0,18 19,16"
Style="{StaticResource Rating}"
Text="3"
WidthRequest="48">

Просмотреть файл

@ -13,25 +13,21 @@
<ResourceDictionary>
<Style x:Key="Header"
TargetType="Label">
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="HorizontalOptions" Value="CenterAndExpand" />
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="Margin" Value="15, 10" />
</Style>
<Style TargetType="ScrollView">
<Setter Property="VerticalOptions" Value="FillAndExpand" />
</Style>
<Style x:Key="ItemsLayout"
TargetType="StackLayout">
<Setter Property="Spacing" Value="16" />
<Setter Property="VerticalOptions" Value="Fill" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ScrollView>
<Grid ColumnDefinitions="Auto, Auto, Auto"
HorizontalOptions="CenterAndExpand"
HorizontalOptions="Center"
RowDefinitions="Auto, Auto, Auto, Auto"
VerticalOptions="CenterAndExpand">
VerticalOptions="Center">
<Label Grid.Row="0"
Grid.ColumnSpan="3"

Просмотреть файл

@ -20,8 +20,7 @@ public partial class ShowPopupInOnAppearingPage : BasePage<ShowPopupInOnAppearin
protected override async void OnAppearing()
{
// Proves that we now support showing a popup before the platform is even ready.
var result = await this.ShowPopupAsync(new ReturnResultPopup(popupSizeConstants));
await this.ShowPopupAsync(new ReturnResultPopup(popupSizeConstants));
}
}

Просмотреть файл

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Просмотреть файл

@ -1,4 +1,5 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Maui.Dispatching;
@ -58,7 +59,7 @@ public sealed partial class ByteArrayToImageSourceConverterViewModel : BaseViewM
}
catch (Exception e)
{
Console.WriteLine(e);
Trace.WriteLine(e);
OnImageDownloadFailed(e.Message);
}
finally

Просмотреть файл

@ -18,7 +18,7 @@ public partial class SpeechToTextViewModel : BaseViewModel
readonly ISpeechToText speechToText;
[ObservableProperty]
Locale? locale;
Locale? currentLocale;
[ObservableProperty]
string? recognitionText = "Welcome to .NET MAUI Community Toolkit!";
@ -45,7 +45,7 @@ public partial class SpeechToTextViewModel : BaseViewModel
Locales.Add(locale);
}
Locale = Locales.FirstOrDefault(x => x.Language is defaultLanguage or defaultLanguage_android or defaultLanguage_tizen) ?? Locales.FirstOrDefault();
CurrentLocale = Locales.FirstOrDefault(x => x.Language is defaultLanguage or defaultLanguage_android or defaultLanguage_tizen) ?? Locales.FirstOrDefault();
}
[RelayCommand]
@ -53,7 +53,7 @@ public partial class SpeechToTextViewModel : BaseViewModel
{
await textToSpeech.SpeakAsync(RecognitionText ?? "Welcome to .NET MAUI Community Toolkit!", new()
{
Locale = Locale,
Locale = CurrentLocale,
Pitch = 2,
Volume = 1
}, cancellationToken);
@ -74,7 +74,7 @@ public partial class SpeechToTextViewModel : BaseViewModel
RecognitionText = beginSpeakingPrompt;
var recognitionResult = await speechToText.ListenAsync(
CultureInfo.GetCultureInfo(Locale?.Language ?? defaultLanguage),
CultureInfo.GetCultureInfo(CurrentLocale?.Language ?? defaultLanguage),
new Progress<string>(partialText =>
{
if (RecognitionText is beginSpeakingPrompt)
@ -102,6 +102,6 @@ public partial class SpeechToTextViewModel : BaseViewModel
void HandleLocalesCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(nameof(Locale));
OnPropertyChanged(nameof(CurrentLocale));
}
}

Просмотреть файл

@ -11,24 +11,10 @@ public sealed partial class PopupAnchorViewModel : BaseViewModel
[RelayCommand]
static void ShowPopup(View anchor)
{
// Using the C# version of Popup until this get fixed
// https://github.com/dotnet/maui/issues/4300
// This works
var popup = new TransparentPopupCSharp()
{
Anchor = anchor
};
// This doesn't work
//var popup = new TransparentPopup
//{
// Anchor = anchor
//};
Page.ShowPopup(popup);
}
}

Просмотреть файл

@ -4,5 +4,5 @@ public sealed partial class XamlBindingPopupViewModel : BaseViewModel
{
public string Title { get; } = "Xaml Binding Popup";
public string Message { get; } = "This is a platform specific popup with a .NET MAUI View being rendered. The behaviors of the popup will confirm to 100% as each platform implementation look and feel, but still allows you to use your .NET MAUI Controls.";
public string Message { get; } = "This is a platform specific popup with a .NET MAUI View being rendered.\nThe behaviors of the popup will confirm to 100% as each platform implementation look and feel, but still allows you to use your .NET MAUI Controls.";
}

Просмотреть файл

@ -31,9 +31,11 @@
<Label x:Name="Title"
Style="{StaticResource Title}" />
Style="{StaticResource Title}"
Text="This Title Is About To Change"/>
<BoxView Style="{StaticResource Divider}" />
<Label x:Name="Message"
Text="This sample changes the title and message in Popup's OnAppearing method"
Style="{StaticResource Content}" />
</VerticalStackLayout>
</mct:Popup>

Просмотреть файл

@ -14,10 +14,12 @@ public partial class OpenedEventSimplePopup : Popup
Opened += OnOpened;
}
void OnOpened(object? sender, PopupOpenedEventArgs e)
async void OnOpened(object? sender, PopupOpenedEventArgs e)
{
Opened -= OnOpened;
await Task.Delay(TimeSpan.FromSeconds(1));
Title.Text = "Opened Event Popup";
Message.Text = "The content of this popup was updated after the popup was rendered";
}

Просмотреть файл

@ -2,7 +2,7 @@
namespace CommunityToolkit.Maui.Sample.Views.Popups;
public class TransparentPopupCSharp : Popup
public sealed class TransparentPopupCSharp : Popup
{
public TransparentPopupCSharp(Size popupSize) : this()
{

Просмотреть файл

@ -10,7 +10,9 @@
<vm:XamlBindingPopupViewModel />
</mct:Popup.BindingContext>
<VerticalStackLayout Style="{StaticResource PopupLayout}">
<VerticalStackLayout
Style="{StaticResource PopupLayout}"
HorizontalOptions="Center">
<VerticalStackLayout.Resources>
<ResourceDictionary>
<Style x:Key="Title" TargetType="Label">
@ -39,6 +41,9 @@
Text="{Binding Title}" />
<BoxView Style="{StaticResource Divider}" />
<Label Style="{StaticResource Content}"
HorizontalTextAlignment="Center"
MaxLines="5"
LineBreakMode="WordWrap"
Text="{Binding Message}" />
</VerticalStackLayout>
</mct:Popup>

Просмотреть файл

@ -8,7 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.6.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.7.0" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>$(NetVersion)</TargetFramework>
<IsPackable>false</IsPackable>
<UseMaui>true</UseMaui>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
@ -11,16 +11,16 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.11.0" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.XUnit" Version="1.1.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing.XUnit" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
<PackageReference Include="xunit" Version="2.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0" PrivateAssets="All" />
<PackageReference Include="coverlet.collector" Version="6.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.7.0" />
</ItemGroup>
<ItemGroup>
@ -28,7 +28,7 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageReference Include="NuGet.Protocol" Version="6.6.1" />
<PackageReference Include="NuGet.Protocol" Version="6.7.0" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0;net7.0-android;net7.0-ios;net7.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);net7.0-tizen</TargetFrameworks>
<TargetFrameworks>$(NetVersion);$(NetVersion)-android;$(NetVersion)-ios;$(NetVersion)-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);$(NetVersion)-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);$(NetVersion)-tizen</TargetFrameworks>
<UseMauiCore>true</UseMauiCore>
<UseMauiEssentials>true</UseMauiEssentials>
<SingleProject>true</SingleProject>
@ -24,7 +24,7 @@
<Authors>Microsoft</Authors>
<Owners>Microsoft</Owners>
<NeutralLanguage>en</NeutralLanguage>
<Product>CommunityToolkit.Maui (net7.0)</Product>
<Product>CommunityToolkit.Maui ($(NetVersion))</Product>
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/CommunityToolkit/Maui</PackageProjectUrl>
@ -56,7 +56,12 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Speech" Version="7.0.0" Condition="'$(TargetFramework)' == 'net7.0-windows10.0.19041.0'" />
<PackageReference Include="MemoryAnalyzers" Version="0.1.0-beta.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Speech" Version="7.0.0" Condition="'$(TargetFramework)' == '$(NetVersion)-windows10.0.19041.0'" />
</ItemGroup>
</Project>

Просмотреть файл

@ -25,7 +25,7 @@ public sealed partial class FileSaverImplementation : IFileSaver, IDisposable
var isDirectoryCreated = fileManager.CreateDirectory(tempDirectoryPath, true, null, out var error);
if (!isDirectoryCreated)
{
throw new Exception(error?.LocalizedDescription ?? "Unable to create temp directory.");
throw new FileSaveException(error?.LocalizedDescription ?? "Unable to create temp directory.");
}
var fileUrl = tempDirectoryPath.Append(fileName, false);

Просмотреть файл

@ -86,7 +86,6 @@ public sealed partial class SpeechToTextImplementation
await using (cancellationToken.Register(async () =>
{
await StopRecording();
speechRecognitionTaskCompletionSource.SetCanceled();
}))
{
return await speechRecognitionTaskCompletionSource.Task;
@ -119,7 +118,10 @@ public sealed partial class SpeechToTextImplementation
{
try
{
await speechRecognizer?.ContinuousRecognitionSession.StopAsync();
if (speechRecognizer is not null)
{
await speechRecognizer.ContinuousRecognitionSession.StopAsync();
}
}
catch
{

Просмотреть файл

@ -1,9 +1,12 @@
using CommunityToolkit.Maui.Core.Views;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
namespace CommunityToolkit.Maui.Core.Handlers;
public partial class PopupHandler : ElementHandler<IPopup, MauiPopup>
public partial class PopupHandler : ElementHandler<IPopup, Popup>
{
/// <summary>
/// Action that's triggered when the Popup is Dismissed.
@ -25,7 +28,14 @@ public partial class PopupHandler : ElementHandler<IPopup, MauiPopup>
/// <param name="result">We don't need to provide the result parameter here.</param>
public static void MapOnOpened(PopupHandler handler, IPopup view, object? result)
{
handler.PlatformView.Show();
ArgumentNullException.ThrowIfNull(view.Parent);
ArgumentNullException.ThrowIfNull(handler.MauiContext);
var parent = view.Parent.ToPlatform(handler.MauiContext);
parent.IsHitTestVisible = false;
handler.PlatformView.XamlRoot = parent.XamlRoot;
handler.PlatformView.IsHitTestVisible = true;
handler.PlatformView.IsOpen = true;
view.OnOpened();
}
/// <summary>
@ -47,7 +57,7 @@ public partial class PopupHandler : ElementHandler<IPopup, MauiPopup>
/// <param name="view">An instance of <see cref="IPopup"/>.</param>
public static void MapAnchor(PopupHandler handler, IPopup view)
{
handler.PlatformView.ConfigureControl();
handler.PlatformView.SetAnchor(view, handler.MauiContext);
}
/// <summary>
@ -57,7 +67,8 @@ public partial class PopupHandler : ElementHandler<IPopup, MauiPopup>
/// <param name="view">An instance of <see cref="IPopup"/>.</param>
public static void MapCanBeDismissedByTappingOutsideOfPopup(PopupHandler handler, IPopup view)
{
handler.PlatformView.ConfigureControl();
handler.PlatformView.IsLightDismissEnabled = view.CanBeDismissedByTappingOutsideOfPopup;
handler.PlatformView.LightDismissOverlayMode = view.CanBeDismissedByTappingOutsideOfPopup ? LightDismissOverlayMode.On : LightDismissOverlayMode.Off;
}
/// <summary>
@ -68,7 +79,6 @@ public partial class PopupHandler : ElementHandler<IPopup, MauiPopup>
public static void MapColor(PopupHandler handler, IPopup view)
{
handler.PlatformView.SetColor(view);
handler.PlatformView.ConfigureControl();
}
/// <summary>
@ -78,26 +88,40 @@ public partial class PopupHandler : ElementHandler<IPopup, MauiPopup>
/// <param name="view">An instance of <see cref="IPopup"/>.</param>
public static void MapSize(PopupHandler handler, IPopup view)
{
handler.PlatformView.ConfigureControl();
handler.PlatformView.SetSize(view);
}
/// <inheritdoc/>
protected override void DisconnectHandler(MauiPopup platformView)
protected override void DisconnectHandler(Popup platformView)
{
platformView.CleanUp();
ArgumentNullException.ThrowIfNull(VirtualView.Parent);
ArgumentNullException.ThrowIfNull(VirtualView.Handler?.MauiContext);
var parent = VirtualView.Parent.ToPlatform(VirtualView.Handler.MauiContext);
parent.IsHitTestVisible = true;
platformView.IsOpen = false;
platformView.Closed -= OnClosed;
}
/// <inheritdoc/>
protected override MauiPopup CreatePlatformElement()
protected override Popup CreatePlatformElement()
{
ArgumentNullException.ThrowIfNull(MauiContext);
return new MauiPopup(MauiContext);
var popup = new Popup();
return popup;
}
/// <inheritdoc/>
protected override void ConnectHandler(MauiPopup platformView)
protected override void ConnectHandler(Popup platformView)
{
platformView.SetElement(VirtualView);
platformView.Closed += OnClosed;
platformView.ConfigureControl(VirtualView, MauiContext);
base.ConnectHandler(platformView);
}
void OnClosed(object? sender, object e)
{
if (!PlatformView.IsOpen && VirtualView.CanBeDismissedByTappingOutsideOfPopup)
{
VirtualView.Handler?.Invoke(nameof(IPopup.OnDismissedByTappingOutsideOfPopup));
}
}
}

Просмотреть файл

@ -2,7 +2,7 @@ namespace CommunityToolkit.Maui.Core.Platform;
static partial class StatusBar
{
static void PlatformSetColor(Color color) => throw new NotSupportedException($"{nameof(PlatformSetColor)} is only supported on net6.0-ios and net6.0-android and later");
static void PlatformSetColor(Color color) => throw new NotSupportedException($"{nameof(PlatformSetColor)} is only supported on iOS and Android 23 and later");
static void PlatformSetStyle(StatusBarStyle statusBarStyle) => throw new NotSupportedException($"{nameof(PlatformSetStyle)} is only supported on net6.0-ios and net6.0-android and later");
static void PlatformSetStyle(StatusBarStyle statusBarStyle) => throw new NotSupportedException($"{nameof(PlatformSetStyle)} is only supported on iOS and Android 23 and later");
}

Просмотреть файл

@ -9,6 +9,8 @@ namespace CommunityToolkit.Maui.Core.Views;
public class AlertView : UIView
{
readonly List<UIView> children = Enumerable.Empty<UIView>().ToList();
readonly WeakReference<UIView?> anchorViewReference = new(null);
readonly WeakReference<UIStackView?> containerReference = new(null);
/// <summary>
/// Parent UIView
@ -20,20 +22,28 @@ public class AlertView : UIView
/// </summary>
public IReadOnlyList<UIView> Children => children;
/// <summary>
/// <see cref="UIView"/> on which Alert will appear. When null, <see cref="AlertView"/> will appear at bottom of screen.
/// </summary>
public UIView? AnchorView { get; set; }
/// <summary>
/// <see cref="AlertViewVisualOptions"/>
/// </summary>
public AlertViewVisualOptions VisualOptions { get; } = new();
/// <summary>
/// <see cref="UIView"/> on which Alert will appear. When null, <see cref="AlertView"/> will appear at bottom of screen.
/// </summary>
public UIView? AnchorView
{
get => anchorViewReference.TryGetTarget(out var anchorView) ? anchorView : null;
set => anchorViewReference.SetTarget(value);
}
/// <summary>
/// Container of <see cref="AlertView"/>
/// </summary>
protected UIStackView? Container { get; set; }
protected UIStackView? Container
{
get => containerReference.TryGetTarget(out var container) ? container : null;
set => containerReference.SetTarget(value);
}
/// <summary>
/// Dismisses the Popup from the screen

Просмотреть файл

@ -1,10 +1,8 @@
using System.Collections.ObjectModel;
using Android.Content;
using Android.Views;
using CommunityToolkit.Maui.Core.Extensions;
using Microsoft.Maui.Platform;
using AColor = Android.Graphics.Color;
using APaint = Android.Graphics.Paint;
using APath = Android.Graphics.Path;
using AView = Android.Views.View;
namespace CommunityToolkit.Maui.Core.Views;
@ -24,6 +22,7 @@ public partial class MauiDrawingView : PlatformTouchGraphicsView
if (disposing)
{
currentPath.Dispose();
proxy?.Dispose();
}
base.Dispose(disposing);
@ -78,11 +77,24 @@ public partial class MauiDrawingView : PlatformTouchGraphicsView
public void Initialize()
{
Drawable = new DrawingViewDrawable(this);
Lines.CollectionChanged += OnLinesCollectionChanged;
proxy = new(this);
}
void Redraw()
{
Invalidate();
}
static ObservableCollection<PointF> CreateCollectionWithNormalizedPoints(in ObservableCollection<PointF> points, in int drawingViewWidth, in int drawingViewHeight, in float canvasScale)
{
var newPoints = new List<PointF>();
foreach (var point in points)
{
var pointX = Math.Clamp(point.X, 0, drawingViewWidth / canvasScale);
var pointY = Math.Clamp(point.Y, 0, drawingViewHeight / canvasScale);
newPoints.Add(new PointF(pointX, pointY));
}
return newPoints.ToObservableCollection();
}
}

Просмотреть файл

@ -49,7 +49,7 @@ public partial class MauiDrawingView : PlatformTouchGraphicsView
public void Initialize()
{
Drawable = new DrawingViewDrawable(this);
Lines.CollectionChanged += OnLinesCollectionChanged;
proxy = new(this);
}
/// <inheritdoc/>
@ -58,6 +58,7 @@ public partial class MauiDrawingView : PlatformTouchGraphicsView
if (disposing)
{
currentPath.Dispose();
proxy?.Dispose();
}
base.Dispose(disposing);

Просмотреть файл

@ -9,11 +9,13 @@ namespace CommunityToolkit.Maui.Core.Views;
public partial class MauiDrawingView
{
readonly WeakEventManager weakEventManager = new();
readonly WeakReference<Action<ICanvas, RectF>?> drawActionReference = new(null);
bool isDrawing;
PointF previousPoint;
PathF currentPath = new();
MauiDrawingLine? currentLine;
MauiDrawingViewProxy? proxy;
Paint paint = new SolidPaint(DrawingViewDefaults.BackgroundColor);
/// <summary>
@ -53,7 +55,11 @@ public partial class MauiDrawingView
/// <summary>
/// Used to draw any shape on the canvas
/// </summary>
public Action<ICanvas, RectF>? DrawAction { get; set; }
public Action<ICanvas, RectF>? DrawAction
{
get => drawActionReference.TryGetTarget(out var drawAction) ? drawAction : null;
set => drawActionReference.SetTarget(value);
}
/// <summary>
/// Drawable background
@ -103,7 +109,7 @@ public partial class MauiDrawingView
Redraw();
Lines.CollectionChanged += OnLinesCollectionChanged;
proxy?.SubscribeCollectionChanged();
}
void OnMoving(PointF currentPoint)
@ -165,7 +171,7 @@ public partial class MauiDrawingView
currentPath = new PathF();
}
class DrawingViewDrawable : IDrawable
sealed class DrawingViewDrawable : IDrawable
{
readonly MauiDrawingView drawingView;
@ -192,8 +198,8 @@ public partial class MauiDrawingView
canvas.StrokeColor = lineColor;
canvas.StrokeSize = lineWidth;
canvas.StrokeDashOffset = 0;
canvas.StrokeLineCap = LineCap.Butt;
canvas.StrokeLineJoin = LineJoin.Miter;
canvas.StrokeLineCap = LineCap.Round;
canvas.StrokeLineJoin = LineJoin.Round;
canvas.StrokeDashPattern = Array.Empty<float>();
}
@ -221,20 +227,32 @@ public partial class MauiDrawingView
}
}
}
}
#if ANDROID
static ObservableCollection<PointF> CreateCollectionWithNormalizedPoints(in ObservableCollection<PointF> points, in int drawingViewWidth, in int drawingViewHeight, in float canvasScale)
// Proxy class required to avoid memory leaks on iOS, resolving MA0003
// Inspired by SearchbarHandler.MauiSearchBarProxy https://github.com/dotnet/maui/blob/911ea757e996d1213711f786f81e05461df6fc2f/src/Core/src/Handlers/SearchBar/SearchBarHandler.iOS.cs#L155-L251
sealed partial class MauiDrawingViewProxy : IDisposable
{
readonly WeakReference<MauiDrawingView> platformView;
public MauiDrawingViewProxy(MauiDrawingView view)
{
var newPoints = new List<PointF>();
foreach (var point in points)
{
var pointX = Math.Clamp(point.X, 0, drawingViewWidth / canvasScale);
var pointY = Math.Clamp(point.Y, 0, drawingViewHeight / canvasScale);
newPoints.Add(new PointF(pointX, pointY));
}
return newPoints.ToObservableCollection();
platformView = new(view);
SubscribeCollectionChanged();
}
MauiDrawingView PlatformView => platformView.TryGetTarget(out var drawingView)
? drawingView
: throw new ObjectDisposedException(nameof(PlatformView));
public void Dispose()
{
PlatformView.Lines.CollectionChanged -= PlatformView.OnLinesCollectionChanged;
}
public void SubscribeCollectionChanged()
{
PlatformView.Lines.CollectionChanged += PlatformView.OnLinesCollectionChanged;
}
#endif
}
}

Просмотреть файл

@ -20,7 +20,7 @@ public partial class MauiDrawingView : PlatformTouchGraphicsView
public void Initialize()
{
Drawable = new DrawingViewDrawable(this);
Lines.CollectionChanged += OnLinesCollectionChanged;
proxy = new(this);
}
/// <inheritdoc />
@ -29,6 +29,7 @@ public partial class MauiDrawingView : PlatformTouchGraphicsView
if (disposing)
{
currentPath.Dispose();
proxy?.Dispose();
TouchEvent -= OnTouch;
}

Просмотреть файл

@ -30,7 +30,7 @@ public partial class MauiDrawingView : PlatformTouchGraphicsView, IDisposable
System.Diagnostics.Trace.WriteLine("DrawingView requires Windows 10.0.18362 or higher.");
}
Lines.CollectionChanged += OnLinesCollectionChanged;
proxy = new(this);
}
/// <inheritdoc />
@ -49,6 +49,7 @@ public partial class MauiDrawingView : PlatformTouchGraphicsView, IDisposable
if (disposing)
{
currentPath.Dispose();
proxy?.Dispose();
}
isDisposed = true;

Просмотреть файл

@ -10,6 +10,7 @@ namespace CommunityToolkit.Maui.Core.Views;
public class MauiPopup : UIViewController
{
readonly IMauiContext mauiContext;
readonly WeakReference<UIViewController?> viewControllerReference = new(null);
/// <summary>
/// Constructor of <see cref="MauiPopup"/>.
@ -31,7 +32,11 @@ public class MauiPopup : UIViewController
/// </summary>
public IPopup? VirtualView { get; private set; }
internal UIViewController? ViewController { get; private set; }
internal UIViewController? ViewController
{
get => viewControllerReference.TryGetTarget(out var viewController) ? viewController : null;
set => viewControllerReference.SetTarget(value);
}
/// <summary>
/// Method to update the Popup's size.
@ -163,8 +168,7 @@ public class MauiPopup : UIViewController
void SetPresentationController()
{
var popOverDelegate = new PopoverDelegate();
popOverDelegate.PopoverDismissedEvent += HandlePopoverDelegateDismissed;
var popOverDelegate = new PopoverDelegate(this);
UIPopoverPresentationController presentationController = (UIPopoverPresentationController)(PresentationController ?? throw new InvalidOperationException($"{nameof(PresentationController)} cannot be null."));
presentationController.SourceView = ViewController?.View ?? throw new InvalidOperationException($"{nameof(ViewController.View)} cannot be null.");
@ -172,13 +176,6 @@ public class MauiPopup : UIViewController
presentationController.Delegate = popOverDelegate;
}
[MemberNotNull(nameof(VirtualView))]
void HandlePopoverDelegateDismissed(object? sender, UIPresentationController e)
{
_ = VirtualView ?? throw new InvalidOperationException($"{nameof(VirtualView)} cannot be null.");
VirtualView.Handler?.Invoke(nameof(IPopup.OnDismissedByTappingOutsideOfPopup));
}
void AddToCurrentPageViewController(UIViewController viewController)
{
viewController.PresentViewController(this, true, null);
@ -187,6 +184,13 @@ public class MauiPopup : UIViewController
sealed class PopoverDelegate : UIPopoverPresentationControllerDelegate
{
readonly WeakEventManager popoverDismissedEventmanager = new();
readonly WeakReference<MauiPopup> mauiPopup;
public PopoverDelegate(MauiPopup mauiPopup)
{
this.mauiPopup = new(mauiPopup);
PopoverDismissedEvent += HandlePopoverDelegateDismissed;
}
public event EventHandler<UIPresentationController> PopoverDismissedEvent
{
@ -194,10 +198,19 @@ public class MauiPopup : UIViewController
remove => popoverDismissedEventmanager.RemoveEventHandler(value);
}
MauiPopup MauiPopup => mauiPopup.TryGetTarget(out var virtualView)
? virtualView
: throw new ObjectDisposedException(nameof(MauiPopup));
public override UIModalPresentationStyle GetAdaptivePresentationStyle(UIPresentationController forPresentationController) =>
UIModalPresentationStyle.None;
public override void DidDismiss(UIPresentationController presentationController) =>
popoverDismissedEventmanager.HandleEvent(this, presentationController, nameof(PopoverDismissedEvent));
void HandlePopoverDelegateDismissed(object? sender, UIPresentationController e)
{
MauiPopup.VirtualView?.Handler?.Invoke(nameof(IPopup.OnDismissedByTappingOutsideOfPopup));
}
}
}

Просмотреть файл

@ -1,288 +0,0 @@
using CommunityToolkit.Maui.Core.Handlers;
using Microsoft.Maui.Platform;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using LayoutAlignment = Microsoft.Maui.Primitives.LayoutAlignment;
using WindowsThickness = Microsoft.UI.Xaml.Thickness;
using XamlStyle = Microsoft.UI.Xaml.Style;
namespace CommunityToolkit.Maui.Core.Views;
/// <summary>
/// The native implementation of Popup control.
/// </summary>
public class MauiPopup : Flyout
{
const double defaultBorderThickness = 0;
const double defaultSize = 600;
readonly IMauiContext mauiContext;
/// <summary>
/// Constructor of <see cref="MauiPopup"/>.
/// </summary>
/// <param name="mauiContext">An instance of <see cref="IMauiContext"/>.</param>
/// <exception cref="ArgumentNullException">If <paramref name="mauiContext"/> is null an exception will be thrown. </exception>
public MauiPopup(IMauiContext mauiContext)
{
this.mauiContext = mauiContext ?? throw new ArgumentNullException(nameof(mauiContext));
}
/// <summary>
/// An instance of the <see cref="IPopup"/>.
/// </summary>
public IPopup? VirtualView { get; private set; }
internal Panel? Control { get; set; }
internal XamlStyle FlyoutStyle { get; private set; } = new(typeof(FlyoutPresenter));
Action<Panel>? panelCleanUp;
Func<PopupHandler, Panel?>? createControl;
/// <summary>
/// Method to initialize the native implementation.
/// </summary>
/// <param name="element">An instance of <see cref="IPopup"/>.</param>
public void SetElement(IPopup element)
{
VirtualView = element;
Closing += OnClosing;
}
/// <summary>
/// Method to setup the Content of the Popup using a WrapperControl
/// </summary>
/// <param name="panelCleanUp">Action to be executed when the Handler discconect</param>
/// <param name="createControl">Function to be executed during the create of the popup content</param>
public void SetUpPlatformView(Action<Panel> panelCleanUp, Func<PopupHandler, Panel?> createControl)
{
ArgumentNullException.ThrowIfNull(panelCleanUp);
ArgumentNullException.ThrowIfNull(createControl);
this.panelCleanUp = panelCleanUp;
this.createControl = createControl;
CreateControl();
ConfigureControl();
}
/// <summary>
/// Method to update all the values of the Popup Control.
/// </summary>
public void ConfigureControl()
{
if (VirtualView is null)
{
return;
}
FlyoutStyle = new(typeof(FlyoutPresenter));
SetFlyoutColor();
SetSize();
SetLayout();
ApplyStyles();
}
/// <summary>
/// Method to show the Popup.
/// </summary>
public void Show()
{
if (VirtualView is null)
{
return;
}
ArgumentNullException.ThrowIfNull(VirtualView.Parent);
if (VirtualView.Anchor is not null)
{
var anchor = VirtualView.Anchor.ToPlatform(mauiContext);
SetAttachedFlyout(anchor, this);
ShowAttachedFlyout(anchor);
}
else
{
var frameworkElement = VirtualView.Parent.ToPlatform(mauiContext);
frameworkElement.ContextFlyout = this;
SetAttachedFlyout(frameworkElement, this);
ShowAttachedFlyout(frameworkElement);
}
VirtualView.OnOpened();
}
/// <summary>
/// Method to CleanUp the resources of the <see cref="MauiPopup"/>.
/// </summary>
public void CleanUp()
{
Closing -= OnClosing;
Hide();
if (Control is not null)
{
panelCleanUp?.Invoke(Control);
}
VirtualView = null;
Control = null;
if (Target is not null)
{
Target.ContextFlyout = null;
}
}
void CreateControl()
{
if (Control is null && VirtualView?.Content is not null && createControl is not null && VirtualView.Handler is PopupHandler handler)
{
Control = createControl(handler);
Content = Control;
}
}
void SetSize()
{
_ = VirtualView ?? throw new InvalidOperationException($"{nameof(VirtualView)} cannot be null.");
if (Control is null)
{
return;
}
var standardSize = new Size { Width = defaultSize, Height = defaultSize / 2 };
var currentSize = VirtualView.Size != default ? VirtualView.Size : standardSize;
if (VirtualView.Content is not null && VirtualView.Size == default)
{
var content = VirtualView.Content;
// There are some situations when the Width and Height values will be NaN
// normally when the dev doesn't set the HeightRequest and WidthRequest
// and we can't use comparasion on those, so the only to prevent the application to crash
// is using this try/catch
try
{
currentSize = new Size(content.Width, content.Height);
}
catch (ArgumentException)
{
}
}
Control.Width = currentSize.Width;
Control.Height = currentSize.Height;
FlyoutStyle.Setters.Add(new Microsoft.UI.Xaml.Setter(FlyoutPresenter.MinHeightProperty, currentSize.Height + (defaultBorderThickness * 2)));
FlyoutStyle.Setters.Add(new Microsoft.UI.Xaml.Setter(FlyoutPresenter.MinWidthProperty, currentSize.Width + (defaultBorderThickness * 2)));
FlyoutStyle.Setters.Add(new Microsoft.UI.Xaml.Setter(FlyoutPresenter.MaxHeightProperty, currentSize.Height + (defaultBorderThickness * 2)));
FlyoutStyle.Setters.Add(new Microsoft.UI.Xaml.Setter(FlyoutPresenter.MaxWidthProperty, currentSize.Width + (defaultBorderThickness * 2)));
}
void SetLayout()
{
LightDismissOverlayMode = LightDismissOverlayMode.On;
if (VirtualView is not null)
{
this.SetDialogPosition(VirtualView.VerticalOptions, VirtualView.HorizontalOptions);
}
}
void SetFlyoutColor()
{
_ = VirtualView?.Content ?? throw new NullReferenceException(nameof(IPopup.Content));
var color = VirtualView.Color ?? Colors.Transparent;
FlyoutStyle.Setters.Add(new Microsoft.UI.Xaml.Setter(FlyoutPresenter.BackgroundProperty, color.ToWindowsColor()));
if (VirtualView.Color == Colors.Transparent)
{
FlyoutStyle.Setters.Add(new Microsoft.UI.Xaml.Setter(FlyoutPresenter.IsDefaultShadowEnabledProperty, false));
}
//Configure border
FlyoutStyle.Setters.Add(new Microsoft.UI.Xaml.Setter(FlyoutPresenter.PaddingProperty, 0));
FlyoutStyle.Setters.Add(new Microsoft.UI.Xaml.Setter(FlyoutPresenter.BorderThicknessProperty, new WindowsThickness(defaultBorderThickness)));
FlyoutStyle.Setters.Add(new Microsoft.UI.Xaml.Setter(FlyoutPresenter.BorderBrushProperty, Color.FromArgb("#2e6da0").ToWindowsColor()));
}
void ApplyStyles()
{
if (Control is null)
{
return;
}
FlyoutPresenterStyle = FlyoutStyle;
}
void SetDialogPosition(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions)
{
if (IsTopLeft(verticalOptions, horizontalOptions))
{
Placement = FlyoutPlacementMode.TopEdgeAlignedLeft;
}
else if (IsTop(verticalOptions, horizontalOptions))
{
Placement = FlyoutPlacementMode.Top;
}
else if (IsTopRight(verticalOptions, horizontalOptions))
{
Placement = FlyoutPlacementMode.TopEdgeAlignedRight;
}
else if (IsRight(verticalOptions, horizontalOptions))
{
Placement = FlyoutPlacementMode.Right;
}
else if (IsBottomRight(verticalOptions, horizontalOptions))
{
Placement = FlyoutPlacementMode.BottomEdgeAlignedRight;
}
else if (IsBottom(verticalOptions, horizontalOptions))
{
Placement = FlyoutPlacementMode.Bottom;
}
else if (IsBottomLeft(verticalOptions, horizontalOptions))
{
Placement = FlyoutPlacementMode.BottomEdgeAlignedLeft;
}
else if (IsLeft(verticalOptions, horizontalOptions))
{
Placement = FlyoutPlacementMode.Left;
}
else if (VirtualView is not null && VirtualView.Anchor is null)
{
Placement = FlyoutPlacementMode.Full;
}
else
{
Placement = FlyoutPlacementMode.Top;
}
static bool IsTopLeft(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Start && horizontalOptions == LayoutAlignment.Start;
static bool IsTop(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Start && horizontalOptions == LayoutAlignment.Center;
static bool IsTopRight(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Start && horizontalOptions == LayoutAlignment.End;
static bool IsRight(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Center && horizontalOptions == LayoutAlignment.End;
static bool IsBottomRight(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.End && horizontalOptions == LayoutAlignment.End;
static bool IsBottom(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.End && horizontalOptions == LayoutAlignment.Center;
static bool IsBottomLeft(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.End && horizontalOptions == LayoutAlignment.Start;
static bool IsLeft(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Center && horizontalOptions == LayoutAlignment.Start;
}
void OnClosing(object? sender, FlyoutBaseClosingEventArgs e)
{
var isLightDismissEnabled = VirtualView?.CanBeDismissedByTappingOutsideOfPopup is true;
if (!isLightDismissEnabled)
{
e.Cancel = true;
}
if (IsOpen && isLightDismissEnabled)
{
VirtualView?.Handler?.Invoke(nameof(IPopup.OnDismissedByTappingOutsideOfPopup));
}
}
}

Просмотреть файл

@ -133,6 +133,10 @@ public static class PopupExtensions
mauiPopup.PopoverPresentationController.SourceRect = new CGRect(originX, originY, 0, 0);
mauiPopup.PopoverPresentationController.PermittedArrowDirections = 0;
// From the point of view of usability, the top, bottom, left, and right values of UIEdgeInsets cannot all be 0.
// If you specify 0 for the top, bottom, left, and right of UIEdgeInsets, the default margins will be added, so
// specify a value as close to 0 here as possible.
mauiPopup.PopoverPresentationController.PopoverLayoutMargins = new UIEdgeInsets(0.0001f, 0.0001f, 0.0001f, 0.0001f);
}
else
{

Просмотреть файл

@ -1,4 +1,8 @@
using Microsoft.Maui.Platform;
using CommunityToolkit.Maui.Core.Handlers;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Primitives;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls.Primitives;
namespace CommunityToolkit.Maui.Core.Views;
@ -10,17 +14,174 @@ public static class PopupExtensions
/// <summary>
/// Method to update the <see cref="Maui.Core.IPopup.Content"/> based on the <see cref="Maui.Core.IPopup.Color"/>.
/// </summary>
/// <param name="flyout">An instance of <see cref="MauiPopup"/>.</param>
/// <param name="mauiPopup">An instance of <see cref="Popup"/>.</param>
/// <param name="popup">An instance of <see cref="Maui.Core.IPopup"/>.</param>
public static void SetColor(this MauiPopup flyout, IPopup popup)
public static void SetColor(this Popup mauiPopup, IPopup popup)
{
ArgumentNullException.ThrowIfNull(popup.Content);
var color = popup.Color ?? Colors.Transparent;
var view = popup.Content;
if (view.Background is null && flyout.Control is not null)
if (mauiPopup.Child is FrameworkElement content)
{
flyout.Control.Background = color.ToPlatform();
var backgroundProperty = content.GetType().GetProperty("Background");
backgroundProperty?.SetValue(content, color.ToPlatform());
}
}
/// <summary>
/// Method to update the popup anchor based on the <see cref="Maui.Core.IPopup.Anchor"/>.
/// </summary>
/// <param name="mauiPopup">An instance of <see cref="Popup"/>.</param>
/// <param name="popup">An instance of <see cref="IPopup"/>.</param>
/// <param name="mauiContext">An instance of <see cref="IMauiContext"/>.</param>
public static void SetAnchor(this Popup mauiPopup, IPopup popup, IMauiContext? mauiContext)
{
ArgumentNullException.ThrowIfNull(mauiContext);
mauiPopup.PlacementTarget = popup.Anchor?.ToPlatform(mauiContext);
}
/// <summary>
/// Method to prepare control.
/// </summary>
/// <param name="mauiPopup">An instance of <see cref="Popup"/>.</param>
/// <param name="popup">An instance of <see cref="IPopup"/>.</param>
/// <param name="mauiContext">An instance of <see cref="IMauiContext"/>.</param>
public static void ConfigureControl(this Popup mauiPopup, IPopup popup, IMauiContext? mauiContext)
{
ArgumentNullException.ThrowIfNull(mauiContext);
if (popup.Content is not null && popup.Handler is PopupHandler handler)
{
mauiPopup.Child = handler.VirtualView.Content?.ToPlatform(mauiContext);
}
mauiPopup.SetSize(popup);
mauiPopup.SetLayout(popup, mauiContext);
}
/// <summary>
/// Method to update the popup size based on the <see cref="Maui.Core.IPopup.Size"/>.
/// </summary>
/// <param name="mauiPopup">An instance of <see cref="Popup"/>.</param>
/// <param name="popup">An instance of <see cref="IPopup"/>.</param>
public static void SetSize(this Popup mauiPopup, IPopup popup)
{
const double defaultBorderThickness = 0;
const double defaultSize = 600;
var standardSize = new Size { Width = defaultSize, Height = defaultSize / 2 };
var currentSize = popup.Size != default ? popup.Size : standardSize;
if (popup.Content is not null && popup.Size == default)
{
var content = popup.Content;
// There are some situations when the Width and Height values will be NaN
// normally when the dev doesn't set the HeightRequest and WidthRequest
// and we can't use comparison on those, so the only to prevent the application to crash
// is using this try/catch
try
{
currentSize = new Size(content.Width, content.Height);
}
catch (ArgumentException)
{
}
}
if (popup.Parent is IView popupParent)
{
currentSize.Width = Math.Min(currentSize.Width, popupParent.Frame.Width);
currentSize.Height = Math.Min(currentSize.Height, popupParent.Frame.Height);
}
mauiPopup.Width = currentSize.Width;
mauiPopup.Height = currentSize.Height;
mauiPopup.MinWidth = mauiPopup.MaxWidth = currentSize.Width + (defaultBorderThickness * 2);
mauiPopup.MinHeight = mauiPopup.MaxHeight = currentSize.Height + (defaultBorderThickness * 2);
}
/// <summary>
/// Method to update the popup layout.
/// </summary>
/// <param name="mauiPopup">An instance of <see cref="Popup"/>.</param>
/// <param name="popup">An instance of <see cref="IPopup"/>.</param>
/// <param name="mauiContext">An instance of <see cref="IMauiContext"/>.</param>
public static void SetLayout(this Popup mauiPopup, IPopup popup, IMauiContext? mauiContext)
{
ArgumentNullException.ThrowIfNull(mauiContext);
var popupParent = popup.Parent as IView;
popup.Content?.Measure(double.PositiveInfinity, double.PositiveInfinity);
var contentSize = popup.Content?.ToPlatform(mauiContext).DesiredSize ?? Windows.Foundation.Size.Empty;
var popupParentFrame = popupParent?.Frame ?? new Rect(0, 0, contentSize.Width, contentSize.Height);
var verticalOptions = popup.VerticalOptions;
var horizontalOptions = popup.HorizontalOptions;
if (IsTopLeft(verticalOptions, horizontalOptions))
{
mauiPopup.DesiredPlacement = PopupPlacementMode.TopEdgeAlignedLeft;
mauiPopup.HorizontalOffset = 0;
mauiPopup.VerticalOffset = 0;
}
else if (IsTop(verticalOptions, horizontalOptions))
{
mauiPopup.DesiredPlacement = PopupPlacementMode.Top;
mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width) / 2;
mauiPopup.VerticalOffset = 0;
}
else if (IsTopRight(verticalOptions, horizontalOptions))
{
mauiPopup.DesiredPlacement = PopupPlacementMode.TopEdgeAlignedRight;
mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width);
mauiPopup.VerticalOffset = 0;
}
else if (IsRight(verticalOptions, horizontalOptions))
{
mauiPopup.DesiredPlacement = PopupPlacementMode.Right;
mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width);
mauiPopup.VerticalOffset = (popupParentFrame.Height - contentSize.Height) / 2;
}
else if (IsBottomRight(verticalOptions, horizontalOptions))
{
mauiPopup.DesiredPlacement = PopupPlacementMode.BottomEdgeAlignedRight;
mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width);
mauiPopup.VerticalOffset = popupParentFrame.Height + contentSize.Height / 2;
}
else if (IsBottom(verticalOptions, horizontalOptions))
{
mauiPopup.DesiredPlacement = PopupPlacementMode.Bottom;
mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width) / 2;
mauiPopup.VerticalOffset = popupParentFrame.Height + contentSize.Height / 2;
}
else if (IsBottomLeft(verticalOptions, horizontalOptions))
{
mauiPopup.DesiredPlacement = PopupPlacementMode.BottomEdgeAlignedLeft;
mauiPopup.HorizontalOffset = 0;
mauiPopup.VerticalOffset = popupParentFrame.Height + contentSize.Height / 2;
}
else if (IsLeft(verticalOptions, horizontalOptions))
{
mauiPopup.DesiredPlacement = PopupPlacementMode.Left;
mauiPopup.HorizontalOffset = 0;
mauiPopup.VerticalOffset = (popupParentFrame.Height - contentSize.Height) / 2;
}
else if (popup.Anchor is null)
{
mauiPopup.DesiredPlacement = PopupPlacementMode.Auto;
mauiPopup.HorizontalOffset = (popupParentFrame.Width - contentSize.Width) / 2;
mauiPopup.VerticalOffset = (popupParentFrame.Height - contentSize.Height) / 2;
}
else
{
mauiPopup.DesiredPlacement = PopupPlacementMode.Top;
}
static bool IsTopLeft(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Start && horizontalOptions == LayoutAlignment.Start;
static bool IsTop(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Start && horizontalOptions == LayoutAlignment.Center;
static bool IsTopRight(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Start && horizontalOptions == LayoutAlignment.End;
static bool IsRight(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Center && horizontalOptions == LayoutAlignment.End;
static bool IsBottomRight(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.End && horizontalOptions == LayoutAlignment.End;
static bool IsBottom(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.End && horizontalOptions == LayoutAlignment.Center;
static bool IsBottomLeft(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.End && horizontalOptions == LayoutAlignment.Start;
static bool IsLeft(LayoutAlignment verticalOptions, LayoutAlignment horizontalOptions) => verticalOptions == LayoutAlignment.Center && horizontalOptions == LayoutAlignment.Start;
}
}

Просмотреть файл

@ -1,79 +0,0 @@
using System.Runtime.InteropServices;
using CoreAnimation;
namespace CommunityToolkit.Maui.Core.Views;
/// <summary>
/// A rounded <see cref="UIStackView"/>
/// </summary>
[Obsolete]
public class RoundedStackView : UIStackView
{
/// <summary>
/// Initialize <see cref="RoundedStackView"/>
/// </summary>
public RoundedStackView(NFloat leftPadding, NFloat topPadding, NFloat rightPadding, NFloat bottomPadding)
{
LeftPadding = leftPadding;
TopPadding = topPadding;
RightPadding = rightPadding;
BottomPadding = bottomPadding;
}
/// <summary>
/// Left Padding
/// </summary>
public NFloat LeftPadding { get; }
/// <summary>
/// Top Padding
/// </summary>
public NFloat TopPadding { get; }
/// <summary>
/// Right Padding
/// </summary>
public NFloat RightPadding { get; }
/// <summary>
/// Bottom Padding
/// </summary>
public NFloat BottomPadding { get; }
/// <inheritdoc />
public override void Draw(CGRect rect)
{
ClipsToBounds = true;
var path = GetRoundedPath(rect, LeftPadding, TopPadding, RightPadding, BottomPadding);
var maskLayer = new CAShapeLayer
{
Frame = rect,
Path = path
};
Layer.Mask = maskLayer;
Layer.MasksToBounds = true;
}
static CGPath? GetRoundedPath(CGRect rect, NFloat left, NFloat top, NFloat right, NFloat bottom)
{
var path = new UIBezierPath();
path.MoveTo(new CGPoint(rect.Width - right, rect.Y));
path.AddArc(new CGPoint(rect.X + rect.Width - right, rect.Y + right), right, (NFloat)(Math.PI * 1.5), (NFloat)Math.PI * 2, true);
path.AddLineTo(new CGPoint(rect.Width, rect.Height - bottom));
path.AddArc(new CGPoint(rect.X + rect.Width - bottom, rect.Y + rect.Height - bottom), bottom, 0, (NFloat)(Math.PI * .5), true);
path.AddLineTo(new CGPoint(left, rect.Height));
path.AddArc(new CGPoint(rect.X + left, rect.Y + rect.Height - left), left, (NFloat)(Math.PI * .5), (NFloat)Math.PI, true);
path.AddLineTo(new CGPoint(rect.X, top));
path.AddArc(new CGPoint(rect.X + top, rect.Y + top), top, (NFloat)Math.PI, (NFloat)(Math.PI * 1.5), true);
path.ClosePath();
return path.CGPath;
}
}

Просмотреть файл

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0;net7.0-android;net7.0-ios;net7.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);net7.0-tizen</TargetFrameworks>
<TargetFrameworks>$(NetVersion);$(NetVersion)-android;$(NetVersion)-ios;$(NetVersion)-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);$(NetVersion)-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);$(NetVersion)-tizen</TargetFrameworks>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@ -23,7 +23,7 @@
<Authors>Microsoft</Authors>
<Owners>Microsoft</Owners>
<NeutralLanguage>en</NeutralLanguage>
<Product>CommunityToolkit.Maui (net7.0)</Product>
<Product>CommunityToolkit.Maui ($(NetVersion))</Product>
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/CommunityToolkit/Maui</PackageProjectUrl>
@ -51,6 +51,11 @@
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls.Maps" Version="7.0.86" />
<PackageReference Include="MemoryAnalyzers" Version="0.1.0-beta.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>

Просмотреть файл

@ -8,7 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.6.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.7.0" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0;net7.0-android;net7.0-ios;net7.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);net7.0-tizen</TargetFrameworks>
<TargetFrameworks>$(NetVersion);$(NetVersion)-android;$(NetVersion)-ios;$(NetVersion)-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);$(NetVersion)-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);$(NetVersion)-tizen</TargetFrameworks>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@ -25,7 +25,7 @@
<Authors>Microsoft</Authors>
<Owners>Microsoft</Owners>
<NeutralLanguage>en</NeutralLanguage>
<Product>CommunityToolkit.Maui (net7.0)</Product>
<Product>CommunityToolkit.Maui ($(NetVersion))</Product>
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/CommunityToolkit/Maui</PackageProjectUrl>
@ -53,11 +53,18 @@
<None Include="ReadMe.txt" pack="true" PackagePath="." />
</ItemGroup>
<ItemGroup>
<ItemGroup>
<None Include="..\CommunityToolkit.Maui.MediaElement.Analyzers\bin\$(Configuration)\netstandard2.0\CommunityToolkit.Maui.MediaElement.Analyzers.dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
<None Include="..\CommunityToolkit.Maui.MediaElement.Analyzers.CodeFixes\bin\$(Configuration)\netstandard2.0\CommunityToolkit.Maui.MediaElement.Analyzers.CodeFixes.dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MemoryAnalyzers" Version="0.1.0-beta.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.Contains('-android'))">
<PackageReference Include="Xam.Plugins.Android.ExoPlayer" Version="2.18.10" />
<PackageReference Include="Xam.Plugins.Android.ExoPlayer.Transformer" Version="2.18.10" />

Просмотреть файл

@ -44,13 +44,10 @@ public class MauiMediaElement : CoordinatorLayout
{
if (disposing)
{
if (playerView is not null)
{
// https://github.com/google/ExoPlayer/issues/1855#issuecomment-251041500
playerView.Player?.Release();
playerView.Player?.Dispose();
playerView.Dispose();
}
// https://github.com/google/ExoPlayer/issues/1855#issuecomment-251041500
playerView.Player?.Release();
playerView.Player?.Dispose();
playerView.Dispose();
}
base.Dispose(disposing);

Просмотреть файл

@ -7,7 +7,7 @@ namespace CommunityToolkit.Maui.Core.Views;
/// <summary>
/// The user-interface element that represents the <see cref="MediaElement"/> on Windows.
/// </summary>
public class MauiMediaElement : Grid
public class MauiMediaElement : Grid, IDisposable
{
readonly MediaPlayerElement mediaElement;
@ -26,6 +26,18 @@ public class MauiMediaElement : Grid
/// </summary>
public void Dispose()
{
mediaElement?.MediaPlayer.Dispose();
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases the managed and unmanaged resources used by the <see cref="MauiMediaElement"/>.
/// </summary>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
mediaElement.MediaPlayer.Dispose();
}
}
}

Просмотреть файл

@ -208,7 +208,7 @@ public partial class MediaManager : Java.Lang.Object, IPlayer.IListener
/// </remarks>
public void OnVolumeChanged(float volume)
{
if (Player is null || MediaElement is null)
if (Player is null)
{
return;
}
@ -252,8 +252,7 @@ public partial class MediaManager : Java.Lang.Object, IPlayer.IListener
protected virtual partial void PlatformStop()
{
if (Player is null || MediaElement is null
|| MediaElement.Source is null)
if (Player is null || MediaElement.Source is null)
{
return;
}
@ -315,7 +314,7 @@ public partial class MediaManager : Java.Lang.Object, IPlayer.IListener
var path = resourceMediaSource.Path;
if (!string.IsNullOrWhiteSpace(path))
{
string assetFilePath = "asset://" + package + "/" + path;
var assetFilePath = $"asset://{package}{Path.PathSeparator}{path}";
Player.SetMediaItem(MediaItem.FromUri(assetFilePath));
Player.Prepare();

Просмотреть файл

@ -24,6 +24,7 @@ class TextColorToGenerator : IIncrementalGenerator
const string iTextStyleInterface = "Microsoft.Maui.ITextStyle";
const string iAnimatableInterface = "Microsoft.Maui.Controls.IAnimatable";
const string mauiControlsAssembly = "Microsoft.Maui.Controls";
const string mauiColorFullName = "global::Microsoft.Maui.Graphics.Color";
public void Initialize(IncrementalGeneratorInitializationContext context)
{
@ -115,7 +116,7 @@ namespace {{textStyleClassMetadata.Namespace}};
/// <param name="length">The duration, in milliseconds, of the animation</param>
/// <param name="easing">The easing function to be used in the animation</param>
/// <returns>Value indicating if the animation completed successfully or not</returns>
public static Task<bool> TextColorTo{{textStyleClassMetadata.GenericArguments}}(this {{textStyleClassMetadata.Namespace}}.{{textStyleClassMetadata.ClassName}}{{textStyleClassMetadata.GenericArguments}} element, Color color, uint rate = 16u, uint length = 250u, Easing? easing = null)
public static Task<bool> TextColorTo{{textStyleClassMetadata.GenericArguments}}(this global::{{textStyleClassMetadata.Namespace}}.{{textStyleClassMetadata.ClassName}}{{textStyleClassMetadata.GenericArguments}} element, {{mauiColorFullName}} color, uint rate = 16u, uint length = 250u, Easing? easing = null)
{{textStyleClassMetadata.GenericConstraints}}
{
ArgumentNullException.ThrowIfNull(element);

Просмотреть файл

@ -44,7 +44,7 @@ public class StatusBarBehaviorTests : BaseTest
{
var statusBarBehavior = new StatusBarBehavior();
var exception = Assert.Throws<NotSupportedException>(() => statusBarBehavior.StatusBarColor = Colors.Red);
exception.Message.Should().Be("PlatformSetColor is only supported on net6.0-ios and net6.0-android and later");
exception.Message.Should().Be("PlatformSetColor is only supported on iOS and Android 23 and later");
}
[Fact]
@ -52,6 +52,6 @@ public class StatusBarBehaviorTests : BaseTest
{
var statusBarBehavior = new StatusBarBehavior();
var exception = Assert.Throws<NotSupportedException>(() => statusBarBehavior.StatusBarStyle = StatusBarStyle.DarkContent);
exception.Message.Should().Be("PlatformSetStyle is only supported on net6.0-ios and net6.0-android and later");
exception.Message.Should().Be("PlatformSetStyle is only supported on iOS and Android 23 and later");
}
}

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>$(NetVersion)</TargetFramework>
<UseMaui>true</UseMaui>
<IsPackable>false</IsPackable>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
@ -10,8 +10,8 @@
<ItemGroup>
<PackageReference Include="AutoFixture.Xunit2" Version="4.18.0" />
<PackageReference Include="FluentAssertions" Version="6.11.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.0" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
<PackageReference Include="xunit" Version="2.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0" PrivateAssets="All" />
<PackageReference Include="coverlet.collector" Version="6.0.0" PrivateAssets="All" />

Просмотреть файл

@ -53,7 +53,7 @@ public class IntToBoolConverterTests : BaseConverterTest<IntToBoolConverter>
{
var intToBoolConverter = new IntToBoolConverter();
Assert.Throws<ArgumentNullException>(() => ((ICommunityToolkitValueConverter)intToBoolConverter).Convert(null, typeof(bool), null, CultureInfo.CurrentCulture));
Assert.Throws<ArgumentNullException>(() => ((ICommunityToolkitValueConverter)intToBoolConverter).ConvertBack(null, typeof(bool), null, CultureInfo.CurrentCulture)); ;
Assert.Throws<ArgumentNullException>(() => ((ICommunityToolkitValueConverter)intToBoolConverter).ConvertBack(null, typeof(bool), null, CultureInfo.CurrentCulture));
}
[Theory]

Просмотреть файл

@ -348,7 +348,7 @@ public class GravatarImageSourceTests : BaseHandlerTest
CancellationTokenSource cts = new();
var gravatarImageSource = new GravatarImageSource();
Stream? stream = await gravatarImageSource.Stream(cts.Token);
stream.Should().BeNull();
stream.Should().NotBeNull();
}
[Fact]

Просмотреть файл

@ -66,14 +66,14 @@ public class StateContainerTests : BaseTest
[Fact]
public void StateView_HasStateKey()
{
var view = StateContainer.GetStateViews(layout).First();
var view = StateContainer.GetStateViews(layout)[0];
Assert.Equal(StateKey.Loading, StateView.GetStateKey(view));
}
[Fact]
public void StateView_SetsStateKey()
{
var view = (View)layout.Children.First();
var view = (View)layout.Children[0];
StateView.SetStateKey(view, StateKey.Anything);
Assert.Equal(StateKey.Anything, StateView.GetStateKey(view));
}
@ -484,7 +484,7 @@ public class StateContainerTests : BaseTest
public void Controller_SwitchesToStateFromContentSuccess()
{
controller.SwitchToState(StateKey.Loading);
var state = controller.GetLayout().Children.First();
var state = controller.GetLayout().Children[0];
Assert.IsType<Label>(state);
Assert.Equal("Loading", ((Label)state).Text);
@ -494,13 +494,13 @@ public class StateContainerTests : BaseTest
public void Controller_SwitchesToContentFromStateSuccess()
{
controller.SwitchToState(StateKey.Loading);
var label = controller.GetLayout().Children.First();
var label = controller.GetLayout().Children[0];
Assert.IsType<Label>(label);
Assert.Equal("Loading", ((Label)label).Text);
controller.SwitchToContent();
label = controller.GetLayout().Children.First();
label = controller.GetLayout().Children[0];
Assert.IsType<Label>(label);
Assert.Equal("Default", ((Label)label).Text);
@ -510,13 +510,13 @@ public class StateContainerTests : BaseTest
public void Controller_SwitchesToStateFromStateSuccess()
{
controller.SwitchToState(StateKey.Anything);
var label = controller.GetLayout().Children.First();
var label = controller.GetLayout().Children[0];
Assert.IsType<Label>(label);
Assert.Equal("Anything", ((Label)label).Text);
controller.SwitchToState(StateKey.Loading);
label = controller.GetLayout().Children.First();
label = controller.GetLayout().Children[0];
Assert.IsType<Label>(label);
Assert.Equal("Loading", ((Label)label).Text);
@ -526,13 +526,13 @@ public class StateContainerTests : BaseTest
public void Controller_SwitchesToStateFromSameStateSuccess()
{
controller.SwitchToState(StateKey.Loading);
var label = controller.GetLayout().Children.First();
var label = controller.GetLayout().Children[0];
Assert.IsType<Label>(label);
Assert.Equal("Loading", ((Label)label).Text);
controller.SwitchToState(StateKey.Loading);
label = controller.GetLayout().Children.First();
label = controller.GetLayout().Children[0];
Assert.IsType<Label>(label);
Assert.Equal("Loading", ((Label)label).Text);
@ -542,7 +542,7 @@ public class StateContainerTests : BaseTest
public void Controller_GridStateViewSpansParent()
{
gridController.SwitchToState(StateKey.Loading);
var view = (View)gridController.GetLayout().Children.First();
var view = (View)gridController.GetLayout().Children[0];
Assert.Equal(Grid.GetColumnSpan(view), grid.ColumnDefinitions.Count);
Assert.Equal(Grid.GetRowSpan(view), grid.RowDefinitions.Count);

Просмотреть файл

@ -39,7 +39,7 @@ sealed class MockDispatcherProvider : IDispatcherProvider, IDisposable
}
}
class DispatcherTimerStub : IDispatcherTimer, IDisposable
sealed class DispatcherTimerStub : IDispatcherTimer, IDisposable
{
readonly DispatcherMock dispatcher;

Просмотреть файл

@ -19,10 +19,6 @@ public partial class Toast
return;
}
if (isDisposing)
{
}
isDisposed = true;
}

Просмотреть файл

@ -47,7 +47,6 @@ public abstract class BaseBehavior<TView> : Behavior<TView> where TView : Visual
defaultBindingContextBinding = null;
return true;
}
/// <summary>
@ -117,6 +116,6 @@ public abstract class BaseBehavior<TView> : Behavior<TView> where TView : Visual
catch (Exception ex) when (Options.ShouldSuppressExceptionsInBehaviors)
{
Trace.WriteLine(ex);
};
}
}
}

Просмотреть файл

@ -33,7 +33,7 @@ public class EventToCommandBehavior : BaseBehavior<VisualElement>
public static readonly BindableProperty EventArgsConverterProperty =
BindableProperty.Create(nameof(EventArgsConverter), typeof(IValueConverter), typeof(EventToCommandBehavior));
readonly MethodInfo eventHandlerMethodInfo = typeof(EventToCommandBehavior).GetTypeInfo()?.GetDeclaredMethod(nameof(OnTriggerHandled)) ?? throw new InvalidOperationException($"Cannot find method {nameof(OnTriggerHandled)}");
readonly MethodInfo eventHandlerMethodInfo = typeof(EventToCommandBehavior).GetTypeInfo().GetDeclaredMethod(nameof(OnTriggerHandled)) ?? throw new InvalidOperationException($"Cannot find method {nameof(OnTriggerHandled)}");
Delegate? eventHandler;
@ -102,7 +102,7 @@ public class EventToCommandBehavior : BaseBehavior<VisualElement>
return;
}
eventInfo = View.GetType()?.GetRuntimeEvent(eventName) ??
eventInfo = View.GetType().GetRuntimeEvent(eventName) ??
throw new ArgumentException($"{nameof(EventToCommandBehavior)}: Couldn't resolve the event.", nameof(EventName));
ArgumentNullException.ThrowIfNull(eventInfo.EventHandlerType);

Просмотреть файл

@ -118,14 +118,7 @@ public partial class IconTintColorBehavior
void LoadAndApplyImageTintColor(View element, WImage image, Color color)
{
if (image.IsLoaded)
{
ApplyTintColor();
}
else
{
image.ImageOpened += OnImageOpened;
}
image.ImageOpened += OnImageOpened;
void OnImageOpened(object sender, RoutedEventArgs e)
{

Просмотреть файл

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Versioning;
using System.Text;
@ -74,7 +75,7 @@ public class SelectAllTextBehavior : PlatformBehavior<InputView>
{
if (OperatingSystem.IsMacCatalyst())
{
Console.WriteLine("WARNING: `SelectAllTextBehavior` does not support `Microsoft.Maui.Controls.Editor` on MacCatalyst. For more information, see https://github.com/CommunityToolkit/Maui/issues/432");
Trace.WriteLine("WARNING: `SelectAllTextBehavior` does not support `Microsoft.Maui.Controls.Editor` on MacCatalyst. For more information, see https://github.com/CommunityToolkit/Maui/issues/432");
}
if (element is not Editor mauiControl)

Просмотреть файл

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0;net7.0-android;net7.0-ios;net7.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);net7.0-tizen</TargetFrameworks>
<TargetFrameworks>$(NetVersion);$(NetVersion)-android;$(NetVersion)-ios;$(NetVersion)-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);$(NetVersion)-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);$(NetVersion)-tizen</TargetFrameworks>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@ -26,7 +26,7 @@
<Authors>Microsoft</Authors>
<Owners>Microsoft</Owners>
<NeutralLanguage>en</NeutralLanguage>
<Product>CommunityToolkit.Maui (net7.0)</Product>
<Product>CommunityToolkit.Maui ($(NetVersion))</Product>
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/CommunityToolkit/Maui</PackageProjectUrl>
@ -67,6 +67,11 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="MemoryAnalyzers" Version="0.1.0-beta.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>

Просмотреть файл

@ -76,7 +76,7 @@ public abstract class CompareConverter<TObject> : BaseConverterOneWay<IComparabl
public TObject? FalseObject { get; set; }
/// <summary>
/// Converts an object that implements IComparable to a specified object or a boolean based on a comparaison result.
/// Converts an object that implements IComparable to a specified object or a boolean based on a comparison result.
/// </summary>
/// <param name="value">The value to convert.</param>
/// <param name="culture">The culture to use in the converter. This is not implemented.</param>
@ -90,7 +90,7 @@ public abstract class CompareConverter<TObject> : BaseConverterOneWay<IComparabl
if (!Enum.IsDefined(typeof(OperatorType), ComparisonOperator))
{
throw new ArgumentOutOfRangeException($"is expected to be of type {nameof(OperatorType)}", nameof(ComparisonOperator));
throw new ArgumentOutOfRangeException(nameof(ComparisonOperator), ComparingValue, $"is expected to be of type {nameof(OperatorType)}");
}
if (!(TrueObject is null ^ FalseObject is not null))

Просмотреть файл

@ -1,5 +1,6 @@
using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Core.Handlers;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;
@ -26,7 +27,8 @@ public partial class Popup
view.SetBinding(BindingContextProperty, new Binding { Source = virtualView, Path = BindingContextProperty.PropertyName });
var contentPage = new ContentPage
{
Content = view
Content = view,
Parent = virtualView.Parent as Element
};
return (PageHandler)contentPage.ToHandler(mauiContext);

Просмотреть файл

@ -1,33 +0,0 @@
using CommunityToolkit.Maui.Core.Handlers;
using CommunityToolkit.Maui.Core.Views;
using Microsoft.UI.Xaml.Controls;
namespace CommunityToolkit.Maui.Views;
public partial class Popup
{
void OnPopupHandlerChanged(object? sender, EventArgs e)
{
if (Handler?.PlatformView is null)
{
return;
}
((MauiPopup)Handler.PlatformView).SetUpPlatformView(CleanUp, CreateWrapperContent);
static void CleanUp(Panel wrapper)
{
((WrapperControl)wrapper).CleanUp();
}
static Panel? CreateWrapperContent(PopupHandler handler)
{
if (handler.VirtualView.Content is null || handler.MauiContext is null)
{
return null;
}
return new WrapperControl((View)handler.VirtualView.Content, handler.MauiContext);
}
}
}

Просмотреть файл

@ -56,9 +56,6 @@ public partial class Popup : Element, IPopup, IWindowController, IPropertyPropag
platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<Popup>>(() => new(this));
VerticalOptions = HorizontalOptions = LayoutAlignment.Center;
#if WINDOWS
this.HandlerChanged += OnPopupHandlerChanged;
#endif
}
/// <summary>

Просмотреть файл

@ -52,6 +52,8 @@ public static partial class PopupExtensions
/// </returns>
public static Task<object?> ShowPopupAsync<TPopup>(this Page page, TPopup popup) where TPopup : Popup
{
page = PageExtensions.GetCurrentPage(page);
if (page.IsPlatformEnabled)
{
return CreateAndShowPopupAsync(page, popup);