diff --git a/.editorconfig b/.editorconfig
index 9ae52b8bbd..238e9887bd 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -64,7 +64,7 @@ dotnet_naming_symbols.static_fields.applicable_kinds = field
dotnet_naming_symbols.static_fields.required_modifiers = static
dotnet_naming_style.static_prefix_style.required_prefix = s_
-dotnet_naming_style.static_prefix_style.capitalization = camel_case
+dotnet_naming_style.static_prefix_style.capitalization = camel_case
# internal and private fields should be _camelCase
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
@@ -137,14 +137,30 @@ space_within_single_line_array_initializer_braces = true
#Net Analyzer
dotnet_analyzer_diagnostic.category-Performance.severity = none #error - Uncomment when all violations are fixed.
+# CS1591: Missing XML comment for publicly visible type or member
+dotnet_diagnostic.CS1591.severity = suggestion
+
+# CA1304: Specify CultureInfo
+dotnet_diagnostic.CA1304.severity = warning
# CA1802: Use literals where appropriate
dotnet_diagnostic.CA1802.severity = warning
# CA1820: Test for empty strings using string length
dotnet_diagnostic.CA1820.severity = warning
# CA1821: Remove empty finalizers
dotnet_diagnostic.CA1821.severity = warning
+# CA1822: Mark members as static
+dotnet_diagnostic.CA1822.severity = suggestion
+dotnet_code_quality.CA1822.api_surface = private, internal
# CA1825: Avoid zero-length array allocations
dotnet_diagnostic.CA1825.severity = warning
+# CA1826: Use property instead of Linq Enumerable method
+dotnet_diagnostic.CA1826.severity = suggestion
+# CA1827: Do not use Count/LongCount when Any can be used
+dotnet_diagnostic.CA1827.severity = warning
+# CA1828: Do not use CountAsync/LongCountAsync when AnyAsync can be used
+dotnet_diagnostic.CA1828.severity = warning
+# CA1829: Use Length/Count property instead of Enumerable.Count method
+dotnet_diagnostic.CA1829.severity = warning
#CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
dotnet_diagnostic.CA1847.severity = warning
diff --git a/.ncrunch/Avalonia.Web.Blazor.v3.ncrunchproject b/.ncrunch/Avalonia.Benchmarks.v3.ncrunchproject
similarity index 100%
rename from .ncrunch/Avalonia.Web.Blazor.v3.ncrunchproject
rename to .ncrunch/Avalonia.Benchmarks.v3.ncrunchproject
diff --git a/.ncrunch/Avalonia.Web.v3.ncrunchproject b/.ncrunch/Avalonia.Browser.Blazor.v3.ncrunchproject
similarity index 100%
rename from .ncrunch/Avalonia.Web.v3.ncrunchproject
rename to .ncrunch/Avalonia.Browser.Blazor.v3.ncrunchproject
diff --git a/.ncrunch/ControlCatalog.Blazor.Web.v3.ncrunchproject b/.ncrunch/Avalonia.Browser.v3.ncrunchproject
similarity index 100%
rename from .ncrunch/ControlCatalog.Blazor.Web.v3.ncrunchproject
rename to .ncrunch/Avalonia.Browser.v3.ncrunchproject
diff --git a/.ncrunch/ControlCatalog.Web.v3.ncrunchproject b/.ncrunch/Avalonia.Designer.HostApp.v3.ncrunchproject
similarity index 100%
rename from .ncrunch/ControlCatalog.Web.v3.ncrunchproject
rename to .ncrunch/Avalonia.Designer.HostApp.v3.ncrunchproject
diff --git a/.ncrunch/Avalonia.Themes.Fluent.net6.0.v3.ncrunchproject b/.ncrunch/Avalonia.Themes.Fluent.net6.0.v3.ncrunchproject
new file mode 100644
index 0000000000..02eb0d211e
--- /dev/null
+++ b/.ncrunch/Avalonia.Themes.Fluent.net6.0.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ False
+
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.Themes.Fluent.netstandard2.0.v3.ncrunchproject b/.ncrunch/Avalonia.Themes.Fluent.netstandard2.0.v3.ncrunchproject
new file mode 100644
index 0000000000..02eb0d211e
--- /dev/null
+++ b/.ncrunch/Avalonia.Themes.Fluent.netstandard2.0.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ False
+
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.Themes.Simple.net6.0.v3.ncrunchproject b/.ncrunch/Avalonia.Themes.Simple.net6.0.v3.ncrunchproject
new file mode 100644
index 0000000000..02eb0d211e
--- /dev/null
+++ b/.ncrunch/Avalonia.Themes.Simple.net6.0.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ False
+
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.Themes.Simple.netstandard2.0.v3.ncrunchproject b/.ncrunch/Avalonia.Themes.Simple.netstandard2.0.v3.ncrunchproject
new file mode 100644
index 0000000000..02eb0d211e
--- /dev/null
+++ b/.ncrunch/Avalonia.Themes.Simple.netstandard2.0.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ False
+
+
\ No newline at end of file
diff --git a/.ncrunch/ControlCatalog.Browser.Blazor.v3.ncrunchproject b/.ncrunch/ControlCatalog.Browser.Blazor.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/ControlCatalog.Browser.Blazor.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/ControlCatalog.Browser.v3.ncrunchproject b/.ncrunch/ControlCatalog.Browser.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/ControlCatalog.Browser.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/MobileSandbox.v3.ncrunchproject b/.ncrunch/MobileSandbox.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/MobileSandbox.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/ReactiveUIDemo.v3.ncrunchproject b/.ncrunch/ReactiveUIDemo.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/ReactiveUIDemo.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/Avalonia.Desktop.slnf b/Avalonia.Desktop.slnf
index 6ba05332be..3fa8e969c8 100644
--- a/Avalonia.Desktop.slnf
+++ b/Avalonia.Desktop.slnf
@@ -9,6 +9,7 @@
"samples\\MiniMvvm\\MiniMvvm.csproj",
"samples\\SampleControls\\ControlSamples.csproj",
"samples\\Sandbox\\Sandbox.csproj",
+ "samples\\ReactiveUIDemo\\ReactiveUIDemo.csproj",
"src\\Avalonia.Base\\Avalonia.Base.csproj",
"src\\Avalonia.Build.Tasks\\Avalonia.Build.Tasks.csproj",
"src\\Avalonia.Controls.ColorPicker\\Avalonia.Controls.ColorPicker.csproj",
diff --git a/Avalonia.sln b/Avalonia.sln
index 34b5596119..7efb294b64 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -40,6 +40,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DE
.editorconfig = .editorconfig
src\Shared\IsExternalInit.cs = src\Shared\IsExternalInit.cs
src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs
+ src\Shared\NullableAttributes.cs = src\Shared\NullableAttributes.cs
src\Shared\SourceGeneratorAttributes.cs = src\Shared\SourceGeneratorAttributes.cs
src\Avalonia.Base\Compatibility\StringCompatibilityExtensions.cs = src\Avalonia.Base\Compatibility\StringCompatibilityExtensions.cs
EndProjectSection
@@ -119,6 +120,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\SourceLink.props = build\SourceLink.props
build\System.Drawing.Common.props = build\System.Drawing.Common.props
build\System.Memory.props = build\System.Memory.props
+ build\TrimmingEnable.props = build\TrimmingEnable.props
build\UnitTests.NetFX.props = build\UnitTests.NetFX.props
build\XUnit.props = build\XUnit.props
EndProjectSection
@@ -222,14 +224,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.iOS", "sample
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.Desktop", "samples\MobileSandbox.Desktop\MobileSandbox.Desktop.csproj", "{62D392C9-81CF-487F-92E8-598B2AF3FDCE}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Browser", "src\Browser\Avalonia.Browser\Avalonia.Browser.csproj", "{4A39637C-9338-4925-A4DB-D072E292EC78}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Browser", "src\Browser\Avalonia.Browser\Avalonia.Browser.csproj", "{4A39637C-9338-4925-A4DB-D072E292EC78}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Browser.Blazor", "src\Browser\Avalonia.Browser.Blazor\Avalonia.Browser.Blazor.csproj", "{47F8530C-F19B-4B1A-B4D6-EB231522AE5D}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Browser.Blazor", "src\Browser\Avalonia.Browser.Blazor\Avalonia.Browser.Blazor.csproj", "{47F8530C-F19B-4B1A-B4D6-EB231522AE5D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Browser", "samples\ControlCatalog.Browser\ControlCatalog.Browser.csproj", "{15B93A4C-1B46-43F6-B534-7B25B6E99932}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Browser.Blazor", "samples\ControlCatalog.Browser.Blazor\ControlCatalog.Browser.Blazor.csproj", "{90B08091-9BBD-4362-B712-E9F2CC62B218}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveUIDemo", "samples\ReactiveUIDemo\ReactiveUIDemo.csproj", "{75C47156-C5D8-44BC-A5A7-E8657C2248D6}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -541,6 +545,10 @@ Global
{90B08091-9BBD-4362-B712-E9F2CC62B218}.Debug|Any CPU.Build.0 = Debug|Any CPU
{90B08091-9BBD-4362-B712-E9F2CC62B218}.Release|Any CPU.ActiveCfg = Release|Any CPU
{90B08091-9BBD-4362-B712-E9F2CC62B218}.Release|Any CPU.Build.0 = Release|Any CPU
+ {75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -605,6 +613,7 @@ Global
{47F8530C-F19B-4B1A-B4D6-EB231522AE5D} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
{15B93A4C-1B46-43F6-B534-7B25B6E99932} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{90B08091-9BBD-4362-B712-E9F2CC62B218} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {75C47156-C5D8-44BC-A5A7-E8657C2248D6} = {9B9E3891-2366-4253-A952-D08BCEB71098}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index 5838519596..e9c3d65b41 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -7,7 +7,7 @@
https://avaloniaui.net
https://github.com/AvaloniaUI/Avalonia/
true
- CS1591
+ $(NoWarn);CS1591
preview
MIT
Icon.png
diff --git a/build/TrimmingEnable.props b/build/TrimmingEnable.props
new file mode 100644
index 0000000000..3f873e3345
--- /dev/null
+++ b/build/TrimmingEnable.props
@@ -0,0 +1,16 @@
+
+
+ false
+ true
+ false
+ true
+
+
+
+ true
+
+ $(WarningsAsErrors);IL2000;IL2001;IL2002;IL2003;IL2004;IL2005;IL2006;IL2007;IL2008;IL2009;IL2010;IL2011;IL2012;IL2013;IL2014;IL2015;IL2016;IL2017;IL2018;IL2019;IL2020;IL2021;IL2022;IL2023;IL2024;IL2025;IL2026;IL2027;IL2028;IL2029;IL2030;IL2031;IL2032;IL2033;IL2034;IL2035;IL2036;IL2037;IL2038;IL2039;IL2040;IL2041;IL2042;IL2043;IL2044;IL2045;IL2046;IL2047;IL2048;IL2049;IL2050;IL2051;IL2052;IL2053;IL2054;IL2055;IL2056;IL2057;IL2058;IL2059;IL2060;IL2061;IL2062;IL2063;IL2064;IL2065;IL2066;IL2067;IL2068;IL2069;IL2070;IL2071;IL2072;IL2073;IL2074;IL2075;IL2076;IL2077;IL2078;IL2079;IL2080;IL2081;IL2082;IL2083;IL2084;IL2085;IL2086;IL2087;IL2088;IL2089;IL2090;IL2091;IL2092;IL2093;IL2094;IL2095;IL2096;IL2097;IL2098;IL2099;IL2100;IL2101;IL2102;IL2103;IL2104;IL2105;IL2106;IL2107;IL2108;IL2109;IL2110;IL2111;IL2112;IL2113;IL2114;IL2115;IL2116;IL2117;IL2118;IL2119;IL2120;IL2121;IL2122;IL2123;IL2124;IL2125;IL2126;IL2127;IL2128;IL2129;IL2130;IL2131;IL2132;IL2133;IL2134;IL2135;IL2136;IL2137;IL2138;IL2139;IL2140;IL2141;IL2142;IL2143;IL2144;IL2145;IL2146;IL2147;IL2148;IL2149;IL2150;IL2151;IL2152;IL2153;IL2154;IL2155;IL2156;IL2157
+
+ $(WarningsAsErrors);IL3050;IL3051;IL3052;IL3053;IL3054;IL3055;IL3056
+
+
diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm
index 2443965957..b6dacb6ce4 100644
--- a/native/Avalonia.Native/src/OSX/WindowImpl.mm
+++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm
@@ -137,7 +137,11 @@ void WindowImpl::BringToFront()
for(auto iterator = _children.begin(); iterator != _children.end(); iterator++)
{
- (*iterator)->BringToFront();
+ auto window = (*iterator)->Window;
+
+ // #9565: Only bring window to front if it's on the currently active space
+ if ([window isOnActiveSpace])
+ (*iterator)->BringToFront();
}
}
}
@@ -161,6 +165,9 @@ void WindowImpl::StartStateTransition() {
void WindowImpl::EndStateTransition() {
_transitioningWindowState = false;
+
+ // Ensure correct order of child windows after fullscreen transition.
+ BringToFront();
}
SystemDecorations WindowImpl::Decorations() {
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index 2295c0beda..3704cee890 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -80,7 +80,6 @@ partial class Build : NukeBuild
if (Parameters.IsRunningOnAzure)
c.AddProperty("JavaSdkDirectory", GetVariable("JAVA_HOME_11_X64"));
c.AddProperty("PackageVersion", Parameters.Version)
- .AddProperty("iOSRoslynPathHackRequired", true)
.SetConfiguration(Parameters.Configuration)
.SetVerbosity(DotNetVerbosity.Minimal);
return c;
diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj
index 92d9732e91..13bac4b7db 100644
--- a/nukebuild/_build.csproj
+++ b/nukebuild/_build.csproj
@@ -4,7 +4,7 @@
false
False
- CS0649;CS0169;SYSLIB0011
+ $(NoWarn);CS0649;CS0169;SYSLIB0011
1
net7.0
diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets
index 4f9c4d7720..ca2d4b66ed 100644
--- a/packages/Avalonia/AvaloniaBuildTasks.targets
+++ b/packages/Avalonia/AvaloniaBuildTasks.targets
@@ -30,7 +30,9 @@
/>
-
+
$(IntermediateOutputPath)/Avalonia/resources
@@ -62,7 +64,9 @@
BeforeTargets="CoreCompile;CoreResGen"
Inputs="@(AvaloniaResource);@(AvaloniaXaml);@(CustomAdditionalGenerateAvaloniaResourcesInputs);$(MSBuildAllProjects)"
Outputs="$(AvaloniaResourcesTemporaryFilePath)"
- DependsOnTargets="$(BuildAvaloniaResourcesDependsOn)">
+ DependsOnTargets="$(BuildAvaloniaResourcesDependsOn)"
+ Condition="('@(AvaloniaResource->Count())' > 0) or ('@(AvaloniaXaml->Count())' > 0)"
+ >
@@ -74,14 +78,19 @@
ReportImportance="$(AvaloniaXamlReportImportance)"/>
+ Command="dotnet msbuild /nodereuse:false $(MSBuildProjectFile) /t:GenerateAvaloniaResources /p:_AvaloniaForceInternalMSBuild=true /p:Configuration=$(Configuration) /p:TargetFramework=$(TargetFramework) /p:RuntimeIdentifier=$(RuntimeIdentifier) /p:BuildProjectReferences=false"/>
$(IntermediateOutputPath)/Avalonia/references
@@ -112,7 +121,7 @@
/>
+ Command="dotnet msbuild /nodereuse:false $(MSBuildProjectFile) /t:CompileAvaloniaXaml /p:_AvaloniaForceInternalMSBuild=true /p:Configuration=$(Configuration) /p:TargetFramework=$(TargetFramework) /p:RuntimeIdentifier=$(RuntimeIdentifier) /p:BuildProjectReferences=false"/>
diff --git a/samples/BindingDemo/App.xaml b/samples/BindingDemo/App.xaml
index 175e838616..5a8e65ed22 100644
--- a/samples/BindingDemo/App.xaml
+++ b/samples/BindingDemo/App.xaml
@@ -2,8 +2,14 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="BindingDemo.App">
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs
index b1bacc6483..d5e5cb14dc 100644
--- a/samples/ControlCatalog.NetCore/Program.cs
+++ b/samples/ControlCatalog.NetCore/Program.cs
@@ -99,6 +99,15 @@ namespace ControlCatalog.NetCore
SilenceConsole();
return builder.StartLinuxDrm(args, scaling: GetScaling());
}
+ else if (args.Contains("--dxgi"))
+ {
+ builder.With(new Win32PlatformOptions()
+ {
+ UseLowLatencyDxgiSwapChain = true,
+ UseWindowsUIComposition = false
+ });
+ return builder.StartWithClassicDesktopLifetime(args);
+ }
else
return builder.StartWithClassicDesktopLifetime(args);
}
diff --git a/samples/ControlCatalog.NetCore/Properties/launchSettings.json b/samples/ControlCatalog.NetCore/Properties/launchSettings.json
new file mode 100644
index 0000000000..5964ca320e
--- /dev/null
+++ b/samples/ControlCatalog.NetCore/Properties/launchSettings.json
@@ -0,0 +1,11 @@
+{
+ "profiles": {
+ "ControlCatalog.NetCore": {
+ "commandName": "Project"
+ },
+ "Dxgi": {
+ "commandName": "Project",
+ "commandLineArgs": "--dxgi"
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj
index 6b550a30be..18f0dd16ba 100644
--- a/samples/ControlCatalog/ControlCatalog.csproj
+++ b/samples/ControlCatalog/ControlCatalog.csproj
@@ -33,4 +33,14 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Converter/DegToRadConverter.cs b/samples/ControlCatalog/Converter/DegToRadConverter.cs
new file mode 100644
index 0000000000..b062bcb64a
--- /dev/null
+++ b/samples/ControlCatalog/Converter/DegToRadConverter.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using Avalonia.Data.Converters;
+
+namespace ControlCatalog.Converter
+{
+ public class DegToRadConverter : IValueConverter
+ {
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value is double rad)
+ {
+ return rad * 180.0d / Math.PI;
+ }
+ return 0.0d;
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value is double deg)
+ {
+ return deg / 180.0d * Math.PI;
+ }
+ return 0.0d;
+ }
+ }
+}
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index 33ea8c0db0..4a5f5bc96c 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -66,6 +66,9 @@
+
+
+
diff --git a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
index 8d9cd74ea7..ae7e43f511 100644
--- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
@@ -14,7 +14,26 @@ namespace ControlCatalog.Pages
{
public class AutoCompleteBoxPage : UserControl
{
- private StateData[] BuildAllStates()
+ public class StateData
+ {
+ public string Name { get; private set; }
+ public string Abbreviation { get; private set; }
+ public string Capital { get; private set; }
+
+ public StateData(string name, string abbreviatoin, string capital)
+ {
+ Name = name;
+ Abbreviation = abbreviatoin;
+ Capital = capital;
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+ }
+
+ private static StateData[] BuildAllStates()
{
return new StateData[]
{
@@ -72,7 +91,7 @@ namespace ControlCatalog.Pages
}
public StateData[] States { get; private set; }
- private LinkedList[] BuildAllSentences()
+ private static LinkedList[] BuildAllSentences()
{
return new string[]
{
@@ -124,7 +143,7 @@ namespace ControlCatalog.Pages
.OfType();
}
- private bool StringContains(string str, string? query)
+ private static bool StringContains(string str, string? query)
{
if (query == null) return false;
return str.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0;
diff --git a/samples/ControlCatalog/Pages/CompositionPage.axaml.cs b/samples/ControlCatalog/Pages/CompositionPage.axaml.cs
index 61e0ed5acb..c70675b606 100644
--- a/samples/ControlCatalog/Pages/CompositionPage.axaml.cs
+++ b/samples/ControlCatalog/Pages/CompositionPage.axaml.cs
@@ -25,7 +25,7 @@ public partial class CompositionPage : UserControl
this.Get("Items").Items = CreateColorItems();
}
- private List CreateColorItems()
+ private static List CreateColorItems()
{
var list = new List();
diff --git a/samples/ControlCatalog/Pages/CustomDrawing.xaml b/samples/ControlCatalog/Pages/CustomDrawing.xaml
new file mode 100644
index 0000000000..04b7fcfea5
--- /dev/null
+++ b/samples/ControlCatalog/Pages/CustomDrawing.xaml
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/CustomDrawing.xaml.cs b/samples/ControlCatalog/Pages/CustomDrawing.xaml.cs
new file mode 100644
index 0000000000..0416e587b9
--- /dev/null
+++ b/samples/ControlCatalog/Pages/CustomDrawing.xaml.cs
@@ -0,0 +1,67 @@
+using System;
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Avalonia.Markup.Xaml;
+
+namespace ControlCatalog.Pages
+{
+ public partial class CustomDrawing : UserControl
+ {
+ public CustomDrawing()
+ {
+ InitializeComponent();
+ }
+
+ private CustomDrawingExampleControl? _customControl;
+ public CustomDrawingExampleControl CustomDrawingControl
+ {
+ get
+ {
+ if (_customControl is not null)
+ return _customControl;
+ throw new System.Exception("Control did not get initialized");
+ }
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ var cntrl = this.FindControl("CustomDrawingControl");
+ if (cntrl != null)
+ {
+ _customControl = cntrl;
+ }
+ else
+ {
+ // be sad about it
+ }
+ }
+
+ private void RotateMinus (object? sender, RoutedEventArgs e)
+ {
+ if (_customControl is null) return;
+ _customControl.Rotation -= Math.PI / 20.0d;
+ }
+
+ private void RotatePlus(object? sender, RoutedEventArgs e)
+ {
+ if (_customControl is null)
+ return;
+ _customControl.Rotation += Math.PI / 20.0d;
+ }
+
+ private void ZoomIn(object? sender, RoutedEventArgs e)
+ {
+ if (_customControl is null)
+ return;
+ _customControl.Scale *= 1.2d;
+ }
+
+ private void ZoomOut(object? sender, RoutedEventArgs e)
+ {
+ if (_customControl is null)
+ return;
+ _customControl.Scale /= 1.2d;
+ }
+ }
+}
diff --git a/samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs b/samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs
new file mode 100644
index 0000000000..11e5e32cf1
--- /dev/null
+++ b/samples/ControlCatalog/Pages/CustomDrawingExampleControl.cs
@@ -0,0 +1,215 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Media;
+using Avalonia.Input;
+using Avalonia.Threading;
+using Avalonia.Controls.Shapes;
+
+namespace ControlCatalog.Pages
+{
+ public class CustomDrawingExampleControl : Control
+ {
+ private Point _cursorPoint;
+
+
+ public StyledProperty ScaleProperty = AvaloniaProperty.Register(nameof(Scale), 1.0d);
+ public double Scale { get => GetValue(ScaleProperty); set => SetValue(ScaleProperty, value); }
+
+ public StyledProperty RotationProperty = AvaloniaProperty.Register(nameof(Rotation));
+ ///
+ /// Rotation, measured in Radians!
+ ///
+ public double Rotation
+ {
+ get => GetValue(RotationProperty);
+ set
+ {
+ double valueToUse = value % (Math.PI * 2);
+ SetValue(RotationProperty, valueToUse);
+ }
+ }
+
+ public StyledProperty ViewportCenterYProperty = AvaloniaProperty.Register(nameof(ViewportCenterY), 0.0d);
+ public double ViewportCenterY { get => GetValue(ViewportCenterYProperty); set => SetValue(ViewportCenterYProperty, value); }
+
+ public StyledProperty ViewportCenterXProperty = AvaloniaProperty.Register(nameof(ViewportCenterX), 0.0d);
+ public double ViewportCenterX { get => GetValue(ViewportCenterXProperty); set => SetValue(ViewportCenterXProperty, value); }
+
+ private IPen _pen;
+
+ private System.Diagnostics.Stopwatch _timeKeeper = System.Diagnostics.Stopwatch.StartNew();
+
+ private bool _isPointerCaptured = false;
+
+ public CustomDrawingExampleControl()
+ {
+ _pen = new Pen(new SolidColorBrush(Colors.Black), lineCap: PenLineCap.Round);
+
+ var _arc = new ArcSegment()
+ {
+ IsLargeArc = false,
+ Point = new Point(0, 0),
+ RotationAngle = 0,
+ Size = new Size(25, 25),
+ SweepDirection = SweepDirection.Clockwise,
+
+ };
+ StreamGeometry sg = new StreamGeometry();
+ var cntx = sg.Open();
+ cntx.BeginFigure(new Point(-25.0d, -10.0d), false);
+ cntx.ArcTo(new Point(25.0d, -10.0d), new Size(10.0d, 10.0d), 0.0d, false, SweepDirection.Clockwise);
+ cntx.EndFigure(true);
+ _smileGeometry = sg.Clone();
+ }
+
+ private Geometry _smileGeometry;
+
+ protected override void OnPointerMoved(PointerEventArgs e)
+ {
+ base.OnPointerMoved(e);
+
+ Point previousPoint = _cursorPoint;
+
+ _cursorPoint = e.GetPosition(this);
+
+ if (_isPointerCaptured)
+ {
+ Point oldWorldPoint = UIPointToWorldPoint(previousPoint, ViewportCenterX, ViewportCenterY, Scale, Rotation);
+ Point newWorldPoint = UIPointToWorldPoint(_cursorPoint, ViewportCenterX, ViewportCenterY, Scale, Rotation);
+
+ Vector diff = newWorldPoint - oldWorldPoint;
+
+ ViewportCenterX -= diff.X;
+ ViewportCenterY -= diff.Y;
+ }
+ }
+
+ protected override void OnPointerPressed(PointerPressedEventArgs e)
+ {
+ e.Handled = true;
+ e.Pointer.Capture(this);
+ _isPointerCaptured = true;
+ base.OnPointerPressed(e);
+ }
+
+ protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
+ {
+ base.OnPointerWheelChanged(e);
+ var oldScale = Scale;
+ Scale *= (1.0d + e.Delta.Y / 12.0d);
+
+ Point oldWorldPoint = UIPointToWorldPoint(_cursorPoint, ViewportCenterX, ViewportCenterY, oldScale, Rotation);
+ Point newWorldPoint = UIPointToWorldPoint(_cursorPoint, ViewportCenterX, ViewportCenterY, Scale, Rotation);
+
+ Vector diff = newWorldPoint - oldWorldPoint;
+
+ ViewportCenterX -= diff.X;
+ ViewportCenterY -= diff.Y;
+ }
+
+ protected override void OnPointerReleased(PointerReleasedEventArgs e)
+ {
+ e.Pointer.Capture(null);
+ _isPointerCaptured = false;
+ base.OnPointerReleased(e);
+ }
+
+ public override void Render(DrawingContext context)
+ {
+ var localBounds = new Rect(new Size(this.Bounds.Width, this.Bounds.Height));
+ var clip = context.PushClip(this.Bounds);
+ context.DrawRectangle(Brushes.White, _pen, localBounds, 1.0d);
+
+ var halfMax = Math.Max(this.Bounds.Width / 2.0d, this.Bounds.Height / 2.0d) * Math.Sqrt(2.0d);
+ var halfMin = Math.Min(this.Bounds.Width / 2.0d, this.Bounds.Height / 2.0d) / 1.3d;
+ var halfWidth = this.Bounds.Width / 2.0d;
+ var halfHeight = this.Bounds.Height / 2.0d;
+
+ // 0,0 refers to the top-left of the control now. It is not prime time to draw gui stuff because it'll be under the world
+
+ var translateModifier = context.PushPreTransform(Avalonia.Matrix.CreateTranslation(new Avalonia.Vector(halfWidth, halfHeight)));
+
+ // now 0,0 refers to the ViewportCenter(X,Y).
+ var rotationMatrix = Avalonia.Matrix.CreateRotation(Rotation);
+ var rotationModifier = context.PushPreTransform(rotationMatrix);
+
+ // everything is rotated but not scaled
+
+ var scaleModifier = context.PushPreTransform(Avalonia.Matrix.CreateScale(Scale, -Scale));
+
+ var mapPositionModifier = context.PushPreTransform(Matrix.CreateTranslation(new Vector(-ViewportCenterX, -ViewportCenterY)));
+
+ // now everything is rotated and scaled, and at the right position, now we're drawing strictly in world coordinates
+
+ context.DrawEllipse(Brushes.White, _pen, new Point(0.0d, 0.0d), 50.0d, 50.0d);
+ context.DrawLine(_pen, new Point(-25.0d, -5.0d), new Point(-25.0d, 15.0d));
+ context.DrawLine(_pen, new Point(25.0d, -5.0d), new Point(25.0d, 15.0d));
+ context.DrawGeometry(null, _pen, _smileGeometry);
+
+ Point cursorInWorldPoint = UIPointToWorldPoint(_cursorPoint, ViewportCenterX, ViewportCenterY, Scale, Rotation);
+ context.DrawEllipse(Brushes.Gray, _pen, cursorInWorldPoint, 20.0d, 20.0d);
+
+
+ for (int i = 0; i < 10; i++)
+ {
+ double orbitRadius = i * 100 + 200;
+ var orbitInput = ((_timeKeeper.Elapsed.TotalMilliseconds + 987654d) / orbitRadius) / 10.0d;
+ if (i % 3 == 0)
+ orbitInput *= -1;
+ Point orbitPosition = new Point(Math.Sin(orbitInput) * orbitRadius, Math.Cos(orbitInput) * orbitRadius);
+ context.DrawEllipse(Brushes.Gray, _pen, orbitPosition, 20.0d, 20.0d);
+ }
+
+
+ // end drawing the world
+
+ mapPositionModifier.Dispose();
+
+ scaleModifier.Dispose();
+
+ rotationModifier.Dispose();
+ translateModifier.Dispose();
+
+ // this is prime time to draw gui stuff
+
+ context.DrawLine(_pen, _cursorPoint + new Vector(-20, 0), _cursorPoint + new Vector(20, 0));
+ context.DrawLine(_pen, _cursorPoint + new Vector(0, -20), _cursorPoint + new Vector(0, 20));
+
+ clip.Dispose();
+
+ // oh and draw again when you can, no rush, right?
+ Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
+ }
+
+ private Point UIPointToWorldPoint(Point inPoint, double viewportCenterX, double viewportCenterY, double scale, double rotation)
+ {
+ Point workingPoint = new Point(inPoint.X, -inPoint.Y);
+ workingPoint += new Vector(-this.Bounds.Width / 2.0d, this.Bounds.Height / 2.0d);
+ workingPoint /= scale;
+
+ workingPoint = Matrix.CreateRotation(rotation).Transform(workingPoint);
+
+ workingPoint += new Vector(viewportCenterX, viewportCenterY);
+
+ return workingPoint;
+ }
+
+ private Point WorldPointToUIPoint(Point inPoint, double viewportCenterX, double viewportCenterY, double scale, double rotation)
+ {
+ Point workingPoint = new Point(inPoint.X, inPoint.Y);
+
+ workingPoint -= new Vector(viewportCenterX, viewportCenterY);
+ // undo rotation
+ workingPoint = Matrix.CreateRotation(-rotation).Transform(workingPoint);
+ workingPoint *= scale;
+ workingPoint -= new Vector(-this.Bounds.Width / 2.0d, this.Bounds.Height / 2.0d);
+ workingPoint = new Point(workingPoint.X, -workingPoint.Y);
+
+ return workingPoint;
+ }
+ }
+}
diff --git a/samples/ControlCatalog/Pages/DataGridPage.xaml b/samples/ControlCatalog/Pages/DataGridPage.xaml
index f1fcd8035a..4c3c211ca5 100644
--- a/samples/ControlCatalog/Pages/DataGridPage.xaml
+++ b/samples/ControlCatalog/Pages/DataGridPage.xaml
@@ -14,22 +14,6 @@
-
-
-
-
-
-
A control for displaying and interacting with a data source.
@@ -45,8 +29,7 @@
+ RowBackground="#1000">
@@ -59,6 +42,24 @@
IsVisible="{Binding #ShowGDP.IsChecked}"
x:DataType="local:Country" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -71,6 +72,20 @@
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/ExpanderPage.xaml b/samples/ControlCatalog/Pages/ExpanderPage.xaml
index f0a80fd7ab..b5a2e6cdd0 100644
--- a/samples/ControlCatalog/Pages/ExpanderPage.xaml
+++ b/samples/ControlCatalog/Pages/ExpanderPage.xaml
@@ -52,6 +52,24 @@
Rounded
+
+
+ Expanded content
+
+
+
+
+ Expanded content
+
+
diff --git a/samples/ControlCatalog/Pages/ExpanderPage.xaml.cs b/samples/ControlCatalog/Pages/ExpanderPage.xaml.cs
index e8a080899a..98a494e533 100644
--- a/samples/ControlCatalog/Pages/ExpanderPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ExpanderPage.xaml.cs
@@ -10,6 +10,12 @@ namespace ControlCatalog.Pages
{
this.InitializeComponent();
DataContext = new ExpanderPageViewModel();
+
+ var CollapsingDisabledExpander = this.Get("CollapsingDisabledExpander");
+ var ExpandingDisabledExpander = this.Get("ExpandingDisabledExpander");
+
+ CollapsingDisabledExpander.Collapsing += (s, e) => { e.Handled = true; };
+ ExpandingDisabledExpander.Expanding += (s, e) => { e.Handled = true; };
}
private void InitializeComponent()
diff --git a/samples/ControlCatalog/Pages/ImagePage.xaml.cs b/samples/ControlCatalog/Pages/ImagePage.xaml.cs
index 45043aa5af..511b01c7ac 100644
--- a/samples/ControlCatalog/Pages/ImagePage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ImagePage.xaml.cs
@@ -58,7 +58,7 @@ namespace ControlCatalog.Pages
}
}
- private PixelRect GetCropRect(int index)
+ private static PixelRect GetCropRect(int index)
{
var bitmapWidth = 640;
var bitmapHeight = 426;
diff --git a/samples/ControlCatalog/Pages/ListBoxPage.xaml b/samples/ControlCatalog/Pages/ListBoxPage.xaml
index 04129cb82d..dc0eaf0a51 100644
--- a/samples/ControlCatalog/Pages/ListBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/ListBoxPage.xaml
@@ -32,6 +32,7 @@
diff --git a/samples/ControlCatalog/Pages/OpenGlPage.xaml.cs b/samples/ControlCatalog/Pages/OpenGlPage.xaml.cs
index a126fbefe5..ded02330d5 100644
--- a/samples/ControlCatalog/Pages/OpenGlPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/OpenGlPage.xaml.cs
@@ -247,7 +247,7 @@ namespace ControlCatalog.Pages
}
- private void CheckError(GlInterface gl)
+ private static void CheckError(GlInterface gl)
{
int err;
while ((err = gl.GetError()) != GL_NO_ERROR)
diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs
index ff62b834c4..6af4cf353e 100644
--- a/samples/ControlCatalog/Pages/ScreenPage.cs
+++ b/samples/ControlCatalog/Pages/ScreenPage.cs
@@ -66,6 +66,7 @@ namespace ControlCatalog.Pages
context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 40));
formattedText = CreateFormattedText($"IsPrimary: {screen.IsPrimary}");
+
context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 60));
formattedText =
@@ -77,7 +78,7 @@ namespace ControlCatalog.Pages
context.DrawRectangle(p, new Rect(w.Position.X / 10f + Math.Abs(_leftMost), w.Position.Y / 10f, w.Bounds.Width / 10, w.Bounds.Height / 10));
}
- private FormattedText CreateFormattedText(string textToFormat)
+ private static FormattedText CreateFormattedText(string textToFormat)
{
return new FormattedText(textToFormat, CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
Typeface.Default, 12, Brushes.Green);
diff --git a/samples/ControlCatalog/Pages/TabControlPage.xaml b/samples/ControlCatalog/Pages/TabControlPage.xaml
index a830ce69ac..e289de90f9 100644
--- a/samples/ControlCatalog/Pages/TabControlPage.xaml
+++ b/samples/ControlCatalog/Pages/TabControlPage.xaml
@@ -53,14 +53,8 @@
-
-
-
-
-
-
diff --git a/samples/ControlCatalog/Pages/TabControlPage.xaml.cs b/samples/ControlCatalog/Pages/TabControlPage.xaml.cs
index 74e9928b24..413b6e1c75 100644
--- a/samples/ControlCatalog/Pages/TabControlPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/TabControlPage.xaml.cs
@@ -49,7 +49,7 @@ namespace ControlCatalog.Pages
AvaloniaXamlLoader.Load(this);
}
- private IBitmap LoadBitmap(string uri)
+ private static IBitmap LoadBitmap(string uri)
{
var assets = AvaloniaLocator.Current!.GetService()!;
return new Bitmap(assets.Open(new Uri(uri)));
diff --git a/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs b/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
index 59489ebcc0..f89d9d1e20 100644
--- a/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Reactive;
using Avalonia.Controls;
using Avalonia.Controls.Selection;
+using ControlCatalog.Pages;
using MiniMvvm;
namespace ControlCatalog.ViewModels
@@ -20,9 +21,9 @@ namespace ControlCatalog.ViewModels
public ListBoxPageViewModel()
{
- Items = new ObservableCollection(Enumerable.Range(1, 10000).Select(i => GenerateItem()));
+ Items = new ObservableCollection(Enumerable.Range(1, 10000).Select(i => GenerateItem()));
- Selection = new SelectionModel();
+ Selection = new SelectionModel();
Selection.Select(1);
_selectionMode = this.WhenAnyValue(
@@ -58,8 +59,8 @@ namespace ControlCatalog.ViewModels
});
}
- public ObservableCollection Items { get; }
- public SelectionModel Selection { get; }
+ public ObservableCollection Items { get; }
+ public SelectionModel Selection { get; }
public IObservable SelectionMode => _selectionMode;
public bool Multiple
@@ -96,6 +97,31 @@ namespace ControlCatalog.ViewModels
public MiniCommand RemoveItemCommand { get; }
public MiniCommand SelectRandomItemCommand { get; }
- private string GenerateItem() => $"Item {_counter++.ToString()}";
+ private ItemModel GenerateItem() => new ItemModel(_counter ++);
+ }
+
+ ///
+ /// An Item model for the
+ ///
+ public class ItemModel
+ {
+ ///
+ /// Creates a new ItemModel with the given ID
+ ///
+ /// The ID to display
+ public ItemModel(int id)
+ {
+ ID = id;
+ }
+
+ ///
+ /// The ID of this Item
+ ///
+ public int ID { get; }
+
+ public override string ToString()
+ {
+ return $"Item {ID}";
+ }
}
}
diff --git a/samples/ControlCatalog/ViewModels/TransitioningContentControlPageViewModel.cs b/samples/ControlCatalog/ViewModels/TransitioningContentControlPageViewModel.cs
index 83892247e6..93857fd899 100644
--- a/samples/ControlCatalog/ViewModels/TransitioningContentControlPageViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/TransitioningContentControlPageViewModel.cs
@@ -293,10 +293,10 @@ namespace ControlCatalog.ViewModels
///
/// Any one of the parameters may be null, but not both.
///
- private static IVisual GetVisualParent(IVisual? from, IVisual? to)
+ private static Visual GetVisualParent(Visual? from, Visual? to)
{
- var p1 = (from ?? to)!.VisualParent;
- var p2 = (to ?? from)!.VisualParent;
+ var p1 = (from ?? to)!.GetVisualParent();
+ var p2 = (to ?? from)!.GetVisualParent();
if (p1 != null && p2 != null && p1 != p2)
{
diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props
index 8fc91aca14..471c42ec07 100644
--- a/samples/Directory.Build.props
+++ b/samples/Directory.Build.props
@@ -4,4 +4,7 @@
$(MSBuildThisFileDirectory)..\src\tools\Avalonia.Designer.HostApp\bin\Debug\netcoreapp2.0\Avalonia.Designer.HostApp.dll
+
+ false
+
diff --git a/samples/IntegrationTestApp/MainWindow.axaml b/samples/IntegrationTestApp/MainWindow.axaml
index 038ced4e5c..54c0cb0655 100644
--- a/samples/IntegrationTestApp/MainWindow.axaml
+++ b/samples/IntegrationTestApp/MainWindow.axaml
@@ -17,11 +17,15 @@
-
+
+
+ WindowState:
+
+
@@ -129,13 +133,14 @@
CenterOwner
- Normal
- Minimized
- Maximized
- FullScreen
+ Normal
+ Minimized
+ Maximized
+ FullScreen
+
diff --git a/samples/IntegrationTestApp/MainWindow.axaml.cs b/samples/IntegrationTestApp/MainWindow.axaml.cs
index c1acc7ca88..841947673a 100644
--- a/samples/IntegrationTestApp/MainWindow.axaml.cs
+++ b/samples/IntegrationTestApp/MainWindow.axaml.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia;
@@ -178,6 +179,8 @@ namespace IntegrationTestApp
ShowWindow();
if (source?.Name == "SendToBack")
SendToBack();
+ if (source?.Name == "EnterFullscreen")
+ WindowState = WindowState.FullScreen;
if (source?.Name == "ExitFullscreen")
WindowState = WindowState.Normal;
if (source?.Name == "RestoreAll")
diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml b/samples/IntegrationTestApp/ShowWindowTest.axaml
index c3a0d8d2e2..00987429d0 100644
--- a/samples/IntegrationTestApp/ShowWindowTest.axaml
+++ b/samples/IntegrationTestApp/ShowWindowTest.axaml
@@ -27,10 +27,10 @@
- Normal
- Minimized
- Maximized
- FullScreen
+ Normal
+ Minimized
+ Maximized
+ FullScreen
diff --git a/samples/ReactiveUIDemo/App.axaml b/samples/ReactiveUIDemo/App.axaml
new file mode 100644
index 0000000000..dd3a39f6ac
--- /dev/null
+++ b/samples/ReactiveUIDemo/App.axaml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/samples/ReactiveUIDemo/App.axaml.cs b/samples/ReactiveUIDemo/App.axaml.cs
new file mode 100644
index 0000000000..4578566427
--- /dev/null
+++ b/samples/ReactiveUIDemo/App.axaml.cs
@@ -0,0 +1,37 @@
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+using Avalonia.ReactiveUI;
+using ReactiveUI;
+using ReactiveUIDemo.ViewModels;
+using ReactiveUIDemo.Views;
+using Splat;
+
+namespace ReactiveUIDemo
+{
+ public class App : Application
+ {
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ Locator.CurrentMutable.Register(() => new FooView(), typeof(IViewFor));
+ Locator.CurrentMutable.Register(() => new BarView(), typeof(IViewFor));
+ }
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ desktop.MainWindow = new MainWindow();
+ base.OnFrameworkInitializationCompleted();
+ }
+
+ public static int Main(string[] args)
+ => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
+
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .UsePlatformDetect()
+ .UseReactiveUI()
+ .LogToTrace();
+ }
+}
diff --git a/samples/ReactiveUIDemo/MainWindow.axaml b/samples/ReactiveUIDemo/MainWindow.axaml
new file mode 100644
index 0000000000..7775fc5a79
--- /dev/null
+++ b/samples/ReactiveUIDemo/MainWindow.axaml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ReactiveUIDemo/MainWindow.axaml.cs b/samples/ReactiveUIDemo/MainWindow.axaml.cs
new file mode 100644
index 0000000000..5bf2d476fd
--- /dev/null
+++ b/samples/ReactiveUIDemo/MainWindow.axaml.cs
@@ -0,0 +1,22 @@
+using ReactiveUIDemo.ViewModels;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace ReactiveUIDemo
+{
+ public class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ this.InitializeComponent();
+ this.DataContext = new MainWindowViewModel();
+ this.AttachDevTools();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+ }
+}
diff --git a/samples/ReactiveUIDemo/ReactiveUIDemo.csproj b/samples/ReactiveUIDemo/ReactiveUIDemo.csproj
new file mode 100644
index 0000000000..94ca4ee809
--- /dev/null
+++ b/samples/ReactiveUIDemo/ReactiveUIDemo.csproj
@@ -0,0 +1,28 @@
+
+
+ Exe
+ net6.0
+ enable
+
+
+
+
+
+
+
+
+
+
+ BarView.axaml
+
+
+ FooView.axaml
+
+
+
+
+
+
+
+
+
diff --git a/samples/ReactiveUIDemo/ViewModels/BarViewModel.cs b/samples/ReactiveUIDemo/ViewModels/BarViewModel.cs
new file mode 100644
index 0000000000..3448453d81
--- /dev/null
+++ b/samples/ReactiveUIDemo/ViewModels/BarViewModel.cs
@@ -0,0 +1,11 @@
+using ReactiveUI;
+
+namespace ReactiveUIDemo.ViewModels
+{
+ internal class BarViewModel : ReactiveObject, IRoutableViewModel
+ {
+ public BarViewModel(IScreen screen) => HostScreen = screen;
+ public string UrlPathSegment => "Bar";
+ public IScreen HostScreen { get; }
+ }
+}
diff --git a/samples/ReactiveUIDemo/ViewModels/FooViewModel.cs b/samples/ReactiveUIDemo/ViewModels/FooViewModel.cs
new file mode 100644
index 0000000000..1a363e18dc
--- /dev/null
+++ b/samples/ReactiveUIDemo/ViewModels/FooViewModel.cs
@@ -0,0 +1,11 @@
+using ReactiveUI;
+
+namespace ReactiveUIDemo.ViewModels
+{
+ internal class FooViewModel : ReactiveObject, IRoutableViewModel
+ {
+ public FooViewModel(IScreen screen) => HostScreen = screen;
+ public string UrlPathSegment => "Foo";
+ public IScreen HostScreen { get; }
+ }
+}
diff --git a/samples/ReactiveUIDemo/ViewModels/MainWindowViewModel.cs b/samples/ReactiveUIDemo/ViewModels/MainWindowViewModel.cs
new file mode 100644
index 0000000000..2222137d38
--- /dev/null
+++ b/samples/ReactiveUIDemo/ViewModels/MainWindowViewModel.cs
@@ -0,0 +1,9 @@
+using ReactiveUI;
+
+namespace ReactiveUIDemo.ViewModels
+{
+ internal class MainWindowViewModel : ReactiveObject
+ {
+ public RoutedViewHostPageViewModel RoutedViewHost { get; } = new();
+ }
+}
diff --git a/samples/ReactiveUIDemo/ViewModels/RoutedViewHostPageViewModel.cs b/samples/ReactiveUIDemo/ViewModels/RoutedViewHostPageViewModel.cs
new file mode 100644
index 0000000000..701447cfe8
--- /dev/null
+++ b/samples/ReactiveUIDemo/ViewModels/RoutedViewHostPageViewModel.cs
@@ -0,0 +1,21 @@
+using ReactiveUI;
+
+namespace ReactiveUIDemo.ViewModels
+{
+ internal class RoutedViewHostPageViewModel : ReactiveObject, IScreen
+ {
+ public RoutedViewHostPageViewModel()
+ {
+ Foo = new(this);
+ Bar = new(this);
+ Router.Navigate.Execute(Foo);
+ }
+
+ public RoutingState Router { get; } = new();
+ public FooViewModel Foo { get; }
+ public BarViewModel Bar { get; }
+
+ public void ShowFoo() => Router.Navigate.Execute(Foo);
+ public void ShowBar() => Router.Navigate.Execute(Bar);
+ }
+}
diff --git a/samples/ReactiveUIDemo/Views/BarView.axaml b/samples/ReactiveUIDemo/Views/BarView.axaml
new file mode 100644
index 0000000000..2622245997
--- /dev/null
+++ b/samples/ReactiveUIDemo/Views/BarView.axaml
@@ -0,0 +1,16 @@
+
+
+
+ Bar!
+
+
+
diff --git a/samples/ReactiveUIDemo/Views/BarView.axaml.cs b/samples/ReactiveUIDemo/Views/BarView.axaml.cs
new file mode 100644
index 0000000000..2fbea6de91
--- /dev/null
+++ b/samples/ReactiveUIDemo/Views/BarView.axaml.cs
@@ -0,0 +1,28 @@
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using ReactiveUI;
+using ReactiveUIDemo.ViewModels;
+
+namespace ReactiveUIDemo.Views
+{
+ internal partial class BarView : UserControl, IViewFor
+ {
+ public BarView()
+ {
+ InitializeComponent();
+ }
+
+ public BarViewModel? ViewModel { get; set; }
+
+ object? IViewFor.ViewModel
+ {
+ get => ViewModel;
+ set => ViewModel = (BarViewModel?)value;
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+ }
+}
diff --git a/samples/ReactiveUIDemo/Views/FooView.axaml b/samples/ReactiveUIDemo/Views/FooView.axaml
new file mode 100644
index 0000000000..8f73250d3b
--- /dev/null
+++ b/samples/ReactiveUIDemo/Views/FooView.axaml
@@ -0,0 +1,16 @@
+
+
+
+ Foo!
+
+
+
diff --git a/samples/ReactiveUIDemo/Views/FooView.axaml.cs b/samples/ReactiveUIDemo/Views/FooView.axaml.cs
new file mode 100644
index 0000000000..313a71044c
--- /dev/null
+++ b/samples/ReactiveUIDemo/Views/FooView.axaml.cs
@@ -0,0 +1,28 @@
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using ReactiveUI;
+using ReactiveUIDemo.ViewModels;
+
+namespace ReactiveUIDemo.Views
+{
+ internal partial class FooView : UserControl, IViewFor
+ {
+ public FooView()
+ {
+ InitializeComponent();
+ }
+
+ public FooViewModel? ViewModel { get; set; }
+
+ object? IViewFor.ViewModel
+ {
+ get => ViewModel;
+ set => ViewModel = (FooViewModel?)value;
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+ }
+}
diff --git a/src/Android/Avalonia.Android/AndroidInputMethod.cs b/src/Android/Avalonia.Android/AndroidInputMethod.cs
index b6adbde738..8d56086470 100644
--- a/src/Android/Avalonia.Android/AndroidInputMethod.cs
+++ b/src/Android/Avalonia.Android/AndroidInputMethod.cs
@@ -95,6 +95,10 @@ namespace Avalonia.Android
_imm.UpdateSelection(_host, surroundingText.AnchorOffset, surroundingText.CursorOffset, surroundingText.AnchorOffset, surroundingText.CursorOffset);
}
+ else
+ {
+ _imm.HideSoftInputFromWindow(_host.WindowToken, HideSoftInputFlags.ImplicitOnly);
+ }
}
private void SurroundingTextChanged(object sender, EventArgs e)
diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj
index 6688dde8f5..66557418dd 100644
--- a/src/Android/Avalonia.Android/Avalonia.Android.csproj
+++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj
@@ -16,4 +16,5 @@
+
diff --git a/src/Android/Avalonia.Android/AvaloniaMainActivity.cs b/src/Android/Avalonia.Android/AvaloniaMainActivity.cs
index de8d02f188..b24581fb8b 100644
--- a/src/Android/Avalonia.Android/AvaloniaMainActivity.cs
+++ b/src/Android/Avalonia.Android/AvaloniaMainActivity.cs
@@ -4,9 +4,12 @@ using Android.Content;
using Android.Content.Res;
using Android.OS;
using Android.Runtime;
+using Android.Views;
using AndroidX.AppCompat.App;
using AndroidX.Lifecycle;
+using AndroidRect = Android.Graphics.Rect;
+
namespace Avalonia.Android
{
public abstract class AvaloniaMainActivity : AppCompatActivity, IActivityResultHandler
@@ -15,6 +18,7 @@ namespace Avalonia.Android
public Action ActivityResult { get; set; }
internal AvaloniaView View;
+ private GlobalLayoutListener _listener;
protected override void OnCreate(Bundle savedInstanceState)
{
@@ -32,6 +36,10 @@ namespace Avalonia.Android
base.OnCreate(savedInstanceState);
SetContentView(View);
+
+ _listener = new GlobalLayoutListener(View);
+
+ View.ViewTreeObserver?.AddOnGlobalLayoutListener(_listener);
}
public object Content
@@ -57,6 +65,8 @@ namespace Avalonia.Android
{
View.Content = null;
+ View.ViewTreeObserver?.RemoveOnGlobalLayoutListener(_listener);
+
base.OnDestroy();
}
@@ -66,5 +76,20 @@ namespace Avalonia.Android
ActivityResult?.Invoke(requestCode, resultCode, data);
}
+
+ class GlobalLayoutListener : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener
+ {
+ private AvaloniaView _view;
+
+ public GlobalLayoutListener(AvaloniaView view)
+ {
+ _view = view;
+ }
+
+ public void OnGlobalLayout()
+ {
+ _view.TopLevelImpl?.Resize(_view.TopLevelImpl.ClientSize);
+ }
+ }
}
}
diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
index 5f53eb36c8..4150b52946 100644
--- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
+++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
@@ -26,6 +26,7 @@ using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
using Java.Lang;
using Math = System.Math;
+using AndroidRect = Android.Graphics.Rect;
namespace Avalonia.Android.Platform.SkiaPlatform
{
@@ -63,7 +64,21 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public IInputRoot InputRoot { get; private set; }
- public virtual Size ClientSize => Size.ToSize(RenderScaling);
+ public virtual Size ClientSize
+ {
+ get
+ {
+ AndroidRect rect = new AndroidRect();
+ AndroidRect intersection = new AndroidRect();
+
+ _view.GetWindowVisibleDisplayFrame(intersection);
+ _view.GetGlobalVisibleRect(rect);
+
+ intersection.Intersect(rect);
+
+ return new PixelSize(intersection.Right - intersection.Left, intersection.Bottom - intersection.Top).ToSize(RenderScaling);
+ }
+ }
public Size? FrameSize => null;
@@ -94,7 +109,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
? new CompositingRenderer(root, AndroidPlatform.Compositor)
: AndroidPlatform.Options.UseDeferredRendering
? new DeferredRenderer(root, AvaloniaLocator.Current.GetRequiredService()) { RenderOnlyOnRenderThread = true }
- : new ImmediateRenderer(root);
+ : new ImmediateRenderer((Visual)root);
public virtual void Hide()
{
@@ -149,6 +164,11 @@ namespace Avalonia.Android.Platform.SkiaPlatform
Resized?.Invoke(size, PlatformResizeReason.Unspecified);
}
+ internal void Resize(Size size)
+ {
+ Resized?.Invoke(size, PlatformResizeReason.Layout);
+ }
+
class ViewImpl : InvalidationAwareSurfaceView, ISurfaceHolderCallback, IInitEditorInfo
{
private readonly TopLevelImpl _tl;
diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs
index 57f6469a42..bc24a16e56 100644
--- a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs
+++ b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs
@@ -30,7 +30,7 @@ namespace Avalonia.Android.Platform.Specific.Helpers
return DispatchKeyEventInternal(e, out callBase);
}
- string UnicodeTextInput(KeyEvent keyEvent)
+ static string UnicodeTextInput(KeyEvent keyEvent)
{
return keyEvent.Action == KeyEventActions.Multiple
&& keyEvent.RepeatCount == 0
diff --git a/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs b/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs
index a9b2e16d43..078f70db60 100644
--- a/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs
+++ b/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs
@@ -178,7 +178,7 @@ internal sealed class AndroidStorageFile : AndroidStorageItem, IStorageBookmarkF
return false;
}
- private Stream? GetVirtualFileStream(Context context, AndroidUri uri, bool isOutput)
+ private static Stream? GetVirtualFileStream(Context context, AndroidUri uri, bool isOutput)
{
var mimeTypes = context.ContentResolver?.GetStreamTypes(uri, FilePickerFileTypes.All.MimeTypes![0]);
if (mimeTypes?.Length >= 1)
diff --git a/src/Avalonia.Base/Animation/Animation.cs b/src/Avalonia.Base/Animation/Animation.cs
index e0883901fd..06087cdd6a 100644
--- a/src/Avalonia.Base/Animation/Animation.cs
+++ b/src/Avalonia.Base/Animation/Animation.cs
@@ -202,9 +202,7 @@ namespace Avalonia.Animation
/// The animation setter.
/// The property animator value.
public static void SetAnimator(IAnimationSetter setter,
-#if NET6_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicMethods)]
-#endif
Type value)
{
s_animators[setter] = (value, () => (IAnimator)Activator.CreateInstance(value)!);
diff --git a/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs b/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs
index 0356723f00..3168a67d79 100644
--- a/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs
+++ b/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
using Avalonia.Animation.Animators;
using Avalonia.Data;
using Avalonia.Reactive;
@@ -66,7 +67,8 @@ namespace Avalonia.Animation
}
}
- public T GetTypedValue()
+ [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)]
+ public T GetTypedValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
{
var typeConv = TypeDescriptor.GetConverter(typeof(T));
diff --git a/src/Avalonia.Base/Animation/Animators/Animator`1.cs b/src/Avalonia.Base/Animation/Animators/Animator`1.cs
index 8765cfb4c9..b5d1feb4a7 100644
--- a/src/Avalonia.Base/Animation/Animators/Animator`1.cs
+++ b/src/Avalonia.Base/Animation/Animators/Animator`1.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Reactive.Disposables;
using System.Reactive.Linq;
using Avalonia.Animation.Utils;
using Avalonia.Collections;
@@ -39,7 +40,7 @@ namespace Avalonia.Animation.Animators
VerifyConvertKeyFrames();
var subject = new DisposeAnimationInstanceSubject(this, animation, control, clock, onComplete);
- return match.Subscribe(subject);
+ return new CompositeDisposable(match.Subscribe(subject), subject);
}
protected T InterpolationHandler(double animationTime, T neutralValue)
diff --git a/src/Avalonia.Base/Animation/Animators/GradientBrushAnimator.cs b/src/Avalonia.Base/Animation/Animators/GradientBrushAnimator.cs
index 4727ea1bfb..068c190fa1 100644
--- a/src/Avalonia.Base/Animation/Animators/GradientBrushAnimator.cs
+++ b/src/Avalonia.Base/Animation/Animators/GradientBrushAnimator.cs
@@ -72,7 +72,7 @@ namespace Avalonia.Animation.Animators
return control.Bind((AvaloniaProperty)Property, instance, BindingPriority.Animation);
}
- private IReadOnlyList InterpolateStops(double progress, IReadOnlyList oldValue, IReadOnlyList newValue)
+ private static IReadOnlyList InterpolateStops(double progress, IReadOnlyList oldValue, IReadOnlyList newValue)
{
var resultCount = Math.Max(oldValue.Count, newValue.Count);
var stops = new ImmutableGradientStop[resultCount];
diff --git a/src/Avalonia.Base/Animation/CrossFade.cs b/src/Avalonia.Base/Animation/CrossFade.cs
index 608a0880ec..a229bc7ce6 100644
--- a/src/Avalonia.Base/Animation/CrossFade.cs
+++ b/src/Avalonia.Base/Animation/CrossFade.cs
@@ -10,7 +10,7 @@ using Avalonia.VisualTree;
namespace Avalonia.Animation
{
///
- /// Defines a cross-fade animation between two s.
+ /// Defines a cross-fade animation between two s.
///
public class CrossFade : IPageTransition
{
diff --git a/src/Avalonia.Base/Animation/KeySpline.cs b/src/Avalonia.Base/Animation/KeySpline.cs
index a6e9769186..6ca5b2e759 100644
--- a/src/Avalonia.Base/Animation/KeySpline.cs
+++ b/src/Avalonia.Base/Animation/KeySpline.cs
@@ -196,7 +196,7 @@ namespace Avalonia.Animation
///
///
///
- private bool IsValidXValue(double value)
+ private static bool IsValidXValue(double value)
{
return value >= 0.0 && value <= 1.0;
}
diff --git a/src/Avalonia.Base/Animation/PageSlide.cs b/src/Avalonia.Base/Animation/PageSlide.cs
index b22bc8b243..609441ae8c 100644
--- a/src/Avalonia.Base/Animation/PageSlide.cs
+++ b/src/Avalonia.Base/Animation/PageSlide.cs
@@ -157,7 +157,7 @@ namespace Avalonia.Animation
///
/// Any one of the parameters may be null, but not both.
///
- protected static IVisual GetVisualParent(IVisual? from, IVisual? to)
+ protected static Visual GetVisualParent(Visual? from, Visual? to)
{
var p1 = (from ?? to)!.VisualParent;
var p2 = (to ?? from)!.VisualParent;
diff --git a/src/Avalonia.Base/AttachedProperty.cs b/src/Avalonia.Base/AttachedProperty.cs
index 12c569c452..a43194153c 100644
--- a/src/Avalonia.Base/AttachedProperty.cs
+++ b/src/Avalonia.Base/AttachedProperty.cs
@@ -34,7 +34,7 @@ namespace Avalonia
///
/// The owner type.
/// The property.
- public new AttachedProperty AddOwner() where TOwner : IAvaloniaObject
+ public new AttachedProperty AddOwner() where TOwner : AvaloniaObject
{
AvaloniaPropertyRegistry.Instance.Register(typeof(TOwner), this);
return this;
diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj
index 21bdb794b3..0d3da66f7a 100644
--- a/src/Avalonia.Base/Avalonia.Base.csproj
+++ b/src/Avalonia.Base/Avalonia.Base.csproj
@@ -19,6 +19,7 @@
+
@@ -30,6 +31,8 @@
+
+
@@ -41,6 +44,7 @@
+
@@ -48,14 +52,10 @@
-
+
-
diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs
index 68c8f19f19..a3a732428e 100644
--- a/src/Avalonia.Base/AvaloniaObject.cs
+++ b/src/Avalonia.Base/AvaloniaObject.cs
@@ -16,7 +16,7 @@ namespace Avalonia
///
/// This class is analogous to DependencyObject in WPF.
///
- public class AvaloniaObject : IAvaloniaObject, IAvaloniaObjectDebug, INotifyPropertyChanged
+ public class AvaloniaObject : IAvaloniaObjectDebug, INotifyPropertyChanged
{
private readonly ValueStore _values;
private AvaloniaObject? _inheritanceParent;
diff --git a/src/Avalonia.Base/AvaloniaObjectExtensions.cs b/src/Avalonia.Base/AvaloniaObjectExtensions.cs
index 9644063da7..867d6215a5 100644
--- a/src/Avalonia.Base/AvaloniaObjectExtensions.cs
+++ b/src/Avalonia.Base/AvaloniaObjectExtensions.cs
@@ -36,7 +36,7 @@ namespace Avalonia
///
/// The subscription to is created using a weak reference.
///
- public static IObservable