diff --git a/Avalonia.sln b/Avalonia.sln
index a216229a5b..1e2a3c6027 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -39,6 +39,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DE
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs
+ src\Shared\SourceGeneratorAttributes.cs = src\Shared\SourceGeneratorAttributes.cs
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI", "src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}"
@@ -55,8 +56,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{7CF9
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Android", "src\Android\Avalonia.Android\Avalonia.Android.csproj", "{7B92AF71-6287-4693-9DCB-BD5B6E927E23}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.AndroidTestApplication", "src\Android\Avalonia.AndroidTestApplication\Avalonia.AndroidTestApplication.csproj", "{FF69B927-C545-49AE-8E16-3D14D621AA12}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "iOS", "iOS", "{0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.iOS", "src\iOS\Avalonia.iOS\Avalonia.iOS.csproj", "{4488AD85-1495-4809-9AA4-DDFE0A48527E}"
@@ -113,6 +112,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\SharedVersion.props = build\SharedVersion.props
build\SharpDX.props = build\SharpDX.props
build\SkiaSharp.props = build\SkiaSharp.props
+ build\SourceGenerators.props = build\SourceGenerators.props
build\SourceLink.props = build\SourceLink.props
build\System.Drawing.Common.props = build\System.Drawing.Common.props
build\System.Memory.props = build\System.Memory.props
@@ -209,10 +209,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlSamples", "samples\S
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.PlatformSupport", "src\Avalonia.PlatformSupport\Avalonia.PlatformSupport.csproj", "{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.iOS", "samples\ControlCatalog.iOS\ControlCatalog.iOS.csproj", "{70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.iOS", "samples\ControlCatalog.iOS\ControlCatalog.iOS.csproj", "{70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.PlatformSupport.UnitTests", "tests\Avalonia.PlatformSupport.UnitTests\Avalonia.PlatformSupport.UnitTests.csproj", "{CE910927-CE5A-456F-BC92-E4C757354A5C}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.SourceGenerator", "src\Avalonia.SourceGenerator\Avalonia.SourceGenerator.csproj", "{CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevAnalyzers", "src\tools\DevAnalyzers\DevAnalyzers.csproj", "{2B390431-288C-435C-BB6B-A374033BD8D1}"
EndProject
Global
@@ -629,22 +631,6 @@ Global
{7B92AF71-6287-4693-9DCB-BD5B6E927E23}.Release|Any CPU.Build.0 = Release|Any CPU
{7B92AF71-6287-4693-9DCB-BD5B6E927E23}.Release|iPhone.ActiveCfg = Release|Any CPU
{7B92AF71-6287-4693-9DCB-BD5B6E927E23}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.AppStore|iPhone.ActiveCfg = Release|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Debug|iPhone.ActiveCfg = Debug|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|Any CPU.Build.0 = Release|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|Any CPU.Deploy.0 = Release|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|iPhone.ActiveCfg = Release|Any CPU
- {FF69B927-C545-49AE-8E16-3D14D621AA12}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4488AD85-1495-4809-9AA4-DDFE0A48527E}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{4488AD85-1495-4809-9AA4-DDFE0A48527E}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{4488AD85-1495-4809-9AA4-DDFE0A48527E}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
@@ -1929,6 +1915,30 @@ Global
{CE910927-CE5A-456F-BC92-E4C757354A5C}.Release|iPhone.Build.0 = Release|Any CPU
{CE910927-CE5A-456F-BC92-E4C757354A5C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{CE910927-CE5A-456F-BC92-E4C757354A5C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Release|iPhone.Build.0 = Release|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {CA932DF3-2616-4BF6-8F28-1AD0EC40F1FF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{2B390431-288C-435C-BB6B-A374033BD8D1}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{2B390431-288C-435C-BB6B-A374033BD8D1}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{2B390431-288C-435C-BB6B-A374033BD8D1}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
@@ -1970,7 +1980,6 @@ Global
{8EF392D5-1416-45AA-9956-7CBBC3229E8A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}
- {FF69B927-C545-49AE-8E16-3D14D621AA12} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}
{4488AD85-1495-4809-9AA4-DDFE0A48527E} = {0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1}
{E1AA3DBF-9056-4530-9376-18119A7A3FFE} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{88060192-33D5-4932-B0F9-8BD2763E857D} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
diff --git a/build/DevAnalyzers.props b/build/DevAnalyzers.props
index 28959dbd47..14e4f6a563 100644
--- a/build/DevAnalyzers.props
+++ b/build/DevAnalyzers.props
@@ -1,6 +1,6 @@
-
+
+
+
+
+
diff --git a/native/Avalonia.Native/src/OSX/app.mm b/native/Avalonia.Native/src/OSX/app.mm
index 79175d9ff1..05b129baca 100644
--- a/native/Avalonia.Native/src/OSX/app.mm
+++ b/native/Avalonia.Native/src/OSX/app.mm
@@ -73,6 +73,11 @@ ComPtr _events;
_isHandlingSendEvent = true;
@try {
[super sendEvent: event];
+ if ([event type] == NSEventTypeKeyUp && ([event modifierFlags] & NSEventModifierFlagCommand))
+ {
+ [[self keyWindow] sendEvent:event];
+ }
+
} @finally {
_isHandlingSendEvent = oldHandling;
}
diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm
index d16c466fe6..4426e7fdff 100644
--- a/native/Avalonia.Native/src/OSX/window.mm
+++ b/native/Avalonia.Native/src/OSX/window.mm
@@ -457,7 +457,7 @@ public:
}
point = ConvertPointY(point);
- NSRect convertRect = [Window convertRectToScreen:NSMakeRect(point.X, point.Y, 0.0, 0.0)];
+ NSRect convertRect = [Window convertRectFromScreen:NSMakeRect(point.X, point.Y, 0.0, 0.0)];
auto viewPoint = NSMakePoint(convertRect.origin.x, convertRect.origin.y);
*ret = [View translateLocalPoint:ToAvnPoint(viewPoint)];
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index 9fcb9d6b7f..f0f677b844 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -221,6 +221,7 @@ partial class Build : NukeBuild
RunCoreTest("Avalonia.Markup.Xaml.UnitTests");
RunCoreTest("Avalonia.Skia.UnitTests");
RunCoreTest("Avalonia.ReactiveUI.UnitTests");
+ RunCoreTest("Avalonia.PlatformSupport.UnitTests");
});
Target RunRenderTests => _ => _
diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
index 8d2ead054c..04c67e84e8 100644
--- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
+++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
@@ -39,49 +39,9 @@
-
+
-
- {7b92af71-6287-4693-9dcb-bd5b6e927e23}
- Avalonia.Android
-
-
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
- Avalonia.Base
-
-
- {d2221c82-4a25-4583-9b43-d791e3f6820c}
- Avalonia.Controls
-
-
- {7062ae20-5dcc-4442-9645-8195bdece63e}
- Avalonia.Diagnostics
-
-
- {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}
- Avalonia.Themes.Default
-
-
- {3e53a01a-b331-47f3-b828-4a5717e77a24}
- Avalonia.Markup.Xaml
-
-
- {6417e941-21bc-467b-a771-0de389353ce6}
- Avalonia.Markup
-
-
- {7d2d3083-71dd-4cc9-8907-39a0d86fb322}
- Avalonia.Skia
-
-
- {d0a739b9-3c68-4ba6-a328-41606954b6bd}
- ControlCatalog
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
index d1b657722c..2b45ac1508 100644
--- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
+++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
@@ -6,7 +6,7 @@
true
-
+
true
https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json
7.0.0-*
@@ -22,12 +22,11 @@
-
+
-
diff --git a/samples/ControlCatalog.NetCore/rd.xml b/samples/ControlCatalog.NetCore/rd.xml
deleted file mode 100644
index 27db7f34ca..0000000000
--- a/samples/ControlCatalog.NetCore/rd.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj b/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj
index d4f10b3580..513ac44f83 100644
--- a/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj
+++ b/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj
@@ -7,59 +7,10 @@
True
iossimulator-x64
-
+
-
-
-
-
-
-
-
-
- {4488ad85-1495-4809-9aa4-ddfe0a48527e}
- Avalonia.iOS
-
-
- {3E53A01A-B331-47F3-B828-4A5717E77A24}
- Avalonia.Markup.Xaml
-
-
- {6417E941-21BC-467B-A771-0DE389353CE6}
- Avalonia.Markup
-
-
- {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
- Avalonia.Base
-
-
- {D2221C82-4A25-4583-9B43-D791E3F6820C}
- Avalonia.Controls
-
-
- {7062AE20-5DCC-4442-9645-8195BDECE63E}
- Avalonia.Diagnostics
-
-
- {3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}
- Avalonia.Themes.Default
-
-
- {7d2d3083-71dd-4cc9-8907-39a0d86fb322}
- Avalonia.Skia
-
-
- {d0a739b9-3c68-4ba6-a328-41606954b6bd}
- ControlCatalog
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/samples/ControlCatalog/Pages/DataGridPage.xaml b/samples/ControlCatalog/Pages/DataGridPage.xaml
index f7e3cf2441..31b4039d33 100644
--- a/samples/ControlCatalog/Pages/DataGridPage.xaml
+++ b/samples/ControlCatalog/Pages/DataGridPage.xaml
@@ -13,9 +13,22 @@
+
+
+
+
@@ -31,7 +44,9 @@
-
+
diff --git a/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml b/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml
index 8305d72d1f..1d42b92096 100644
--- a/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml
+++ b/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml
@@ -53,10 +53,12 @@
UniformGrid - Horizontal
+
+
("scroller");
_scrollToLast = this.FindControl
+
+
+
@@ -430,9 +452,12 @@
Width="12"
Height="12"
Margin="12,0,0,0"
+ BorderBrush="{TemplateBinding BorderBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
- Foreground="{TemplateBinding Foreground}"
- Focusable="False" />
+ CornerRadius="{TemplateBinding CornerRadius}"
+ Focusable="False"
+ Foreground="{TemplateBinding Foreground}" />
-
-
+ CornerRadius="{TemplateBinding CornerRadius}">
+
diff --git a/src/Avalonia.Controls/ApiCompatBaseline.txt b/src/Avalonia.Controls/ApiCompatBaseline.txt
index fe3ac31734..33e5efbc15 100644
--- a/src/Avalonia.Controls/ApiCompatBaseline.txt
+++ b/src/Avalonia.Controls/ApiCompatBaseline.txt
@@ -1,11 +1,17 @@
Compat issues with assembly Avalonia.Controls:
+MembersMustExist : Member 'protected void Avalonia.Controls.Button.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.ButtonSpinner.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.CalendarDatePicker.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.ContextMenu.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'Avalonia.Controls.DropDown' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'Avalonia.Controls.DropDownItem' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.Expander.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Controls.IMenuItem.StaysOpenOnClick' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Controls.IMenuItem.StaysOpenOnClick.get()' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.IMenuItem.StaysOpenOnClick.set(System.Boolean)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseClosed()' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseOpening()' is present in the implementation but not in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.ItemsRepeater.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.DirectProperty Avalonia.DirectProperty Avalonia.Controls.NumericUpDown.ValueProperty' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.StyledProperty Avalonia.StyledProperty Avalonia.Controls.NumericUpDown.IncrementProperty' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.StyledProperty Avalonia.StyledProperty Avalonia.Controls.NumericUpDown.MaximumProperty' does not exist in the implementation but it does exist in the contract.
@@ -30,7 +36,9 @@ MembersMustExist : Member 'public void Avalonia.Controls.NumericUpDown.Value.set
MembersMustExist : Member 'public void Avalonia.Controls.NumericUpDownValueChangedEventArgs..ctor(Avalonia.Interactivity.RoutedEvent, System.Double, System.Double)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public System.Double Avalonia.Controls.NumericUpDownValueChangedEventArgs.NewValue.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public System.Double Avalonia.Controls.NumericUpDownValueChangedEventArgs.OldValue.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.ProgressBar.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.StyledProperty Avalonia.StyledProperty Avalonia.Controls.ScrollViewer.AllowAutoHideProperty' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.Slider.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.AttachedProperty Avalonia.AttachedProperty Avalonia.Controls.TextBlock.FontFamilyProperty' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.AttachedProperty Avalonia.AttachedProperty Avalonia.Controls.TextBlock.FontStyleProperty' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.AttachedProperty Avalonia.AttachedProperty Avalonia.Controls.TextBlock.FontWeightProperty' does not exist in the implementation but it does exist in the contract.
@@ -51,10 +59,12 @@ MembersMustExist : Member 'public void Avalonia.Controls.TextBlock.SetFontSize(A
MembersMustExist : Member 'public void Avalonia.Controls.TextBlock.SetFontStyle(Avalonia.Controls.Control, Avalonia.Media.FontStyle)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Controls.TextBlock.SetFontWeight(Avalonia.Controls.Control, Avalonia.Media.FontWeight)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Controls.TextBlock.SetForeground(Avalonia.Controls.Control, Avalonia.Media.IBrush)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.TextBox.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.TopLevel' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract.
CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Viewbox' does not inherit from base type 'Avalonia.Controls.Decorator' in the implementation but it does in the contract.
MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Viewbox.StretchProperty' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Window' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.Window.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.WindowBase' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.EventHandler Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.ShutdownRequested' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.add_ShutdownRequested(System.EventHandler)' is present in the implementation but not in the contract.
@@ -65,12 +75,17 @@ MembersMustExist : Member 'public System.Action Avalonia.Controls
MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.Resized.set(System.Action)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Notifications.NotificationCard.CloseOnClickProperty' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.Notifications.WindowNotificationManager.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.Platform.ITopLevelNativeMenuExporter.SetNativeMenu(Avalonia.Controls.NativeMenu)' is present in the contract but not in the implementation.
+MembersMustExist : Member 'protected void Avalonia.Controls.Presenters.ScrollContentPresenter.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'protected Avalonia.Media.FormattedText Avalonia.Controls.Presenters.TextPresenter.CreateFormattedText()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Media.FormattedText Avalonia.Controls.Presenters.TextPresenter.FormattedText.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public System.Int32 Avalonia.Controls.Presenters.TextPresenter.GetCaretIndex(Avalonia.Point)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'protected void Avalonia.Controls.Presenters.TextPresenter.InvalidateFormattedText()' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Primitives.PopupRoot' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.Primitives.ScrollBar.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.Primitives.SelectingItemsControl.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.Primitives.Track.OnPropertyChanged(Avalonia.AvaloniaPropertyChangedEventArgs)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'Avalonia.Platform.ExportWindowingSubsystemAttribute' does not exist in the implementation but it does exist in the contract.
EnumValuesMustMatch : Enum value 'Avalonia.Platform.ExtendClientAreaChromeHints Avalonia.Platform.ExtendClientAreaChromeHints.Default' is (System.Int32)2 in the implementation but (System.Int32)1 in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.Screen Avalonia.Platform.IScreenImpl.ScreenFromPoint(Avalonia.PixelPoint)' is present in the implementation but not in the contract.
@@ -94,4 +109,4 @@ InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platfor
MembersMustExist : Member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size)' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size, Avalonia.Platform.PlatformResizeReason)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.ITrayIconImpl Avalonia.Platform.IWindowingPlatform.CreateTrayIcon()' is present in the implementation but not in the contract.
-Total Issues: 95
+Total Issues: 110
diff --git a/src/Avalonia.Controls/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox.cs
index 3316c06bf5..5c95932c1f 100644
--- a/src/Avalonia.Controls/AutoCompleteBox.cs
+++ b/src/Avalonia.Controls/AutoCompleteBox.cs
@@ -1346,12 +1346,16 @@ namespace Avalonia.Controls
/// enabled.
///
/// The property.
- /// The new binding value for the property.
- protected override void UpdateDataValidation(AvaloniaProperty property, BindingValue value)
+ /// The current data binding state.
+ /// The current data binding error, if any.
+ protected override void UpdateDataValidation(
+ AvaloniaProperty property,
+ BindingValueType state,
+ Exception? error)
{
if (property == TextProperty || property == SelectedItemProperty)
{
- DataValidationErrors.SetError(this, value.Error);
+ DataValidationErrors.SetError(this, error);
}
}
diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs
index a4d15bab8d..0ef1ba4c8c 100644
--- a/src/Avalonia.Controls/Button.cs
+++ b/src/Avalonia.Controls/Button.cs
@@ -413,7 +413,7 @@ namespace Avalonia.Controls
}
///
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
@@ -421,12 +421,13 @@ namespace Avalonia.Controls
{
if (((ILogical)this).IsAttachedToLogicalTree)
{
- if (change.OldValue.GetValueOrDefault() is ICommand oldCommand)
+ var (oldValue, newValue) = change.GetOldAndNewValue();
+ if (oldValue is ICommand oldCommand)
{
oldCommand.CanExecuteChanged -= CanExecuteChanged;
}
- if (change.NewValue.GetValueOrDefault() is ICommand newCommand)
+ if (newValue is ICommand newCommand)
{
newCommand.CanExecuteChanged += CanExecuteChanged;
}
@@ -440,7 +441,7 @@ namespace Avalonia.Controls
}
else if (change.Property == IsCancelProperty)
{
- var isCancel = change.NewValue.GetValueOrDefault();
+ var isCancel = change.GetNewValue();
if (VisualRoot is IInputElement inputRoot)
{
@@ -456,7 +457,7 @@ namespace Avalonia.Controls
}
else if (change.Property == IsDefaultProperty)
{
- var isDefault = change.NewValue.GetValueOrDefault();
+ var isDefault = change.GetNewValue();
if (VisualRoot is IInputElement inputRoot)
{
@@ -476,8 +477,7 @@ namespace Avalonia.Controls
}
else if (change.Property == FlyoutProperty)
{
- var oldFlyout = change.OldValue.GetValueOrDefault() as FlyoutBase;
- var newFlyout = change.NewValue.GetValueOrDefault() as FlyoutBase;
+ var (oldFlyout, newFlyout) = change.GetOldAndNewValue();
// If flyout is changed while one is already open, make sure we
// close the old one first
@@ -498,12 +498,15 @@ namespace Avalonia.Controls
protected override AutomationPeer OnCreateAutomationPeer() => new ButtonAutomationPeer(this);
///
- protected override void UpdateDataValidation(AvaloniaProperty property, BindingValue value)
+ protected override void UpdateDataValidation(
+ AvaloniaProperty property,
+ BindingValueType state,
+ Exception? error)
{
- base.UpdateDataValidation(property, value);
+ base.UpdateDataValidation(property, state, error);
if (property == CommandProperty)
{
- if (value.Type == BindingValueType.BindingError)
+ if (state == BindingValueType.BindingError)
{
if (_commandCanExecute)
{
diff --git a/src/Avalonia.Controls/ButtonSpinner.cs b/src/Avalonia.Controls/ButtonSpinner.cs
index 29a954098f..e455c6c6f3 100644
--- a/src/Avalonia.Controls/ButtonSpinner.cs
+++ b/src/Avalonia.Controls/ButtonSpinner.cs
@@ -210,13 +210,13 @@ namespace Avalonia.Controls
}
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == ButtonSpinnerLocationProperty)
{
- UpdatePseudoClasses(change.NewValue.GetValueOrDefault());
+ UpdatePseudoClasses(change.GetNewValue());
}
}
diff --git a/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs b/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs
index 0ac2056ed1..0409eb30aa 100644
--- a/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs
@@ -540,11 +540,11 @@ namespace Avalonia.Controls
}
}
- protected override void UpdateDataValidation(AvaloniaProperty property, BindingValue value)
+ protected override void UpdateDataValidation(AvaloniaProperty property, BindingValueType state, Exception? error)
{
if (property == SelectedDateProperty)
{
- DataValidationErrors.SetError(this, value.Error);
+ DataValidationErrors.SetError(this, error);
}
}
diff --git a/src/Avalonia.Controls/Calendar/DateTimeHelper.cs b/src/Avalonia.Controls/Calendar/DateTimeHelper.cs
index eb90f6c399..7a5c74a51b 100644
--- a/src/Avalonia.Controls/Calendar/DateTimeHelper.cs
+++ b/src/Avalonia.Controls/Calendar/DateTimeHelper.cs
@@ -68,10 +68,7 @@ namespace Avalonia.Controls
public static DateTime DiscardDayTime(DateTime d)
{
- int year = d.Year;
- int month = d.Month;
- DateTime newD = new DateTime(year, month, 1, 0, 0, 0);
- return newD;
+ return new DateTime(d.Year, d.Month, 1, 0, 0, 0);
}
[return: NotNullIfNotNull("d")]
diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs
index a6dee5cfaa..cbf9b35a05 100644
--- a/src/Avalonia.Controls/ComboBox.cs
+++ b/src/Avalonia.Controls/ComboBox.cs
@@ -453,42 +453,18 @@ namespace Avalonia.Controls
private void SelectNext()
{
- int next = SelectedIndex + 1;
-
- if (next >= ItemCount)
+ if (ItemCount >= 1)
{
- if (WrapSelection == true)
- {
- next = 0;
- }
- else
- {
- return;
- }
+ MoveSelection(NavigationDirection.Next, WrapSelection);
}
-
-
-
- SelectedIndex = next;
}
private void SelectPrev()
{
- int prev = SelectedIndex - 1;
-
- if (prev < 0)
+ if (ItemCount >= 1)
{
- if (WrapSelection == true)
- {
- prev = ItemCount - 1;
- }
- else
- {
- return;
- }
+ MoveSelection(NavigationDirection.Previous, WrapSelection);
}
-
- SelectedIndex = prev;
}
}
}
diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs
index bc5195ff6c..ee2378101a 100644
--- a/src/Avalonia.Controls/ContextMenu.cs
+++ b/src/Avalonia.Controls/ContextMenu.cs
@@ -241,13 +241,13 @@ namespace Avalonia.Controls
}
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == WindowManagerAddShadowHintProperty && _popup != null)
{
- _popup.WindowManagerAddShadowHint = change.NewValue.GetValueOrDefault();
+ _popup.WindowManagerAddShadowHint = change.GetNewValue();
}
}
diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs
index 2c696c8f74..d6a5fa0727 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -348,7 +348,7 @@ namespace Avalonia.Controls
}
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
diff --git a/src/Avalonia.Controls/Documents/Inline.cs b/src/Avalonia.Controls/Documents/Inline.cs
index a657d754b3..b400625903 100644
--- a/src/Avalonia.Controls/Documents/Inline.cs
+++ b/src/Avalonia.Controls/Documents/Inline.cs
@@ -54,7 +54,7 @@ namespace Avalonia.Controls.Documents
TextDecorations, Foreground, Background, BaselineAlignment);
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
diff --git a/src/Avalonia.Controls/Documents/Run.cs b/src/Avalonia.Controls/Documents/Run.cs
index 2c6482b586..2bd66b8a64 100644
--- a/src/Avalonia.Controls/Documents/Run.cs
+++ b/src/Avalonia.Controls/Documents/Run.cs
@@ -68,7 +68,7 @@ namespace Avalonia.Controls.Documents
stringBuilder.Append(text);
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
diff --git a/src/Avalonia.Controls/Documents/TextElement.cs b/src/Avalonia.Controls/Documents/TextElement.cs
index faf869cce6..f228519e60 100644
--- a/src/Avalonia.Controls/Documents/TextElement.cs
+++ b/src/Avalonia.Controls/Documents/TextElement.cs
@@ -252,7 +252,7 @@ namespace Avalonia.Controls.Documents
internal IInlineHost? InlineHost { get; set; }
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
diff --git a/src/Avalonia.Controls/Expander.cs b/src/Avalonia.Controls/Expander.cs
index 020b162864..3ba99d8a67 100644
--- a/src/Avalonia.Controls/Expander.cs
+++ b/src/Avalonia.Controls/Expander.cs
@@ -106,13 +106,13 @@ namespace Avalonia.Controls
}
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == ExpandDirectionProperty)
{
- UpdatePseudoClasses(change.NewValue.GetValueOrDefault());
+ UpdatePseudoClasses(change.GetNewValue());
}
}
diff --git a/src/Avalonia.Controls/Generators/TreeContainerIndex.cs b/src/Avalonia.Controls/Generators/TreeContainerIndex.cs
index da13416700..eb60fca367 100644
--- a/src/Avalonia.Controls/Generators/TreeContainerIndex.cs
+++ b/src/Avalonia.Controls/Generators/TreeContainerIndex.cs
@@ -15,6 +15,7 @@ namespace Avalonia.Controls.Generators
///
public class TreeContainerIndex
{
+ private readonly Dictionary> _itemToContainerSet = new Dictionary>();
private readonly Dictionary _itemToContainer = new Dictionary();
private readonly Dictionary _containerToItem = new Dictionary();
@@ -45,14 +46,45 @@ namespace Avalonia.Controls.Generators
/// The item container.
public void Add(object item, IControl container)
{
- _itemToContainer.Add(item, container);
+ _itemToContainer[item] = container;
+ if (_itemToContainerSet.TryGetValue(item, out var set))
+ {
+ set.Add(container);
+ }
+ else
+ {
+ _itemToContainerSet.Add(item, new HashSet { container });
+ }
+
_containerToItem.Add(container, item);
Materialized?.Invoke(
- this,
+ this,
new ItemContainerEventArgs(new ItemContainerInfo(container, item, 0)));
}
+ ///
+ /// Removes a container from private collections.
+ ///
+ /// The item container.
+ /// The DataContext object
+ private void RemoveContainer(IControl container, object item)
+ {
+ if (_itemToContainerSet.TryGetValue(item, out var set))
+ {
+ set.Remove(container);
+ if (set.Count == 0)
+ {
+ _itemToContainerSet.Remove(item);
+ _itemToContainer.Remove(item);
+ }
+ else
+ {
+ _itemToContainer[item] = set.First();
+ }
+ }
+ }
+
///
/// Removes a container from the index.
///
@@ -61,10 +93,10 @@ namespace Avalonia.Controls.Generators
{
var item = _containerToItem[container];
_containerToItem.Remove(container);
- _itemToContainer.Remove(item);
+ RemoveContainer(container, item);
Dematerialized?.Invoke(
- this,
+ this,
new ItemContainerEventArgs(new ItemContainerInfo(container, item, 0)));
}
@@ -79,7 +111,7 @@ namespace Avalonia.Controls.Generators
{
var item = _containerToItem[container.ContainerControl];
_containerToItem.Remove(container.ContainerControl);
- _itemToContainer.Remove(item);
+ RemoveContainer(container.ContainerControl, item);
}
Dematerialized?.Invoke(
@@ -97,6 +129,14 @@ namespace Avalonia.Controls.Generators
if (item != null)
{
_itemToContainer.TryGetValue(item, out var result);
+ if (result == null)
+ {
+ _itemToContainerSet.TryGetValue(item, out var set);
+ if (set?.Count > 0)
+ {
+ return set.FirstOrDefault();
+ }
+ }
return result;
}
@@ -113,6 +153,10 @@ namespace Avalonia.Controls.Generators
if (container != null)
{
_containerToItem.TryGetValue(container, out var result);
+ if (result != null)
+ {
+ _itemToContainer[result] = container;
+ }
return result;
}
diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs
index 0cd72dc91c..256160a116 100644
--- a/src/Avalonia.Controls/ItemsControl.cs
+++ b/src/Avalonia.Controls/ItemsControl.cs
@@ -166,7 +166,7 @@ namespace Avalonia.Controls
if (Presenter is IChildIndexProvider innerProvider)
{
innerProvider.ChildIndexChanged += PresenterChildIndexChanged;
- _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs());
+ _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty);
}
}
@@ -341,13 +341,13 @@ namespace Avalonia.Controls
return new ItemsControlAutomationPeer(this);
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == ItemCountProperty)
{
- UpdatePseudoClasses(change.NewValue.GetValueOrDefault());
+ UpdatePseudoClasses(change.GetNewValue());
}
}
@@ -508,7 +508,6 @@ namespace Avalonia.Controls
do
{
result = container.GetControl(direction, c, wrap);
- from = from ?? result;
if (result != null &&
result.Focusable &&
diff --git a/src/Avalonia.Controls/MaskedTextBox.cs b/src/Avalonia.Controls/MaskedTextBox.cs
index ad64c61ebe..933788f9ea 100644
--- a/src/Avalonia.Controls/MaskedTextBox.cs
+++ b/src/Avalonia.Controls/MaskedTextBox.cs
@@ -280,7 +280,7 @@ namespace Avalonia.Controls
base.OnLostFocus(e);
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
void UpdateMaskProvider()
{
diff --git a/src/Avalonia.Controls/MenuItem.cs b/src/Avalonia.Controls/MenuItem.cs
index 955af8888b..619eafb71b 100644
--- a/src/Avalonia.Controls/MenuItem.cs
+++ b/src/Avalonia.Controls/MenuItem.cs
@@ -501,12 +501,15 @@ namespace Avalonia.Controls
return new MenuItemAutomationPeer(this);
}
- protected override void UpdateDataValidation(AvaloniaProperty property, BindingValue value)
+ protected override void UpdateDataValidation(
+ AvaloniaProperty property,
+ BindingValueType state,
+ Exception? error)
{
- base.UpdateDataValidation(property, value);
+ base.UpdateDataValidation(property, state, error);
if (property == CommandProperty)
{
- _commandBindingError = value.Type == BindingValueType.BindingError;
+ _commandBindingError = state == BindingValueType.BindingError;
if (_commandBindingError && _commandCanExecute)
{
_commandCanExecute = false;
diff --git a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
index d6b82a8f8a..2449f4c15c 100644
--- a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
+++ b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
@@ -139,13 +139,13 @@ namespace Avalonia.Controls.Notifications
notificationControl.Close();
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == PositionProperty)
{
- UpdatePseudoClasses(change.NewValue.GetValueOrDefault());
+ UpdatePseudoClasses(change.GetNewValue());
}
}
diff --git a/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs b/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
index fbbaab6182..4d86a0f17c 100644
--- a/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
+++ b/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
@@ -403,12 +403,16 @@ namespace Avalonia.Controls
/// enabled.
///
/// The property.
- /// The new binding value for the property.
- protected override void UpdateDataValidation(AvaloniaProperty property, BindingValue value)
+ /// The current data binding state.
+ /// The current data binding error, if any.
+ protected override void UpdateDataValidation(
+ AvaloniaProperty property,
+ BindingValueType state,
+ Exception? error)
{
if (property == TextProperty || property == ValueProperty)
{
- DataValidationErrors.SetError(this, value.Error);
+ DataValidationErrors.SetError(this, error);
}
}
diff --git a/src/Avalonia.Controls/Panel.cs b/src/Avalonia.Controls/Panel.cs
index 482a7fab84..2230b4b0d2 100644
--- a/src/Avalonia.Controls/Panel.cs
+++ b/src/Avalonia.Controls/Panel.cs
@@ -147,7 +147,7 @@ namespace Avalonia.Controls
throw new NotSupportedException();
}
- _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs());
+ _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty);
InvalidateMeasureOnChildrenChanged();
}
diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs
index 8229f25a07..03159c7a8e 100644
--- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs
@@ -403,7 +403,7 @@ namespace Avalonia.Controls.Presenters
}
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
switch (change.Property.Name)
diff --git a/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs b/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs
index f938c8d437..2821fa8cf0 100644
--- a/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs
+++ b/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs
@@ -158,7 +158,7 @@ namespace Avalonia.Controls.Presenters
{
ItemsChanged(e);
- _childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs());
+ _childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty);
}
}
diff --git a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
index a8bffcc842..c526b7ac49 100644
--- a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
@@ -469,7 +469,7 @@ namespace Avalonia.Controls.Presenters
}
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
if (change.Property == OffsetProperty && !_arranging)
{
diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs
index 9ac4b71a12..db1bbdbc6c 100644
--- a/src/Avalonia.Controls/Presenters/TextPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs
@@ -776,7 +776,7 @@ namespace Avalonia.Controls.Presenters
_caretTimer.Tick -= CaretTimerTick;
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
diff --git a/src/Avalonia.Controls/Primitives/AdornerLayer.cs b/src/Avalonia.Controls/Primitives/AdornerLayer.cs
index 353f12118f..fb047d93df 100644
--- a/src/Avalonia.Controls/Primitives/AdornerLayer.cs
+++ b/src/Avalonia.Controls/Primitives/AdornerLayer.cs
@@ -69,15 +69,18 @@ namespace Avalonia.Controls.Primitives
{
foreach (var child in Children)
{
- var info = child.GetValue(s_adornedElementInfoProperty);
-
- if (info != null && info.Bounds.HasValue)
- {
- child.Measure(info.Bounds.Value.Bounds.Size);
- }
- else
+ if (child is AvaloniaObject ao)
{
- child.Measure(availableSize);
+ var info = ao.GetValue(s_adornedElementInfoProperty);
+
+ if (info != null && info.Bounds.HasValue)
+ {
+ child.Measure(info.Bounds.Value.Bounds.Size);
+ }
+ else
+ {
+ child.Measure(availableSize);
+ }
}
}
@@ -88,19 +91,22 @@ namespace Avalonia.Controls.Primitives
{
foreach (var child in Children)
{
- var info = child.GetValue(s_adornedElementInfoProperty);
- var isClipEnabled = child.GetValue(IsClipEnabledProperty);
-
- if (info != null && info.Bounds.HasValue)
- {
- child.RenderTransform = new MatrixTransform(info.Bounds.Value.Transform);
- child.RenderTransformOrigin = new RelativePoint(new Point(0,0), RelativeUnit.Absolute);
- UpdateClip(child, info.Bounds.Value, isClipEnabled);
- child.Arrange(info.Bounds.Value.Bounds);
- }
- else
+ if (child is AvaloniaObject ao)
{
- child.Arrange(new Rect(finalSize));
+ var info = ao.GetValue(s_adornedElementInfoProperty);
+ var isClipEnabled = ao.GetValue(IsClipEnabledProperty);
+
+ if (info != null && info.Bounds.HasValue)
+ {
+ child.RenderTransform = new MatrixTransform(info.Bounds.Value.Transform);
+ child.RenderTransformOrigin = new RelativePoint(new Point(0, 0), RelativeUnit.Absolute);
+ UpdateClip(child, info.Bounds.Value, isClipEnabled);
+ child.Arrange(info.Bounds.Value.Bounds);
+ }
+ else
+ {
+ child.Arrange(new Rect(finalSize));
+ }
}
}
diff --git a/src/Avalonia.Controls/Primitives/ScrollBar.cs b/src/Avalonia.Controls/Primitives/ScrollBar.cs
index 6a30097fbb..e5c3392faf 100644
--- a/src/Avalonia.Controls/Primitives/ScrollBar.cs
+++ b/src/Avalonia.Controls/Primitives/ScrollBar.cs
@@ -194,13 +194,13 @@ namespace Avalonia.Controls.Primitives
}
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == OrientationProperty)
{
- UpdatePseudoClasses(change.NewValue.GetValueOrDefault());
+ UpdatePseudoClasses(change.GetNewValue());
}
else if (change.Property == AllowAutoHideProperty)
{
diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
index cec02c7ae9..bff6799792 100644
--- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
+++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
@@ -501,12 +501,16 @@ namespace Avalonia.Controls.Primitives
/// enabled.
///
/// The property.
- /// The new binding value for the property.
- protected override void UpdateDataValidation(AvaloniaProperty property, BindingValue value)
+ /// The current data binding state.
+ /// The current data binding error, if any.
+ protected override void UpdateDataValidation(
+ AvaloniaProperty property,
+ BindingValueType state,
+ Exception? error)
{
if (property == SelectedItemProperty)
{
- DataValidationErrors.SetError(this, value.Error);
+ DataValidationErrors.SetError(this, error);
}
}
@@ -533,9 +537,9 @@ namespace Avalonia.Controls.Primitives
bool Match(ItemContainerInfo info)
{
- if (info.ContainerControl.IsSet(TextSearch.TextProperty))
+ if (info.ContainerControl is AvaloniaObject ao && ao.IsSet(TextSearch.TextProperty))
{
- var searchText = info.ContainerControl.GetValue(TextSearch.TextProperty);
+ var searchText = ao.GetValue(TextSearch.TextProperty);
if (searchText?.StartsWith(_textSearchTerm, StringComparison.OrdinalIgnoreCase) == true)
{
@@ -585,7 +589,7 @@ namespace Avalonia.Controls.Primitives
}
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
@@ -595,7 +599,7 @@ namespace Avalonia.Controls.Primitives
}
if (change.Property == ItemsProperty && _updateState is null && _selection is object)
{
- var newValue = change.NewValue.GetValueOrDefault();
+ var newValue = change.GetNewValue();
_selection.Source = newValue;
if (newValue is null)
@@ -605,7 +609,7 @@ namespace Avalonia.Controls.Primitives
}
else if (change.Property == SelectionModeProperty && _selection is object)
{
- var newValue = change.NewValue.GetValueOrDefault();
+ var newValue = change.GetNewValue();
_selection.SingleSelect = !newValue.HasAllFlags(SelectionMode.Multiple);
}
else if (change.Property == WrapSelectionProperty)
diff --git a/src/Avalonia.Controls/Primitives/Track.cs b/src/Avalonia.Controls/Primitives/Track.cs
index f8d6046101..49f0cda982 100644
--- a/src/Avalonia.Controls/Primitives/Track.cs
+++ b/src/Avalonia.Controls/Primitives/Track.cs
@@ -291,13 +291,13 @@ namespace Avalonia.Controls.Primitives
return arrangeSize;
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == OrientationProperty)
{
- UpdatePseudoClasses(change.NewValue.GetValueOrDefault());
+ UpdatePseudoClasses(change.GetNewValue());
}
}
diff --git a/src/Avalonia.Controls/ProgressBar.cs b/src/Avalonia.Controls/ProgressBar.cs
index a4f2cc799a..1075328c67 100644
--- a/src/Avalonia.Controls/ProgressBar.cs
+++ b/src/Avalonia.Controls/ProgressBar.cs
@@ -178,17 +178,17 @@ namespace Avalonia.Controls
return base.ArrangeOverride(finalSize);
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == IsIndeterminateProperty)
{
- UpdatePseudoClasses(change.NewValue.GetValueOrDefault(), null);
+ UpdatePseudoClasses(change.GetNewValue(), null);
}
else if (change.Property == OrientationProperty)
{
- UpdatePseudoClasses(null, change.NewValue.GetValueOrDefault());
+ UpdatePseudoClasses(null, change.GetNewValue());
}
}
diff --git a/src/Avalonia.Controls/RepeatButton.cs b/src/Avalonia.Controls/RepeatButton.cs
index 0415a78721..80f841fa18 100644
--- a/src/Avalonia.Controls/RepeatButton.cs
+++ b/src/Avalonia.Controls/RepeatButton.cs
@@ -70,11 +70,11 @@ namespace Avalonia.Controls
_repeatTimer?.Stop();
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
- if (change.Property == IsPressedProperty && change.NewValue.GetValueOrDefault() == false)
+ if (change.Property == IsPressedProperty && change.GetNewValue() == false)
{
StopTimer();
}
diff --git a/src/Avalonia.Controls/Repeater/ItemsRepeater.cs b/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
index 09c0e58332..3f42d95deb 100644
--- a/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
+++ b/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
@@ -20,7 +20,7 @@ namespace Avalonia.Controls
/// Represents a data-driven collection control that incorporates a flexible layout system,
/// custom views, and virtualization.
///
- public class ItemsRepeater : Panel, IChildIndexProvider, IWeakEventSubscriber
+ public class ItemsRepeater : Panel, IChildIndexProvider
{
///
/// Defines the property.
@@ -60,6 +60,7 @@ namespace Avalonia.Controls
private readonly ViewManager _viewManager;
private readonly ViewportManager _viewportManager;
+ private readonly TargetWeakEventSubscriber _layoutWeakSubscriber;
private IEnumerable? _items;
private VirtualizingLayoutContext? _layoutContext;
private EventHandler? _childIndexChanged;
@@ -74,6 +75,15 @@ namespace Avalonia.Controls
///
public ItemsRepeater()
{
+ _layoutWeakSubscriber = new TargetWeakEventSubscriber(
+ this, static (target, _, ev, _) =>
+ {
+ if (ev == AttachedLayout.ArrangeInvalidatedWeakEvent)
+ target.InvalidateArrange();
+ else if (ev == AttachedLayout.MeasureInvalidatedWeakEvent)
+ target.InvalidateMeasure();
+ });
+
_viewManager = new ViewManager(this);
_viewportManager = new ViewportManager(this);
KeyboardNavigation.SetTabNavigation(this, KeyboardNavigationMode.Once);
@@ -257,10 +267,9 @@ namespace Avalonia.Controls
internal void UnpinElement(IControl element) => _viewManager.UpdatePin(element, false);
- internal static VirtualizationInfo TryGetVirtualizationInfo(IControl element)
+ internal static VirtualizationInfo? TryGetVirtualizationInfo(IControl element)
{
- var value = element.GetValue(VirtualizationInfoProperty);
- return value;
+ return (element as AvaloniaObject)?.GetValue(VirtualizationInfoProperty);
}
internal static VirtualizationInfo CreateAndInitializeVirtualizationInfo(IControl element)
@@ -277,15 +286,20 @@ namespace Avalonia.Controls
internal static VirtualizationInfo GetVirtualizationInfo(IControl element)
{
- var result = element.GetValue(VirtualizationInfoProperty);
-
- if (result == null)
+ if (element is AvaloniaObject ao)
{
- result = new VirtualizationInfo();
- element.SetValue(VirtualizationInfoProperty, result);
+ var result = ao.GetValue(VirtualizationInfoProperty);
+
+ if (result == null)
+ {
+ result = new VirtualizationInfo();
+ ao.SetValue(VirtualizationInfoProperty, result);
+ }
+
+ return result;
}
- return result;
+ throw new NotSupportedException("Custom implementations of IAvaloniaObject not supported.");
}
private protected override void InvalidateMeasureOnChildrenChanged()
@@ -391,11 +405,7 @@ namespace Avalonia.Controls
var newBounds = element.Bounds;
virtInfo.ArrangeBounds = newBounds;
- if (!virtInfo.IsRegisteredAsAnchorCandidate)
- {
- _viewportManager.RegisterScrollAnchorCandidate(element);
- virtInfo.IsRegisteredAsAnchorCandidate = true;
- }
+ _viewportManager.RegisterScrollAnchorCandidate(element, virtInfo);
}
}
@@ -420,12 +430,11 @@ namespace Avalonia.Controls
_viewportManager.ResetScrollers();
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
if (change.Property == ItemsProperty)
{
- var oldEnumerable = change.OldValue.GetValueOrDefault();
- var newEnumerable = change.NewValue.GetValueOrDefault();
+ var (oldEnumerable, newEnumerable) = change.GetOldAndNewValue();
if (oldEnumerable != newEnumerable)
{
@@ -440,23 +449,21 @@ namespace Avalonia.Controls
}
else if (change.Property == ItemTemplateProperty)
{
- OnItemTemplateChanged(
- change.OldValue.GetValueOrDefault(),
- change.NewValue.GetValueOrDefault());
+ var (oldvalue, newValue) = change.GetOldAndNewValue();
+ OnItemTemplateChanged(oldvalue, newValue);
}
else if (change.Property == LayoutProperty)
{
- OnLayoutChanged(
- change.OldValue.GetValueOrDefault(),
- change.NewValue.GetValueOrDefault());
+ var (oldvalue, newValue) = change.GetOldAndNewValue();
+ OnLayoutChanged(oldvalue, newValue);
}
else if (change.Property == HorizontalCacheLengthProperty)
{
- _viewportManager.HorizontalCacheLength = change.NewValue.GetValueOrDefault();
+ _viewportManager.HorizontalCacheLength = change.GetNewValue();
}
else if (change.Property == VerticalCacheLengthProperty)
{
- _viewportManager.VerticalCacheLength = change.NewValue.GetValueOrDefault();
+ _viewportManager.VerticalCacheLength = change.GetNewValue();
}
base.OnPropertyChanged(change);
@@ -480,7 +487,7 @@ namespace Avalonia.Controls
_processingItemsSourceChange.Action == NotifyCollectionChangedAction.Reset);
_viewManager.ClearElement(element, isClearedDueToCollectionChange);
- _viewportManager.OnElementCleared(element);
+ _viewportManager.OnElementCleared(element, GetVirtualizationInfo(element));
}
private int GetElementIndexImpl(IControl element)
@@ -491,7 +498,7 @@ namespace Avalonia.Controls
if (parent == this)
{
var virtInfo = TryGetVirtualizationInfo(element);
- return _viewManager.GetElementIndex(virtInfo);
+ return _viewManager.GetElementIndex(virtInfo!);
}
return -1;
@@ -728,8 +735,8 @@ namespace Avalonia.Controls
{
oldValue.UninitializeForContext(LayoutContext);
- AttachedLayout.MeasureInvalidatedWeakEvent.Unsubscribe(oldValue, this);
- AttachedLayout.ArrangeInvalidatedWeakEvent.Unsubscribe(oldValue, this);
+ AttachedLayout.MeasureInvalidatedWeakEvent.Unsubscribe(oldValue, _layoutWeakSubscriber);
+ AttachedLayout.ArrangeInvalidatedWeakEvent.Unsubscribe(oldValue, _layoutWeakSubscriber);
// Walk through all the elements and make sure they are cleared
foreach (var element in Children)
@@ -747,8 +754,8 @@ namespace Avalonia.Controls
{
newValue.InitializeForContext(LayoutContext);
- AttachedLayout.MeasureInvalidatedWeakEvent.Subscribe(newValue, this);
- AttachedLayout.ArrangeInvalidatedWeakEvent.Subscribe(newValue, this);
+ AttachedLayout.MeasureInvalidatedWeakEvent.Subscribe(newValue, _layoutWeakSubscriber);
+ AttachedLayout.ArrangeInvalidatedWeakEvent.Subscribe(newValue, _layoutWeakSubscriber);
}
bool isVirtualizingLayout = newValue != null && newValue is VirtualizingLayout;
@@ -798,15 +805,7 @@ namespace Avalonia.Controls
{
_viewportManager.OnBringIntoViewRequested(e);
}
-
- void IWeakEventSubscriber.OnEvent(object? sender, WeakEvent ev, EventArgs e)
- {
- if(ev == AttachedLayout.ArrangeInvalidatedWeakEvent)
- InvalidateArrange();
- else if (ev == AttachedLayout.MeasureInvalidatedWeakEvent)
- InvalidateMeasure();
- }
-
+
private VirtualizingLayoutContext GetLayoutContext()
{
if (_layoutContext == null)
diff --git a/src/Avalonia.Controls/Repeater/RecyclePool.cs b/src/Avalonia.Controls/Repeater/RecyclePool.cs
index 9e2da81f99..cf2b40836e 100644
--- a/src/Avalonia.Controls/Repeater/RecyclePool.cs
+++ b/src/Avalonia.Controls/Repeater/RecyclePool.cs
@@ -80,8 +80,8 @@ namespace Avalonia.Controls
return null;
}
- internal string GetReuseKey(IControl element) => element.GetValue(ReuseKeyProperty);
- internal void SetReuseKey(IControl element, string value) => element.SetValue(ReuseKeyProperty, value);
+ internal string GetReuseKey(IControl element) => ((Control)element).GetValue(ReuseKeyProperty);
+ internal void SetReuseKey(IControl element, string value) => ((Control)element).SetValue(ReuseKeyProperty, value);
private IPanel? EnsureOwnerIsPanelOrNull(IControl? owner)
{
diff --git a/src/Avalonia.Controls/Repeater/ViewManager.cs b/src/Avalonia.Controls/Repeater/ViewManager.cs
index b28753b518..12db48a2c2 100644
--- a/src/Avalonia.Controls/Repeater/ViewManager.cs
+++ b/src/Avalonia.Controls/Repeater/ViewManager.cs
@@ -47,7 +47,7 @@ namespace Avalonia.Controls
if (madeAnchor != null)
{
var anchorVirtInfo = ItemsRepeater.TryGetVirtualizationInfo(madeAnchor);
- if (anchorVirtInfo.Index == index)
+ if (anchorVirtInfo!.Index == index)
{
element = madeAnchor;
}
@@ -60,12 +60,12 @@ namespace Avalonia.Controls
var virtInfo = ItemsRepeater.TryGetVirtualizationInfo(element);
if (suppressAutoRecycle)
{
- virtInfo.AutoRecycleCandidate = false;
+ virtInfo!.AutoRecycleCandidate = false;
Logger.TryGet(LogEventLevel.Verbose, "Repeater")?.Log(this, "GetElement: {Index} Not AutoRecycleCandidate:", virtInfo.Index);
}
else
{
- virtInfo.AutoRecycleCandidate = true;
+ virtInfo!.AutoRecycleCandidate = true;
virtInfo.KeepAlive = true;
Logger.TryGet(LogEventLevel.Verbose, "Repeater")?.Log(this, "GetElement: {Index} AutoRecycleCandidate:", virtInfo.Index);
}
diff --git a/src/Avalonia.Controls/Repeater/ViewportManager.cs b/src/Avalonia.Controls/Repeater/ViewportManager.cs
index ec25fcb265..7f03cc575e 100644
--- a/src/Avalonia.Controls/Repeater/ViewportManager.cs
+++ b/src/Avalonia.Controls/Repeater/ViewportManager.cs
@@ -249,9 +249,10 @@ namespace Avalonia.Controls
virtInfo.IsRegisteredAsAnchorCandidate = false;
}
- public void OnElementCleared(IControl element)
+ public void OnElementCleared(IControl element, VirtualizationInfo virtInfo)
{
_scroller?.UnregisterAnchorCandidate(element);
+ virtInfo.IsRegisteredAsAnchorCandidate = false;
}
public void OnOwnerMeasuring()
@@ -358,9 +359,12 @@ namespace Avalonia.Controls
{
foreach (var child in _owner.Children)
{
- if (child != targetChild)
+ var info = ItemsRepeater.GetVirtualizationInfo(child);
+
+ if (child != targetChild && info.IsRegisteredAsAnchorCandidate)
{
_scroller.UnregisterAnchorCandidate(child);
+ info.IsRegisteredAsAnchorCandidate = false;
}
}
}
@@ -377,9 +381,13 @@ namespace Avalonia.Controls
}
}
- public void RegisterScrollAnchorCandidate(IControl element)
+ public void RegisterScrollAnchorCandidate(IControl element, VirtualizationInfo virtInfo)
{
- _scroller?.RegisterAnchorCandidate(element);
+ if (!virtInfo.IsRegisteredAsAnchorCandidate)
+ {
+ _scroller?.RegisterAnchorCandidate(element);
+ virtInfo.IsRegisteredAsAnchorCandidate = true;
+ }
}
private IControl? GetImmediateChildOfRepeater(IControl descendant)
@@ -405,15 +413,18 @@ namespace Avalonia.Controls
_isBringIntoViewInProgress = false;
_makeAnchorElement = null;
+ // Undo the anchor deregistrations done by OnBringIntoViewRequested.
if (_scroller is object)
{
foreach (var child in _owner.Children)
{
var info = ItemsRepeater.GetVirtualizationInfo(child);
- if (info.IsRealized && info.IsHeldByLayout)
+ // The item brought into view is still registered - don't register it more than once.
+ if (info.IsRealized && info.IsHeldByLayout && !info.IsRegisteredAsAnchorCandidate)
{
_scroller.RegisterAnchorCandidate(child);
+ info.IsRegisteredAsAnchorCandidate = true;
}
}
}
@@ -430,7 +441,13 @@ namespace Avalonia.Controls
{
foreach (var child in _owner.Children)
{
- _scroller.UnregisterAnchorCandidate(child);
+ var info = ItemsRepeater.GetVirtualizationInfo(child);
+
+ if (info.IsRegisteredAsAnchorCandidate)
+ {
+ _scroller.UnregisterAnchorCandidate(child);
+ info.IsRegisteredAsAnchorCandidate = false;
+ }
}
_scroller = null;
diff --git a/src/Avalonia.Controls/Slider.cs b/src/Avalonia.Controls/Slider.cs
index f2bd1947d6..64dfce22d4 100644
--- a/src/Avalonia.Controls/Slider.cs
+++ b/src/Avalonia.Controls/Slider.cs
@@ -361,21 +361,24 @@ namespace Avalonia.Controls
Value = IsSnapToTickEnabled ? SnapToTick(finalValue) : finalValue;
}
- protected override void UpdateDataValidation(AvaloniaProperty property, BindingValue value)
+ protected override void UpdateDataValidation(
+ AvaloniaProperty property,
+ BindingValueType state,
+ Exception? error)
{
if (property == ValueProperty)
{
- DataValidationErrors.SetError(this, value.Error);
+ DataValidationErrors.SetError(this, error);
}
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == OrientationProperty)
{
- UpdatePseudoClasses(change.NewValue.GetValueOrDefault());
+ UpdatePseudoClasses(change.GetNewValue());
}
}
diff --git a/src/Avalonia.Controls/SplitButton/SplitButton.cs b/src/Avalonia.Controls/SplitButton/SplitButton.cs
index f2f4e951ae..37cdefd4e5 100644
--- a/src/Avalonia.Controls/SplitButton/SplitButton.cs
+++ b/src/Avalonia.Controls/SplitButton/SplitButton.cs
@@ -276,19 +276,21 @@ namespace Avalonia.Controls
}
///
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
if (e.Property == CommandProperty)
{
if (_isAttachedToLogicalTree)
{
// Must unregister events here while a reference to the old command still exists
- if (e.OldValue.GetValueOrDefault() is ICommand oldCommand)
+ var (oldValue, newValue) = e.GetOldAndNewValue();
+
+ if (oldValue is ICommand oldCommand)
{
oldCommand.CanExecuteChanged -= CanExecuteChanged;
}
- if (e.NewValue.GetValueOrDefault() is ICommand newCommand)
+ if (newValue is ICommand newCommand)
{
newCommand.CanExecuteChanged += CanExecuteChanged;
}
@@ -302,8 +304,7 @@ namespace Avalonia.Controls
}
else if (e.Property == FlyoutProperty)
{
- var oldFlyout = e.OldValue.GetValueOrDefault() as FlyoutBase;
- var newFlyout = e.NewValue.GetValueOrDefault() as FlyoutBase;
+ var (oldFlyout, newFlyout) = e.GetOldAndNewValue();
// If flyout is changed while one is already open, make sure we
// close the old one first
diff --git a/src/Avalonia.Controls/SplitButton/ToggleSplitButton.cs b/src/Avalonia.Controls/SplitButton/ToggleSplitButton.cs
index 879c1aa6e1..cd34f8060a 100644
--- a/src/Avalonia.Controls/SplitButton/ToggleSplitButton.cs
+++ b/src/Avalonia.Controls/SplitButton/ToggleSplitButton.cs
@@ -90,7 +90,7 @@ namespace Avalonia.Controls
////////////////////////////////////////////////////////////////////////
///
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
if (e.Property == IsCheckedProperty)
{
diff --git a/src/Avalonia.Controls/StackPanel.cs b/src/Avalonia.Controls/StackPanel.cs
index feb425a9c3..50c48d2bb0 100644
--- a/src/Avalonia.Controls/StackPanel.cs
+++ b/src/Avalonia.Controls/StackPanel.cs
@@ -123,7 +123,7 @@ namespace Avalonia.Controls
index = Children.Count - 1;
break;
case NavigationDirection.Next:
- if (index != -1) ++index;
+ ++index;
break;
case NavigationDirection.Previous:
if (index != -1) --index;
diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs
index 3bcb74eee6..c04a62008b 100644
--- a/src/Avalonia.Controls/TextBlock.cs
+++ b/src/Avalonia.Controls/TextBlock.cs
@@ -644,7 +644,7 @@ namespace Avalonia.Controls
private static bool IsValidLineHeight(double lineHeight) => double.IsNaN(lineHeight) || lineHeight > 0;
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index 947830b217..0be58e7fcc 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -585,7 +585,7 @@ namespace Avalonia.Controls
_imClient.SetPresenter(null, null);
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
@@ -594,7 +594,7 @@ namespace Avalonia.Controls
UpdatePseudoclasses();
UpdateCommandStates();
}
- else if (change.Property == IsUndoEnabledProperty && change.NewValue.GetValueOrDefault() == false)
+ else if (change.Property == IsUndoEnabledProperty && change.GetNewValue() == false)
{
// from docs at
// https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.primitives.textboxbase.isundoenabled:
@@ -1262,11 +1262,14 @@ namespace Avalonia.Controls
return new TextBoxAutomationPeer(this);
}
- protected override void UpdateDataValidation(AvaloniaProperty property, BindingValue value)
+ protected override void UpdateDataValidation(
+ AvaloniaProperty property,
+ BindingValueType state,
+ Exception? error)
{
if (property == TextProperty)
{
- DataValidationErrors.SetError(this, value.Error);
+ DataValidationErrors.SetError(this, error);
}
}
diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs
index 55202dd20d..57fb82485c 100644
--- a/src/Avalonia.Controls/TopLevel.cs
+++ b/src/Avalonia.Controls/TopLevel.cs
@@ -15,7 +15,6 @@ using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.Utilities;
using Avalonia.VisualTree;
-using JetBrains.Annotations;
namespace Avalonia.Controls
{
@@ -35,8 +34,7 @@ namespace Avalonia.Controls
ICloseable,
IStyleHost,
ILogicalRoot,
- ITextInputMethodRoot,
- IWeakEventSubscriber
+ ITextInputMethodRoot
{
///
/// Defines the property.
@@ -87,11 +85,14 @@ namespace Avalonia.Controls
private readonly IKeyboardNavigationHandler? _keyboardNavigationHandler;
private readonly IPlatformRenderInterface? _renderInterface;
private readonly IGlobalStyles? _globalStyles;
+ private readonly PointerOverPreProcessor? _pointerOverPreProcessor;
+ private readonly IDisposable? _pointerOverPreProcessorSubscription;
private Size _clientSize;
private Size? _frameSize;
private WindowTransparencyLevel _actualTransparencyLevel;
private ILayoutManager? _layoutManager;
private Border? _transparencyFallbackBorder;
+ private TargetWeakEventSubscriber? _resourcesChangesSubscriber;
///
/// Initializes static members of the class.
@@ -191,10 +192,19 @@ namespace Avalonia.Controls
if (((IStyleHost)this).StylingParent is IResourceHost applicationResources)
{
- ResourcesChangedWeakEvent.Subscribe(applicationResources, this);
+ _resourcesChangesSubscriber = new TargetWeakEventSubscriber(
+ this, static (target, _, _, e) =>
+ {
+ ((ILogical)target).NotifyResourcesChanged(e);
+ });
+
+ ResourcesChangedWeakEvent.Subscribe(applicationResources, _resourcesChangesSubscriber);
}
impl.LostFocus += PlatformImpl_LostFocus;
+
+ _pointerOverPreProcessor = new PointerOverPreProcessor(this);
+ _pointerOverPreProcessorSubscription = _inputManager?.PreProcess.Subscribe(_pointerOverPreProcessor);
}
///
@@ -283,9 +293,7 @@ namespace Avalonia.Controls
///
IKeyboardNavigationHandler IInputRoot.KeyboardNavigationHandler => _keyboardNavigationHandler!;
- ///
- /// Gets or sets the input element that the pointer is currently over.
- ///
+ ///
IInputElement? IInputRoot.PointerOverElement
{
get { return GetValue(PointerOverElementProperty); }
@@ -295,11 +303,6 @@ namespace Avalonia.Controls
///
IMouseDevice? IInputRoot.MouseDevice => PlatformImpl?.MouseDevice;
- void IWeakEventSubscriber.OnEvent(object? sender, WeakEvent ev, ResourcesChangedEventArgs e)
- {
- ((ILogical)this).NotifyResourcesChanged(e);
- }
-
///
/// Gets or sets a value indicating whether access keys are shown in the window.
///
@@ -378,10 +381,12 @@ namespace Avalonia.Controls
Renderer?.Dispose();
Renderer = null!;
-
- (this as IInputRoot).MouseDevice?.TopLevelClosed(this);
+
+ _pointerOverPreProcessor?.OnCompleted();
+ _pointerOverPreProcessorSubscription?.Dispose();
+
PlatformImpl = null;
-
+
var logicalArgs = new LogicalTreeAttachmentEventArgs(this, this, null);
((ILogical)this).NotifyDetachedFromLogicalTree(logicalArgs);
@@ -515,12 +520,17 @@ namespace Avalonia.Controls
/// The event args.
private void HandleInput(RawInputEventArgs e)
{
+ if (e is RawPointerEventArgs pointerArgs)
+ {
+ pointerArgs.InputHitTestResult = this.InputHitTest(pointerArgs.Position);
+ }
+
_inputManager?.ProcessInput(e);
}
private void SceneInvalidated(object? sender, SceneInvalidatedEventArgs e)
{
- (this as IInputRoot).MouseDevice?.SceneInvalidated(this, e.DirtyRect);
+ _pointerOverPreProcessor?.SceneInvalidated(e.DirtyRect);
}
void PlatformImpl_LostFocus()
diff --git a/src/Avalonia.Controls/TransitioningContentControl.cs b/src/Avalonia.Controls/TransitioningContentControl.cs
index cb0d229110..451e234653 100644
--- a/src/Avalonia.Controls/TransitioningContentControl.cs
+++ b/src/Avalonia.Controls/TransitioningContentControl.cs
@@ -61,7 +61,7 @@ public class TransitioningContentControl : ContentControl
_lastTransitionCts?.Cancel();
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
diff --git a/src/Avalonia.Controls/TrayIcon.cs b/src/Avalonia.Controls/TrayIcon.cs
index b8ab48a2b7..2ccb03e447 100644
--- a/src/Avalonia.Controls/TrayIcon.cs
+++ b/src/Avalonia.Controls/TrayIcon.cs
@@ -206,7 +206,7 @@ namespace Avalonia.Controls
}
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
@@ -216,15 +216,15 @@ namespace Avalonia.Controls
}
else if (change.Property == IsVisibleProperty)
{
- _impl?.SetIsVisible(change.NewValue.GetValueOrDefault());
+ _impl?.SetIsVisible(change.GetNewValue());
}
else if (change.Property == ToolTipTextProperty)
{
- _impl?.SetToolTipText(change.NewValue.GetValueOrDefault());
+ _impl?.SetToolTipText(change.GetNewValue());
}
else if (change.Property == MenuProperty)
{
- _impl?.MenuExporter?.SetNativeMenu(change.NewValue.GetValueOrDefault());
+ _impl?.MenuExporter?.SetNativeMenu(change.GetNewValue());
}
}
diff --git a/src/Avalonia.Controls/TreeView.cs b/src/Avalonia.Controls/TreeView.cs
index 1d806913dd..b2a188a2ea 100644
--- a/src/Avalonia.Controls/TreeView.cs
+++ b/src/Avalonia.Controls/TreeView.cs
@@ -401,7 +401,7 @@ namespace Avalonia.Controls
protected virtual ITreeItemContainerGenerator CreateTreeItemContainerGenerator() =>
CreateTreeItemContainerGenerator();
- protected virtual ITreeItemContainerGenerator CreateTreeItemContainerGenerator() where TVItem: TreeViewItem, new()
+ protected ITreeItemContainerGenerator CreateTreeItemContainerGenerator() where TVItem: TreeViewItem, new()
{
return new TreeItemContainerGenerator(
this,
diff --git a/src/Avalonia.Controls/TreeViewItem.cs b/src/Avalonia.Controls/TreeViewItem.cs
index a0a3c09942..490b0b3ce3 100644
--- a/src/Avalonia.Controls/TreeViewItem.cs
+++ b/src/Avalonia.Controls/TreeViewItem.cs
@@ -96,7 +96,7 @@ namespace Avalonia.Controls
protected override IItemContainerGenerator CreateItemContainerGenerator() => CreateTreeItemContainerGenerator();
///
- protected virtual ITreeItemContainerGenerator CreateTreeItemContainerGenerator()
+ protected ITreeItemContainerGenerator CreateTreeItemContainerGenerator()
where TVItem: TreeViewItem, new()
{
return new TreeItemContainerGenerator(
diff --git a/src/Avalonia.Controls/Viewbox.cs b/src/Avalonia.Controls/Viewbox.cs
index 50b9560cac..dd74d549bd 100644
--- a/src/Avalonia.Controls/Viewbox.cs
+++ b/src/Avalonia.Controls/Viewbox.cs
@@ -82,13 +82,13 @@ namespace Avalonia.Controls
set => _containerVisual.RenderTransform = value;
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == ChildProperty)
{
- _containerVisual.Child = change.NewValue.GetValueOrDefault();
+ _containerVisual.Child = change.GetNewValue();
InvalidateMeasure();
}
}
diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs
index 993b3aaa1b..a5f99918b2 100644
--- a/src/Avalonia.Controls/Window.cs
+++ b/src/Avalonia.Controls/Window.cs
@@ -1019,16 +1019,16 @@ namespace Avalonia.Controls
///
protected virtual void OnClosing(CancelEventArgs e) => Closing?.Invoke(this, e);
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == SystemDecorationsProperty)
{
- var typedNewValue = change.NewValue.GetValueOrDefault();
+ var (typedOldValue, typedNewValue) = change.GetOldAndNewValue();
PlatformImpl?.SetSystemDecorations(typedNewValue);
- var o = change.OldValue.GetValueOrDefault() == SystemDecorations.Full;
+ var o = typedOldValue == SystemDecorations.Full;
var n = typedNewValue == SystemDecorations.Full;
if (o != n)
diff --git a/src/Avalonia.DesignerSupport/Remote/HtmlTransport/HtmlTransport.cs b/src/Avalonia.DesignerSupport/Remote/HtmlTransport/HtmlTransport.cs
index 6b1934ed06..f100be5d5b 100644
--- a/src/Avalonia.DesignerSupport/Remote/HtmlTransport/HtmlTransport.cs
+++ b/src/Avalonia.DesignerSupport/Remote/HtmlTransport/HtmlTransport.cs
@@ -10,6 +10,7 @@ using System.Threading;
using System.Threading.Tasks;
using Avalonia.Remote.Protocol;
using Avalonia.Remote.Protocol.Viewport;
+using Avalonia.Utilities;
using InputProtocol = Avalonia.Remote.Protocol.Input;
namespace Avalonia.DesignerSupport.Remote.HtmlTransport
@@ -320,15 +321,13 @@ namespace Avalonia.DesignerSupport.Remote.HtmlTransport
? null
: modifiersText
.Split(',')
- .Select(x => (InputProtocol.InputModifiers)Enum.Parse(
- typeof(InputProtocol.InputModifiers), x, true))
+ .Select(x => EnumHelper.Parse(x, true))
.ToArray();
private static InputProtocol.MouseButton ParseMouseButton(string buttonText) =>
string.IsNullOrWhiteSpace(buttonText)
? InputProtocol.MouseButton.None
- : (InputProtocol.MouseButton)Enum.Parse(
- typeof(InputProtocol.MouseButton), buttonText, true);
+ : EnumHelper.Parse(buttonText, true);
private static double ParseDouble(string text) =>
double.Parse(text, NumberStyles.Float, CultureInfo.InvariantCulture);
diff --git a/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/package-lock.json b/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/package-lock.json
index 08ede477c3..403bb5a59a 100644
--- a/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/package-lock.json
+++ b/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/package-lock.json
@@ -377,9 +377,9 @@
"dev": true
},
"async": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
- "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
+ "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
"dev": true,
"requires": {
"lodash": "^4.17.14"
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs b/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs
index cb98fb70f3..ec7e91c8be 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs
@@ -92,7 +92,7 @@ namespace Avalonia.Diagnostics.Controls
set => SetValue(HighlightProperty, value);
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
@@ -102,7 +102,7 @@ namespace Avalonia.Diagnostics.Controls
{
_isUpdatingThickness = true;
- var value = change.NewValue.GetValueOrDefault();
+ var value = change.GetNewValue();
Left = value.Left;
Top = value.Top;
diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs
index 4dc0c34c0a..0c0c005122 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs
@@ -110,7 +110,7 @@ namespace Avalonia.Diagnostics.ViewModels
private void UpdateSizeConstraints()
{
- if (_control is IAvaloniaObject ao)
+ if (_control is AvaloniaObject ao)
{
string? CreateConstraintInfo(StyledProperty minProperty, StyledProperty maxProperty)
{
@@ -191,7 +191,7 @@ namespace Avalonia.Diagnostics.ViewModels
}
else
{
- if (_control is IAvaloniaObject ao)
+ if (_control is AvaloniaObject ao)
{
if (e.Property == Layoutable.MarginProperty)
{
diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/MainViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/MainViewModel.cs
index e08c5bc8dd..9e8a5d8d9b 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/MainViewModel.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/MainViewModel.cs
@@ -7,7 +7,6 @@ using Avalonia.Diagnostics.Models;
using Avalonia.Input;
using Avalonia.Metadata;
using Avalonia.Threading;
-using System.Reactive.Linq;
using System.Linq;
namespace Avalonia.Diagnostics.ViewModels
@@ -59,8 +58,8 @@ namespace Avalonia.Diagnostics.ViewModels
.Subscribe(e =>
{
PointerOverRoot = e.Root;
- PointerOverElement = e.Root.GetInputElementsAt(e.Position).FirstOrDefault();
- });
+ PointerOverElement = e.Root.InputHitTest(e.Position);
+ });
#nullable restore
}
Console = new ConsoleViewModel(UpdateConsoleContext);
@@ -163,8 +162,7 @@ namespace Avalonia.Diagnostics.ViewModels
}
catch { }
},
- TimeSpan.FromMilliseconds(0),
- DispatcherPriority.ApplicationIdle);
+ TimeSpan.FromMilliseconds(0));
}
RaiseAndSetIfChanged(ref _content, value);
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml.cs b/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml.cs
index 2553ae90ce..58807b489e 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml.cs
@@ -36,6 +36,7 @@ namespace Avalonia.Diagnostics.Views
new Border { BorderBrush = new SolidColorBrush(Colors.Yellow, 0.5) }
},
};
+ AdornerLayer.SetIsClipEnabled(_adorner, false);
}
protected void AddAdorner(object? sender, PointerEventArgs e)
diff --git a/src/Avalonia.PlatformSupport/AssetLoader.cs b/src/Avalonia.PlatformSupport/AssetLoader.cs
index fb03ec2f6e..0e33c3d4c7 100644
--- a/src/Avalonia.PlatformSupport/AssetLoader.cs
+++ b/src/Avalonia.PlatformSupport/AssetLoader.cs
@@ -14,14 +14,14 @@ namespace Avalonia.PlatformSupport
///
public class AssetLoader : IAssetLoader
{
- private static AssemblyDescriptorResolver s_assemblyDescriptorResolver = new();
+ private static IAssemblyDescriptorResolver s_assemblyDescriptorResolver = new AssemblyDescriptorResolver();
private AssemblyDescriptor? _defaultResmAssembly;
///
/// Introduced for tests.
///
- internal static void SetAssemblyDescriptorResolver(AssemblyDescriptorResolver resolver) =>
+ internal static void SetAssemblyDescriptorResolver(IAssemblyDescriptorResolver resolver) =>
s_assemblyDescriptorResolver = resolver;
///
@@ -182,13 +182,13 @@ namespace Avalonia.PlatformSupport
throw new ArgumentException($"Unsupported url type: " + uri.Scheme, nameof(uri));
}
- private (AssemblyDescriptor asm, string path) GetResAsmAndPath(Uri uri)
+ private (IAssemblyDescriptor asm, string path) GetResAsmAndPath(Uri uri)
{
var asm = s_assemblyDescriptorResolver.GetAssembly(uri.Authority);
return (asm, uri.GetUnescapeAbsolutePath());
}
- private AssemblyDescriptor? GetAssembly(Uri? uri)
+ private IAssemblyDescriptor? GetAssembly(Uri? uri)
{
if (uri != null)
{
diff --git a/src/Avalonia.PlatformSupport/Avalonia.PlatformSupport.csproj b/src/Avalonia.PlatformSupport/Avalonia.PlatformSupport.csproj
index 420ac0796c..5336f1e630 100644
--- a/src/Avalonia.PlatformSupport/Avalonia.PlatformSupport.csproj
+++ b/src/Avalonia.PlatformSupport/Avalonia.PlatformSupport.csproj
@@ -19,6 +19,6 @@
-
+
diff --git a/src/Avalonia.PlatformSupport/Internal/AssemblyDescriptor.cs b/src/Avalonia.PlatformSupport/Internal/AssemblyDescriptor.cs
index a3de7f2b8a..64ffec8482 100644
--- a/src/Avalonia.PlatformSupport/Internal/AssemblyDescriptor.cs
+++ b/src/Avalonia.PlatformSupport/Internal/AssemblyDescriptor.cs
@@ -6,7 +6,15 @@ using Avalonia.Utilities;
namespace Avalonia.PlatformSupport.Internal;
-internal class AssemblyDescriptor
+internal interface IAssemblyDescriptor
+{
+ Assembly Assembly { get; }
+ Dictionary? Resources { get; }
+ Dictionary? AvaloniaResources { get; }
+ string? Name { get; }
+}
+
+internal class AssemblyDescriptor : IAssemblyDescriptor
{
public AssemblyDescriptor(Assembly assembly)
{
diff --git a/src/Avalonia.PlatformSupport/Internal/AssemblyDescriptorResolver.cs b/src/Avalonia.PlatformSupport/Internal/AssemblyDescriptorResolver.cs
index a78051a9c4..28ae35d57d 100644
--- a/src/Avalonia.PlatformSupport/Internal/AssemblyDescriptorResolver.cs
+++ b/src/Avalonia.PlatformSupport/Internal/AssemblyDescriptorResolver.cs
@@ -5,11 +5,16 @@ using System.Reflection;
namespace Avalonia.PlatformSupport.Internal;
-internal class AssemblyDescriptorResolver
+internal interface IAssemblyDescriptorResolver
{
- private readonly Dictionary _assemblyNameCache = new();
+ IAssemblyDescriptor GetAssembly(string name);
+}
+
+internal class AssemblyDescriptorResolver: IAssemblyDescriptorResolver
+{
+ private readonly Dictionary _assemblyNameCache = new();
- public AssemblyDescriptor GetAssembly(string name)
+ public IAssemblyDescriptor GetAssembly(string name)
{
if (name == null)
throw new ArgumentNullException(nameof(name));
diff --git a/src/Avalonia.SourceGenerator/Avalonia.SourceGenerator.csproj b/src/Avalonia.SourceGenerator/Avalonia.SourceGenerator.csproj
new file mode 100644
index 0000000000..97e58f8a64
--- /dev/null
+++ b/src/Avalonia.SourceGenerator/Avalonia.SourceGenerator.csproj
@@ -0,0 +1,17 @@
+
+
+
+ netstandard2.0
+ enable
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
diff --git a/src/Avalonia.SourceGenerator/IsExternalInit.cs b/src/Avalonia.SourceGenerator/IsExternalInit.cs
new file mode 100644
index 0000000000..c6ddf762ad
--- /dev/null
+++ b/src/Avalonia.SourceGenerator/IsExternalInit.cs
@@ -0,0 +1,14 @@
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+
+namespace System.Runtime.CompilerServices
+{
+ ///
+ /// Reserved to be used by the compiler for tracking metadata.
+ /// This class should not be used by developers in source code.
+ ///
+ [ExcludeFromCodeCoverage, DebuggerNonUserCode]
+ internal static class IsExternalInit
+ {
+ }
+}
diff --git a/src/Avalonia.SourceGenerator/SubtypesFactoryGenerator.cs b/src/Avalonia.SourceGenerator/SubtypesFactoryGenerator.cs
new file mode 100644
index 0000000000..4fc9397e7a
--- /dev/null
+++ b/src/Avalonia.SourceGenerator/SubtypesFactoryGenerator.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Threading;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace Avalonia.SourceGenerator
+{
+ [Generator(LanguageNames.CSharp)]
+ public class SubtypesFactoryGenerator : IIncrementalGenerator
+ {
+ private record struct MethodTarget(IMethodSymbol Method, string MethodDecl, ITypeSymbol BaseType, string Namespace);
+ private static readonly string s_attributeName = typeof(SubtypesFactoryAttribute).FullName;
+
+ private static bool IsSubtypeOf(ITypeSymbol type, ITypeSymbol baseType)
+ {
+ return type.BaseType is not null && (SymbolEqualityComparer.Default.Equals(type.BaseType, baseType) || IsSubtypeOf(type.BaseType, baseType));
+ }
+
+ private static void GenerateSubTypes(SourceProductionContext context, MethodTarget methodTarget, ImmutableArray types)
+ {
+ var (method, methodDecl, baseType, @namespace) = methodTarget;
+ var candidateTypes = types.Where(i => IsSubtypeOf(i, baseType)).Where(i => $"{i.ContainingNamespace}.".StartsWith($"{@namespace}.")).ToArray();
+ var type = method.ContainingType;
+ var isGeneric = type.TypeParameters.Length > 0;
+ var isClass = type.TypeKind == TypeKind.Class;
+
+ var typeDecl = $"partial {(isClass ? "class" : "struct")} {type.Name}{(isGeneric ? $"<{string.Join(", ", type.TypeParameters)}>" : "")}";
+ var source = $@"using System;
+using System.Collections.Generic;
+
+namespace {method.ContainingNamespace}
+{{
+ {typeDecl}
+ {{
+ {methodDecl}
+ {{
+ var hasMatch = false;
+ (hasMatch, {method.Parameters[1].Name}) = {method.Parameters[0].Name} switch
+ {{
+{string.Join("\n", candidateTypes.Select(i => $" \"{i.Name}\" => (true, ({method.Parameters[1].Type})new {i}()),"))}
+ _ => (false, default({method.Parameters[1].Type}))
+ }};
+
+ return hasMatch;
+ }}
+ }}
+}}";
+
+ context.AddSource($"{type}.{method.MetadataName}.gen.cs", source);
+ }
+
+ private static MethodTarget? PopulateMethodTargets(GeneratorSyntaxContext context, CancellationToken token)
+ {
+ token.ThrowIfCancellationRequested();
+ if (context.Node is MethodDeclarationSyntax method)
+ {
+ var attributes = method.AttributeLists.SelectMany(i => i.Attributes);
+ var semanticModel = context.SemanticModel;
+ foreach (var attribute in attributes)
+ {
+ var attributeTypeInfo = semanticModel.GetTypeInfo(attribute);
+ if (attributeTypeInfo.Type is null ||
+ attributeTypeInfo.Type.ToString() != s_attributeName ||
+ attribute.ArgumentList is null)
+ {
+ continue;
+ }
+
+ var arguments = attribute.ArgumentList.Arguments;
+ if (arguments.Count != 2)
+ {
+ continue;
+ }
+
+ if (arguments[0].Expression is not TypeOfExpressionSyntax typeOfExpr ||
+ arguments[1].Expression is not LiteralExpressionSyntax and not IdentifierNameSyntax)
+ {
+ continue;
+ }
+
+ var type = semanticModel.GetTypeInfo(typeOfExpr.Type);
+ var ns = semanticModel.GetConstantValue(arguments[1].Expression);
+ var methodDeclInfo = semanticModel.GetDeclaredSymbol(method);
+
+ if (type.Type is not ITypeSymbol baseType ||
+ ns.HasValue is false ||
+ ns.Value is not string nsValue ||
+ methodDeclInfo is not IMethodSymbol methodSymbol ||
+ methodSymbol.Parameters.Length != 2 ||
+ methodSymbol.Parameters[1].RefKind != RefKind.Out)
+ {
+ continue;
+ }
+
+ var parameters = new SeparatedSyntaxList().AddRange(method.ParameterList.Parameters.Select(i => i.WithAttributeLists(new SyntaxList())));
+ var methodDecl = method
+ .WithAttributeLists(new SyntaxList())
+ .WithParameterList(method.ParameterList.WithParameters(parameters))
+ .WithBody(null)
+ .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.None))
+ .WithoutTrivia().ToString();
+
+ return new MethodTarget(methodSymbol, methodDecl, baseType, nsValue);
+ }
+ }
+
+ return null;
+ }
+
+ public void Initialize(IncrementalGeneratorInitializationContext context)
+ {
+ var typesProvider = context.SyntaxProvider.CreateSyntaxProvider(
+ static (syntaxNode, token) =>
+ {
+ token.ThrowIfCancellationRequested();
+ return syntaxNode is ClassDeclarationSyntax or StructDeclarationSyntax;
+ },
+ static (syntaxContext, token) =>
+ {
+ token.ThrowIfCancellationRequested();
+ return syntaxContext.Node is ClassDeclarationSyntax or StructDeclarationSyntax &&
+ syntaxContext.SemanticModel.GetDeclaredSymbol(syntaxContext.Node) is ITypeSymbol typeSymbol
+ ? typeSymbol : null;
+ })
+ .SelectMany((type, token) =>
+ {
+ token.ThrowIfCancellationRequested();
+ return type is null ? Array.Empty() : new ITypeSymbol[] { type };
+ });
+
+ var methodsProvider = context.SyntaxProvider.CreateSyntaxProvider(
+ static (syntaxNode, token) =>
+ {
+ token.ThrowIfCancellationRequested();
+ return syntaxNode is MethodDeclarationSyntax { AttributeLists.Count: > 0 };
+ }, PopulateMethodTargets)
+ .SelectMany((method, token) =>
+ {
+ token.ThrowIfCancellationRequested();
+ return method is null ? Array.Empty() : new MethodTarget[] { method.Value };
+ });
+
+ var generateContext = methodsProvider.Combine(typesProvider.Collect());
+
+ context.RegisterSourceOutput(generateContext, static (sourceContext, source) =>
+ {
+ sourceContext.CancellationToken.ThrowIfCancellationRequested();
+ GenerateSubTypes(sourceContext, source.Left, source.Right);
+ });
+ }
+ }
+}
diff --git a/src/Avalonia.Themes.Default/Controls/ScrollViewer.xaml b/src/Avalonia.Themes.Default/Controls/ScrollViewer.xaml
index b357446bfa..aab1b76259 100644
--- a/src/Avalonia.Themes.Default/Controls/ScrollViewer.xaml
+++ b/src/Avalonia.Themes.Default/Controls/ScrollViewer.xaml
@@ -13,7 +13,7 @@
CanVerticallyScroll="{TemplateBinding CanVerticallyScroll}"
Content="{TemplateBinding Content}"
Extent="{TemplateBinding Extent, Mode=TwoWay}"
- Margin="{TemplateBinding Padding}"
+ Padding="{TemplateBinding Padding}"
Offset="{TemplateBinding Offset, Mode=TwoWay}"
Viewport="{TemplateBinding Viewport, Mode=TwoWay}"
IsScrollChainingEnabled="{TemplateBinding IsScrollChainingEnabled}">
diff --git a/src/Avalonia.Themes.Default/SimpleTheme.cs b/src/Avalonia.Themes.Default/SimpleTheme.cs
index 1d9f2d5f9d..6929660757 100644
--- a/src/Avalonia.Themes.Default/SimpleTheme.cs
+++ b/src/Avalonia.Themes.Default/SimpleTheme.cs
@@ -116,7 +116,7 @@ namespace Avalonia.Themes.Default
return false;
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == ModeProperty)
diff --git a/src/Avalonia.Themes.Fluent/Controls/ScrollViewer.xaml b/src/Avalonia.Themes.Fluent/Controls/ScrollViewer.xaml
index 53a1b721d1..b7addcb61e 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ScrollViewer.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ScrollViewer.xaml
@@ -32,7 +32,7 @@
CanVerticallyScroll="{TemplateBinding CanVerticallyScroll}"
Content="{TemplateBinding Content}"
Extent="{TemplateBinding Extent, Mode=TwoWay}"
- Margin="{TemplateBinding Padding}"
+ Padding="{TemplateBinding Padding}"
Offset="{TemplateBinding Offset, Mode=TwoWay}"
Viewport="{TemplateBinding Viewport, Mode=TwoWay}"
IsScrollChainingEnabled="{TemplateBinding IsScrollChainingEnabled}">
diff --git a/src/Avalonia.Themes.Fluent/FluentTheme.cs b/src/Avalonia.Themes.Fluent/FluentTheme.cs
index d1136d44a4..f6b47a5466 100644
--- a/src/Avalonia.Themes.Fluent/FluentTheme.cs
+++ b/src/Avalonia.Themes.Fluent/FluentTheme.cs
@@ -78,7 +78,7 @@ namespace Avalonia.Themes.Fluent
set => SetValue(DensityStyleProperty, value);
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == ModeProperty)
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
index 88529ae3a0..d907bcbef9 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
@@ -160,6 +160,29 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return true;
}
+ if (type.Equals(types.RelativePoint))
+ {
+ try
+ {
+ var relativePoint = RelativePoint.Parse(text);
+
+ var relativePointTypeRef = new XamlAstClrTypeReference(node, types.RelativePoint, false);
+
+ result = new XamlAstNewClrObjectNode(node, relativePointTypeRef, types.RelativePointFullConstructor, new List
+ {
+ new XamlConstantNode(node, types.XamlIlTypes.Double, relativePoint.Point.X),
+ new XamlConstantNode(node, types.XamlIlTypes.Double, relativePoint.Point.Y),
+ new XamlConstantNode(node, types.RelativeUnit, (int) relativePoint.Unit),
+ });
+
+ return true;
+ }
+ catch
+ {
+ throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a relative point", node);
+ }
+ }
+
if (type.Equals(types.GridLength))
{
try
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
index 99072ace02..5da40035d2 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
@@ -71,6 +71,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlConstructor MatrixFullConstructor { get; }
public IXamlType CornerRadius { get; }
public IXamlConstructor CornerRadiusFullConstructor { get; }
+ public IXamlType RelativeUnit { get; }
+ public IXamlType RelativePoint { get; }
+ public IXamlConstructor RelativePointFullConstructor { get; }
public IXamlType GridLength { get; }
public IXamlConstructor GridLengthConstructorValueType { get; }
public IXamlType Color { get; }
@@ -135,7 +138,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
NameScopeSetNameScope = NameScope.GetMethod(new FindMethodMethodSignature("SetNameScope",
XamlIlTypes.Void, StyledElement, INameScope)
{ IsStatic = true });
- AvaloniaObjectSetValueMethod = AvaloniaObject.FindMethod("SetValue", XamlIlTypes.Void,
+ AvaloniaObjectSetValueMethod = AvaloniaObject.FindMethod("SetValue", IDisposable,
false, AvaloniaProperty, XamlIlTypes.Object, BindingPriority);
IPropertyInfo = cfg.TypeSystem.GetType("Avalonia.Data.Core.IPropertyInfo");
ClrPropertyInfo = cfg.TypeSystem.GetType("Avalonia.Data.Core.ClrPropertyInfo");
@@ -175,6 +178,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
(Matrix, MatrixFullConstructor) = GetNumericTypeInfo("Avalonia.Matrix", XamlIlTypes.Double, 6);
(CornerRadius, CornerRadiusFullConstructor) = GetNumericTypeInfo("Avalonia.CornerRadius", XamlIlTypes.Double, 4);
+ RelativeUnit = cfg.TypeSystem.GetType("Avalonia.RelativeUnit");
+ RelativePoint = cfg.TypeSystem.GetType("Avalonia.RelativePoint");
+ RelativePointFullConstructor = RelativePoint.GetConstructor(new List { XamlIlTypes.Double, XamlIlTypes.Double, RelativeUnit });
+
GridLength = cfg.TypeSystem.GetType("Avalonia.Controls.GridLength");
GridLengthConstructorValueType = GridLength.GetConstructor(new List { XamlIlTypes.Double, cfg.TypeSystem.GetType("Avalonia.Controls.GridUnitType") });
Color = cfg.TypeSystem.GetType("Avalonia.Media.Color");
diff --git a/src/Shared/SourceGeneratorAttributes.cs b/src/Shared/SourceGeneratorAttributes.cs
new file mode 100644
index 0000000000..fdb5977d23
--- /dev/null
+++ b/src/Shared/SourceGeneratorAttributes.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Avalonia.SourceGenerator
+{
+ [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
+ internal sealed class SubtypesFactoryAttribute : Attribute
+ {
+ public SubtypesFactoryAttribute(Type baseType, string @namespace)
+ {
+ BaseType = baseType;
+ Namespace = @namespace;
+ }
+
+ public string Namespace { get; }
+ public Type BaseType { get; }
+ }
+}
diff --git a/src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs b/src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs
index 5026fbaaba..89cde01ff4 100644
--- a/src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs
+++ b/src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs
@@ -23,7 +23,7 @@ namespace Avalonia.Win32.WinRT
[DllImport("api-ms-win-core-winrt-string-l1-1-0.dll",
CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
- internal static extern unsafe IntPtr WindowsDeleteString(IntPtr hString);
+ internal static extern unsafe void WindowsDeleteString(IntPtr hString);
[DllImport("Windows.UI.Composition", EntryPoint = "DllGetActivationFactory",
CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_DataValidation.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_DataValidation.cs
index 65f03b3eca..d48e58136a 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_DataValidation.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_DataValidation.cs
@@ -52,14 +52,14 @@ namespace Avalonia.Base.UnitTests
source.OnNext(BindingValue.DataValidationError(new Exception()));
source.OnNext(7);
- var result = target.Notifications.Cast>().ToList();
+ var result = target.Notifications;
Assert.Equal(4, result.Count);
- Assert.Equal(BindingValueType.Value, result[0].Type);
- Assert.Equal(6, result[0].Value);
- Assert.Equal(BindingValueType.BindingError, result[1].Type);
- Assert.Equal(BindingValueType.DataValidationError, result[2].Type);
- Assert.Equal(BindingValueType.Value, result[3].Type);
- Assert.Equal(7, result[3].Value);
+ Assert.Equal(BindingValueType.Value, result[0].type);
+ Assert.Equal(6, result[0].value);
+ Assert.Equal(BindingValueType.BindingError, result[1].type);
+ Assert.Equal(BindingValueType.DataValidationError, result[2].type);
+ Assert.Equal(BindingValueType.Value, result[3].type);
+ Assert.Equal(7, result[3].value);
}
[Fact]
@@ -72,8 +72,7 @@ namespace Avalonia.Base.UnitTests
target.Bind(Class1.NonValidatedDirectProperty, source);
source.OnNext(1);
- var result = target.Notifications.Cast>().ToList();
- Assert.Equal(1, result.Count);
+ Assert.Equal(1, target.Notifications.Count);
}
[Fact]
@@ -154,13 +153,14 @@ namespace Avalonia.Base.UnitTests
set { SetAndRaise(ValidatedDirectStringProperty, ref _directString, value); }
}
- public IList Notifications { get; } = new List();
+ public List<(BindingValueType type, object value)> Notifications { get; } = new();
- protected override void UpdateDataValidation(
- AvaloniaProperty property,
- BindingValue value)
+ protected override void UpdateDataValidation(
+ AvaloniaProperty property,
+ BindingValueType state,
+ Exception error)
{
- Notifications.Add(value);
+ Notifications.Add((state, GetValue(property)));
}
}
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_OnPropertyChanged.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_OnPropertyChanged.cs
index e8fc3f9f40..7f4dcace71 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_OnPropertyChanged.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_OnPropertyChanged.cs
@@ -109,25 +109,26 @@ namespace Avalonia.Base.UnitTests
public List Changes { get; }
public List CoreChanges { get; }
- protected override void OnPropertyChangedCore(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChangedCore(AvaloniaPropertyChangedEventArgs change)
{
CoreChanges.Add(Clone(change));
base.OnPropertyChangedCore(change);
}
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
Changes.Add(Clone(change));
base.OnPropertyChanged(change);
}
- private static AvaloniaPropertyChangedEventArgs Clone(AvaloniaPropertyChangedEventArgs change)
+ private static AvaloniaPropertyChangedEventArgs Clone(AvaloniaPropertyChangedEventArgs change)
{
- var result = new AvaloniaPropertyChangedEventArgs(
+ var e = (AvaloniaPropertyChangedEventArgs)change;
+ var result = new AvaloniaPropertyChangedEventArgs(
change.Sender,
- change.Property,
- change.OldValue,
- change.NewValue,
+ e.Property,
+ e.OldValue,
+ e.NewValue,
change.Priority);
if (!change.IsEffectiveValueChange)
diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs b/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs
index 1adb6988a2..f3f39b465b 100644
--- a/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs
+++ b/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Avalonia.Data;
+using Avalonia.Styling;
using Avalonia.Utilities;
using Xunit;
@@ -146,46 +147,46 @@ namespace Avalonia.Base.UnitTests
OverrideMetadata(typeof(T), metadata);
}
- public override void Accept(IAvaloniaPropertyVisitor vistor, ref TData data)
- {
- throw new NotImplementedException();
- }
-
internal override IDisposable RouteBind(
- IAvaloniaObject o,
+ AvaloniaObject o,
IObservable> source,
BindingPriority priority)
{
throw new NotImplementedException();
}
- internal override void RouteClearValue(IAvaloniaObject o)
+ internal override void RouteClearValue(AvaloniaObject o)
{
throw new NotImplementedException();
}
- internal override object RouteGetValue(IAvaloniaObject o)
+ internal override object RouteGetValue(AvaloniaObject o)
{
throw new NotImplementedException();
}
- internal override object RouteGetBaseValue(IAvaloniaObject o, BindingPriority maxPriority)
+ internal override object RouteGetBaseValue(AvaloniaObject o, BindingPriority maxPriority)
{
throw new NotImplementedException();
}
- internal override void RouteInheritanceParentChanged(AvaloniaObject o, IAvaloniaObject oldParent)
+ internal override void RouteInheritanceParentChanged(AvaloniaObject o, AvaloniaObject oldParent)
{
throw new NotImplementedException();
}
internal override IDisposable RouteSetValue(
- IAvaloniaObject o,
+ AvaloniaObject o,
object value,
BindingPriority priority)
{
throw new NotImplementedException();
}
+
+ internal override ISetterInstance CreateSetterInstance(IStyleable target, object value)
+ {
+ throw new NotImplementedException();
+ }
}
private class Class1 : AvaloniaObject
diff --git a/tests/Avalonia.Base.UnitTests/Input/MouseDeviceTests.cs b/tests/Avalonia.Base.UnitTests/Input/MouseDeviceTests.cs
index 758d501cc1..88abb4a6fa 100644
--- a/tests/Avalonia.Base.UnitTests/Input/MouseDeviceTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Input/MouseDeviceTests.cs
@@ -6,7 +6,6 @@ using Avalonia.Input.Raw;
using Avalonia.Media;
using Avalonia.Rendering;
using Avalonia.UnitTests;
-using Avalonia.VisualTree;
using Moq;
using Xunit;
@@ -34,160 +33,6 @@ namespace Avalonia.Base.UnitTests.Input
}
#pragma warning restore CS0618 // Type or member is obsolete
- [Fact]
- public void MouseMove_Should_Update_IsPointerOver()
- {
- var renderer = new Mock();
-
- using (TestApplication(renderer.Object))
- {
- var inputManager = InputManager.Instance;
-
- Canvas canvas;
- Border border;
- Decorator decorator;
-
- var root = new TestRoot
- {
- MouseDevice = new MouseDevice(),
- Renderer = renderer.Object,
- Child = new Panel
- {
- Children =
- {
- (canvas = new Canvas()),
- (border = new Border
- {
- Child = decorator = new Decorator(),
- })
- }
- }
- };
-
- SetHit(renderer, decorator);
- SendMouseMove(inputManager, root);
-
- Assert.True(decorator.IsPointerOver);
- Assert.True(border.IsPointerOver);
- Assert.False(canvas.IsPointerOver);
- Assert.True(root.IsPointerOver);
-
- SetHit(renderer, canvas);
- SendMouseMove(inputManager, root);
-
- Assert.False(decorator.IsPointerOver);
- Assert.False(border.IsPointerOver);
- Assert.True(canvas.IsPointerOver);
- Assert.True(root.IsPointerOver);
- }
- }
-
- [Fact]
- public void IsPointerOver_Should_Be_Updated_When_Child_Sets_Handled_True()
- {
- var renderer = new Mock();
-
- using (TestApplication(renderer.Object))
- {
- var inputManager = InputManager.Instance;
-
- Canvas canvas;
- Border border;
- Decorator decorator;
-
- var root = new TestRoot
- {
- MouseDevice = new MouseDevice(),
- Renderer = renderer.Object,
- Child = new Panel
- {
- Children =
- {
- (canvas = new Canvas()),
- (border = new Border
- {
- Child = decorator = new Decorator(),
- })
- }
- }
- };
-
- SetHit(renderer, canvas);
- SendMouseMove(inputManager, root);
-
- Assert.False(decorator.IsPointerOver);
- Assert.False(border.IsPointerOver);
- Assert.True(canvas.IsPointerOver);
- Assert.True(root.IsPointerOver);
-
- // Ensure that e.Handled is reset between controls.
- decorator.PointerEnter += (s, e) => e.Handled = true;
-
- SetHit(renderer, decorator);
- SendMouseMove(inputManager, root);
-
- Assert.True(decorator.IsPointerOver);
- Assert.True(border.IsPointerOver);
- Assert.False(canvas.IsPointerOver);
- Assert.True(root.IsPointerOver);
- }
- }
-
- [Fact]
- public void PointerEnter_Leave_Should_Be_Raised_In_Correct_Order()
- {
- var renderer = new Mock();
- var result = new List<(object, string)>();
-
- void HandleEvent(object sender, PointerEventArgs e)
- {
- result.Add((sender, e.RoutedEvent.Name));
- }
-
- using (TestApplication(renderer.Object))
- {
- var inputManager = InputManager.Instance;
-
- Canvas canvas;
- Border border;
- Decorator decorator;
-
- var root = new TestRoot
- {
- MouseDevice = new MouseDevice(),
- Renderer = renderer.Object,
- Child = new Panel
- {
- Children =
- {
- (canvas = new Canvas()),
- (border = new Border
- {
- Child = decorator = new Decorator(),
- })
- }
- }
- };
-
- SetHit(renderer, canvas);
- SendMouseMove(inputManager, root);
-
- AddEnterLeaveHandlers(HandleEvent, root, canvas, border, decorator);
- SetHit(renderer, decorator);
- SendMouseMove(inputManager, root);
-
- Assert.Equal(
- new[]
- {
- ((object)canvas, "PointerLeave"),
- ((object)decorator, "PointerEnter"),
- ((object)border, "PointerEnter"),
- },
- result);
- }
- }
-
-
[Fact]
public void GetPosition_Should_Respect_Control_RenderTransform()
{
@@ -216,17 +61,6 @@ namespace Avalonia.Base.UnitTests.Input
}
}
- private void AddEnterLeaveHandlers(
- EventHandler handler,
- params IControl[] controls)
- {
- foreach (var c in controls)
- {
- c.PointerEnter += handler;
- c.PointerLeave += handler;
- }
- }
-
private void SendMouseMove(IInputManager inputManager, TestRoot root, Point p = new Point())
{
inputManager.ProcessInput(new RawPointerEventArgs(
@@ -238,15 +72,6 @@ namespace Avalonia.Base.UnitTests.Input
RawInputModifiers.None));
}
- private void SetHit(Mock renderer, IControl hit)
- {
- renderer.Setup(x => x.HitTest(It.IsAny(), It.IsAny(), It.IsAny>()))
- .Returns(new[] { hit });
-
- renderer.Setup(x => x.HitTestFirst(It.IsAny(), It.IsAny(), It.IsAny