diff --git a/.editorconfig b/.editorconfig
index b39bbc2f71..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,12 +137,20 @@ 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
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 1b822c14cf..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)"
+ >
@@ -81,7 +85,12 @@
$(IntermediateOutputPath)/Avalonia/references
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/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/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.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/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/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/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/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/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/AvaloniaProperty.cs b/src/Avalonia.Base/AvaloniaProperty.cs
index 2c89062e51..e0782c51a2 100644
--- a/src/Avalonia.Base/AvaloniaProperty.cs
+++ b/src/Avalonia.Base/AvaloniaProperty.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using Avalonia.Data;
using Avalonia.Data.Core;
using Avalonia.PropertyStore;
@@ -442,6 +443,7 @@ namespace Avalonia
///
/// The value.
/// True if the value is valid, otherwise false.
+ [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)]
public bool IsValidValue(object? value)
{
return TypeUtilities.TryConvertImplicit(PropertyType, value, out _);
diff --git a/src/Avalonia.Base/AvaloniaPropertyRegistry.cs b/src/Avalonia.Base/AvaloniaPropertyRegistry.cs
index 6106c58880..fc0ca2323e 100644
--- a/src/Avalonia.Base/AvaloniaPropertyRegistry.cs
+++ b/src/Avalonia.Base/AvaloniaPropertyRegistry.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Avalonia
@@ -42,6 +43,7 @@ namespace Avalonia
///
/// The type.
/// A collection of definitions.
+ [UnconditionalSuppressMessage("Trimming", "IL2059", Justification = "If type was trimmed out, no properties were referenced")]
public IReadOnlyList GetRegistered(Type type)
{
_ = type ?? throw new ArgumentNullException(nameof(type));
diff --git a/src/Avalonia.Base/AvaloniaProperty`1.cs b/src/Avalonia.Base/AvaloniaProperty`1.cs
index 5a0d69f3bf..53444ee475 100644
--- a/src/Avalonia.Base/AvaloniaProperty`1.cs
+++ b/src/Avalonia.Base/AvaloniaProperty`1.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Reactive.Subjects;
using Avalonia.Data;
using Avalonia.Utilities;
@@ -67,6 +68,7 @@ namespace Avalonia
protected override IObservable GetChanged() => Changed;
+ [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)]
protected BindingValue
@@ -111,6 +111,7 @@
Markup/%(RecursiveDir)%(FileName)%(Extension)
+
diff --git a/src/Avalonia.Build.Tasks/BuildEngineErrorCode.cs b/src/Avalonia.Build.Tasks/BuildEngineErrorCode.cs
index a149a758f4..a31c9a7516 100644
--- a/src/Avalonia.Build.Tasks/BuildEngineErrorCode.cs
+++ b/src/Avalonia.Build.Tasks/BuildEngineErrorCode.cs
@@ -7,6 +7,7 @@ namespace Avalonia.Build.Tasks
LegacyResmScheme = 3,
TransformError = 4,
EmitError = 4,
+ Loader = 5,
Unknown = 9999
}
diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
index ea2cf2cf99..a394d47904 100644
--- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
+++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
@@ -196,7 +196,8 @@ namespace Avalonia.Build.Tasks
var runtimeHelpers = typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");
var createRootServiceProviderMethod = asm.MainModule.ImportReference(
typeSystem.GetTypeReference(runtimeHelpers).Resolve().Methods
- .First(x => x.Name == "CreateRootServiceProviderV2"));
+ .First(x => x.Name == "CreateRootServiceProviderV3"));
+ var serviceProviderType = createRootServiceProviderMethod.ReturnType;
var loaderDispatcherDef = new TypeDefinition(CompiledAvaloniaXamlNamespace, "!XamlLoader",
TypeAttributes.Class | TypeAttributes.Public, asm.MainModule.TypeSystem.Object);
@@ -212,11 +213,36 @@ namespace Avalonia.Build.Tasks
MethodAttributes.Static | MethodAttributes.Public,
asm.MainModule.TypeSystem.Object)
{
- Parameters = {new ParameterDefinition(asm.MainModule.TypeSystem.String)}
+ Parameters =
+ {
+ new ParameterDefinition(serviceProviderType),
+ new ParameterDefinition(asm.MainModule.TypeSystem.String)
+ },
+ };
+ var loaderDispatcherMethodOld = new MethodDefinition("TryLoad",
+ MethodAttributes.Static | MethodAttributes.Public,
+ asm.MainModule.TypeSystem.Object)
+ {
+ Parameters =
+ {
+ new ParameterDefinition(asm.MainModule.TypeSystem.String)
+ },
+ Body =
+ {
+ Instructions =
+ {
+ Instruction.Create(OpCodes.Ldnull),
+ Instruction.Create(OpCodes.Ldarg_0),
+ Instruction.Create(OpCodes.Call, loaderDispatcherMethod),
+ Instruction.Create(OpCodes.Ret)
+ }
+ }
};
loaderDispatcherDef.Methods.Add(loaderDispatcherMethod);
+ loaderDispatcherDef.Methods.Add(loaderDispatcherMethodOld);
asm.MainModule.Types.Add(loaderDispatcherDef);
+
var stringEquals = asm.MainModule.ImportReference(asm.MainModule.TypeSystem.String.Resolve().Methods.First(
m =>
m.IsStatic && m.Name == "Equals" && m.Parameters.Count == 3 &&
@@ -377,30 +403,42 @@ namespace Avalonia.Build.Tasks
classTypeDefinition.Fields.Add(designLoaderField);
const string TrampolineName = "!XamlIlPopulateTrampoline";
- var trampoline = new MethodDefinition(TrampolineName,
- MethodAttributes.Static | MethodAttributes.Private, asm.MainModule.TypeSystem.Void);
- trampoline.Parameters.Add(new ParameterDefinition(classTypeDefinition));
- classTypeDefinition.Methods.Add(trampoline);
+ var trampolineMethodWithoutSP = new Lazy(() => CreateTrampolineMethod(false));
+ var trampolineMethodWithSP = new Lazy(() => CreateTrampolineMethod(true));
+ MethodDefinition CreateTrampolineMethod(bool hasSystemProviderArg)
+ {
+ var trampoline = new MethodDefinition(TrampolineName,
+ MethodAttributes.Static | MethodAttributes.Private, asm.MainModule.TypeSystem.Void);
+ if (hasSystemProviderArg)
+ {
+ trampoline.Parameters.Add(new ParameterDefinition(serviceProviderType));
+ }
+ trampoline.Parameters.Add(new ParameterDefinition(classTypeDefinition));
+
+ classTypeDefinition.Methods.Add(trampoline);
- var regularStart = Instruction.Create(OpCodes.Call, createRootServiceProviderMethod);
+ var regularStart = Instruction.Create(OpCodes.Nop);
- trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
- trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Brfalse, regularStart));
- trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
- trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
- trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, designLoaderLoad));
- trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Brfalse, regularStart));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
+ trampoline.Body.Instructions.Add(Instruction.Create(hasSystemProviderArg ? OpCodes.Ldarg_1 : OpCodes.Ldarg_0));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, designLoaderLoad));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
- trampoline.Body.Instructions.Add(regularStart);
- trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
- trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, compiledPopulateMethod));
- trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
- CopyDebugDocument(trampoline, compiledPopulateMethod);
+ trampoline.Body.Instructions.Add(regularStart);
+ trampoline.Body.Instructions.Add(Instruction.Create(hasSystemProviderArg ? OpCodes.Ldarg_0 : OpCodes.Ldnull));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, createRootServiceProviderMethod));
+ trampoline.Body.Instructions.Add(Instruction.Create(hasSystemProviderArg ? OpCodes.Ldarg_1 : OpCodes.Ldarg_0));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, compiledPopulateMethod));
+ trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
+ CopyDebugDocument(trampoline, compiledPopulateMethod);
+ return trampoline;
+ }
var foundXamlLoader = false;
- // Find AvaloniaXamlLoader.Load(this) and replace it with !XamlIlPopulateTrampoline(this)
- foreach (var method in classTypeDefinition.Methods
- .Where(m => !m.Attributes.HasFlag(MethodAttributes.Static)))
+ // Find AvaloniaXamlLoader.Load(this) or AvaloniaXamlLoader.Load(sp, this) and replace it with !XamlIlPopulateTrampoline(this)
+ foreach (var method in classTypeDefinition.Methods.ToArray())
{
var i = method.Body.Instructions;
for (var c = 1; c < i.Count; c++)
@@ -422,7 +460,20 @@ namespace Avalonia.Build.Tasks
{
if (MatchThisCall(i, c - 1))
{
- i[c].Operand = trampoline;
+ i[c].Operand = trampolineMethodWithoutSP.Value;
+ foundXamlLoader = true;
+ }
+ }
+ if (op != null
+ && op.Name == "Load"
+ && op.Parameters.Count == 2
+ && op.Parameters[0].ParameterType.FullName == "System.IServiceProvider"
+ && op.Parameters[1].ParameterType.FullName == "System.Object"
+ && op.DeclaringType.FullName == "Avalonia.Markup.Xaml.AvaloniaXamlLoader")
+ {
+ if (MatchThisCall(i, c - 1))
+ {
+ i[c].Operand = trampolineMethodWithSP.Value;
foundXamlLoader = true;
}
}
@@ -439,7 +490,7 @@ namespace Avalonia.Build.Tasks
{
var i = ctors[0].Body.Instructions;
var retIdx = i.IndexOf(i.Last(x => x.OpCode == OpCodes.Ret));
- i.Insert(retIdx, Instruction.Create(OpCodes.Call, trampoline));
+ i.Insert(retIdx, Instruction.Create(OpCodes.Call, trampolineMethodWithoutSP.Value));
i.Insert(retIdx, Instruction.Create(OpCodes.Ldarg_0));
}
else
@@ -461,20 +512,33 @@ namespace Avalonia.Build.Tasks
null :
classTypeDefinition.GetConstructors().FirstOrDefault(c =>
c.IsPublic && !c.IsStatic && !c.HasParameters);
+ var constructorWithSp = compiledBuildMethod != null ?
+ null :
+ classTypeDefinition.GetConstructors().FirstOrDefault(c =>
+ c.IsPublic && !c.IsStatic && c.Parameters.Count == 1 && c.Parameters[0].ParameterType.FullName == serviceProviderType.FullName);
- if (compiledBuildMethod != null || parameterlessConstructor != null)
+ if (compiledBuildMethod != null || parameterlessConstructor != null || constructorWithSp != null)
{
var i = loaderDispatcherMethod.Body.Instructions;
var nop = Instruction.Create(OpCodes.Nop);
- i.Add(Instruction.Create(OpCodes.Ldarg_0));
+ i.Add(Instruction.Create(OpCodes.Ldarg_1));
i.Add(Instruction.Create(OpCodes.Ldstr, res.Uri));
i.Add(Instruction.Create(OpCodes.Ldc_I4, (int)StringComparison.OrdinalIgnoreCase));
i.Add(Instruction.Create(OpCodes.Call, stringEquals));
i.Add(Instruction.Create(OpCodes.Brfalse, nop));
if (parameterlessConstructor != null)
+ {
i.Add(Instruction.Create(OpCodes.Newobj, parameterlessConstructor));
+ }
+ else if (constructorWithSp != null)
+ {
+ i.Add(Instruction.Create(OpCodes.Ldarg_0));
+ i.Add(Instruction.Create(OpCodes.Call, createRootServiceProviderMethod));
+ i.Add(Instruction.Create(OpCodes.Newobj, constructorWithSp));
+ }
else
{
+ i.Add(Instruction.Create(OpCodes.Ldarg_0));
i.Add(Instruction.Create(OpCodes.Call, createRootServiceProviderMethod));
i.Add(Instruction.Create(OpCodes.Call, compiledBuildMethod));
}
@@ -482,6 +546,11 @@ namespace Avalonia.Build.Tasks
i.Add(Instruction.Create(OpCodes.Ret));
i.Add(nop);
}
+ else
+ {
+ engine.LogWarning(BuildEngineErrorCode.Loader, "",
+ $"XAML resource \"{res.Uri}\" won't be reachable via runtime loader, as no public constructor was found");
+ }
}
}
diff --git a/src/Avalonia.Controls.ColorPicker/Avalonia.Controls.ColorPicker.csproj b/src/Avalonia.Controls.ColorPicker/Avalonia.Controls.ColorPicker.csproj
index e0790795c5..f3f8e4c82c 100644
--- a/src/Avalonia.Controls.ColorPicker/Avalonia.Controls.ColorPicker.csproj
+++ b/src/Avalonia.Controls.ColorPicker/Avalonia.Controls.ColorPicker.csproj
@@ -21,6 +21,7 @@
+
diff --git a/src/Avalonia.Controls.ColorPicker/ColorSlider/ColorSlider.cs b/src/Avalonia.Controls.ColorPicker/ColorSlider/ColorSlider.cs
index ec08e96d87..be320246b3 100644
--- a/src/Avalonia.Controls.ColorPicker/ColorSlider/ColorSlider.cs
+++ b/src/Avalonia.Controls.ColorPicker/ColorSlider/ColorSlider.cs
@@ -154,7 +154,7 @@ namespace Avalonia.Controls.Primitives
///
/// The to round component values for.
/// A new with rounded component values.
- private HsvColor RoundComponentValues(HsvColor hsvColor)
+ private static HsvColor RoundComponentValues(HsvColor hsvColor)
{
return new HsvColor(
Math.Round(hsvColor.A, 2, MidpointRounding.AwayFromZero),
diff --git a/src/Avalonia.Controls.ColorPicker/ColorSpectrum/ColorSpectrum.cs b/src/Avalonia.Controls.ColorPicker/ColorSpectrum/ColorSpectrum.cs
index f0ed89fb3a..2df46889a9 100644
--- a/src/Avalonia.Controls.ColorPicker/ColorSpectrum/ColorSpectrum.cs
+++ b/src/Avalonia.Controls.ColorPicker/ColorSpectrum/ColorSpectrum.cs
@@ -1146,7 +1146,7 @@ namespace Avalonia.Controls.Primitives
});
}
- private void FillPixelForBox(
+ private static void FillPixelForBox(
double x,
double y,
Hsv baseHsv,
diff --git a/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs
index ba285a701c..3ec78d6d6a 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs
@@ -56,7 +56,7 @@ namespace Avalonia.Controls
set => SetAndRaise(CellEditingTemplateProperty, ref _cellEditingCellTemplate, value);
}
- private void OnCellTemplateChanged(AvaloniaPropertyChangedEventArgs e)
+ private static void OnCellTemplateChanged(AvaloniaPropertyChangedEventArgs e)
{
var oldValue = (IDataTemplate)e.OldValue;
var value = (IDataTemplate)e.NewValue;
diff --git a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml
index a3c0ed1d0c..fb4335f4de 100644
--- a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml
+++ b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml
@@ -6,8 +6,8 @@
M1875 1011l-787 787v-1798h-128v1798l-787 -787l-90 90l941 941l941 -941z
M1965 947l-941 -941l-941 941l90 90l787 -787v1798h128v-1798l787 787z
- M515 93l930 931l-930 931l90 90l1022 -1021l-1022 -1021z
- M109 486 19 576 1024 1581 2029 576 1939 486 1024 1401z
+ M515 93l930 931l-930 931l90 90l1022 -1021l-1022 -1021z
+ M109 486 19 576 1024 1581 2029 576 1939 486 1024 1401z
diff --git a/src/Avalonia.Controls/AppBuilderBase.cs b/src/Avalonia.Controls/AppBuilderBase.cs
index 1dfad7dcc5..604f2369e7 100644
--- a/src/Avalonia.Controls/AppBuilderBase.cs
+++ b/src/Avalonia.Controls/AppBuilderBase.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Linq;
using Avalonia.Controls.ApplicationLifetimes;
@@ -162,13 +163,6 @@ namespace Avalonia.Controls
return Self;
}
- ///
- /// Specifies a windowing subsystem to use.
- ///
- /// The dll in which to look for subsystem.
- /// An instance.
- public TAppBuilder UseWindowingSubsystem(string dll) => UseWindowingSubsystem(GetInitializer(dll), dll.Replace("Avalonia.", string.Empty));
-
///
/// Specifies a rendering subsystem to use.
///
@@ -182,50 +176,8 @@ namespace Avalonia.Controls
return Self;
}
- ///
- /// Specifies a rendering subsystem to use.
- ///
- /// The dll in which to look for subsystem.
- /// An instance.
- public TAppBuilder UseRenderingSubsystem(string dll) => UseRenderingSubsystem(GetInitializer(dll));
-
- static Action GetInitializer(string assemblyName) => () =>
- {
- var assembly = Assembly.Load(new AssemblyName(assemblyName));
- var platformClassName = assemblyName.Replace("Avalonia.", string.Empty) + "Platform";
- var platformClassFullName = assemblyName + "." + platformClassName;
- var platformClass = assembly.GetType(platformClassFullName);
- var init = platformClass!.GetRuntimeMethod("Initialize", Type.EmptyTypes);
- init!.Invoke(null, null);
- };
-
- public TAppBuilder UseAvaloniaModules() => AfterSetup(builder => SetupAvaloniaModules());
-
protected virtual bool CheckSetup => true;
- ///
- /// Searches and initiates modules included with attribute.
- ///
- private void SetupAvaloniaModules()
- {
- var moduleInitializers = from assembly in AppDomain.CurrentDomain.GetAssemblies()
- from attribute in assembly.GetCustomAttributes()
- where string.IsNullOrEmpty(attribute.ForWindowingSubsystem)
- || attribute.ForWindowingSubsystem == WindowingSubsystemName
- where string.IsNullOrEmpty(attribute.ForRenderingSubsystem)
- || attribute.ForRenderingSubsystem == RenderingSubsystemName
- group attribute by attribute.Name into exports
- select (from export in exports
- orderby export.ForWindowingSubsystem.Length descending
- orderby export.ForRenderingSubsystem.Length descending
- select export).First().ModuleType into moduleType
- select (from constructor in moduleType.GetTypeInfo().DeclaredConstructors
- where constructor.GetParameters().Length == 0 && !constructor.IsStatic
- select constructor).Single() into constructor
- select (Action)(() => constructor.Invoke(Array.Empty()));
- Delegate.Combine(moduleInitializers.ToArray())!.DynamicInvoke();
- }
-
///
/// Configures platform-specific options
///
diff --git a/src/Avalonia.Controls/Automation/Peers/ComboBoxAutomationPeer.cs b/src/Avalonia.Controls/Automation/Peers/ComboBoxAutomationPeer.cs
index 5ff291d972..5d71e7a8e4 100644
--- a/src/Avalonia.Controls/Automation/Peers/ComboBoxAutomationPeer.cs
+++ b/src/Avalonia.Controls/Automation/Peers/ComboBoxAutomationPeer.cs
@@ -71,7 +71,7 @@ namespace Avalonia.Automation.Peers
}
}
- private ExpandCollapseState ToState(bool value)
+ private static ExpandCollapseState ToState(bool value)
{
return value ? ExpandCollapseState.Expanded : ExpandCollapseState.Collapsed;
}
diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj
index c4587a2d9c..2710ac5cc2 100644
--- a/src/Avalonia.Controls/Avalonia.Controls.csproj
+++ b/src/Avalonia.Controls/Avalonia.Controls.csproj
@@ -10,6 +10,7 @@
+
diff --git a/src/Avalonia.Controls/Calendar/CalendarBlackoutDatesCollection.cs b/src/Avalonia.Controls/Calendar/CalendarBlackoutDatesCollection.cs
index a92feec509..fe8b616e02 100644
--- a/src/Avalonia.Controls/Calendar/CalendarBlackoutDatesCollection.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarBlackoutDatesCollection.cs
@@ -206,7 +206,7 @@ namespace Avalonia.Controls.Primitives
return true;
}
- private void EnsureValidThread()
+ private static void EnsureValidThread()
{
Dispatcher.UIThread.VerifyAccess();
}
diff --git a/src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs b/src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs
index 211b5edb0d..ac4159d536 100644
--- a/src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs
+++ b/src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs
@@ -6,7 +6,6 @@
using Avalonia.Threading;
using System;
using System.Collections.ObjectModel;
-using System.Threading;
namespace Avalonia.Controls.Primitives
{
@@ -353,7 +352,7 @@ namespace Avalonia.Controls.Primitives
return true;
}
- private void EnsureValidThread()
+ private static void EnsureValidThread()
{
Dispatcher.UIThread.VerifyAccess();
}
diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs
index 2b407cc42a..f02df2e9c1 100644
--- a/src/Avalonia.Controls/ComboBox.cs
+++ b/src/Avalonia.Controls/ComboBox.cs
@@ -454,10 +454,9 @@ namespace Avalonia.Controls
{
if (SelectionBoxItem is Rectangle rectangle)
{
- if ((rectangle.Fill as VisualBrush)?.Visual is Control content)
+ if ((rectangle.Fill as VisualBrush)?.Visual is Visual content)
{
- var flowDirection = (((Visual)content!).VisualParent as Control)?.FlowDirection ??
- FlowDirection.LeftToRight;
+ var flowDirection = content.VisualParent?.FlowDirection ?? FlowDirection.LeftToRight;
rectangle.FlowDirection = flowDirection;
}
}
diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs
index 063e6ae7c8..88c9823952 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -91,13 +91,6 @@ namespace Avalonia.Controls
RoutedEvent.Register(
nameof(SizeChanged), RoutingStrategies.Direct);
- ///
- /// Defines the property.
- ///
- public static readonly AttachedProperty FlowDirectionProperty =
- AvaloniaProperty.RegisterAttached(
- nameof(FlowDirection),
- inherits: true);
// Note the following:
// _loadedQueue :
@@ -170,15 +163,6 @@ namespace Avalonia.Controls
get => GetValue(TagProperty);
set => SetValue(TagProperty, value);
}
-
- ///
- /// Gets or sets the text flow direction.
- ///
- public FlowDirection FlowDirection
- {
- get => GetValue(FlowDirectionProperty);
- set => SetValue(FlowDirectionProperty, value);
- }
///
/// Occurs when the user has completed a context input gesture, such as a right-click.
@@ -229,39 +213,9 @@ namespace Avalonia.Controls
public new Control? Parent => (Control?)base.Parent;
- ///
- /// Gets the value of the attached on a control.
- ///
- /// The control.
- /// The flow direction.
- public static FlowDirection GetFlowDirection(Control control)
- {
- return control.GetValue(FlowDirectionProperty);
- }
-
- ///
- /// Sets the value of the attached on a control.
- ///
- /// The control.
- /// The property value to set.
- public static void SetFlowDirection(Control control, FlowDirection value)
- {
- control.SetValue(FlowDirectionProperty, value);
- }
-
///
bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
- ///
- /// Gets a value indicating whether control bypass FlowDirecton policies.
- ///
- ///
- /// Related to FlowDirection system and returns false as default, so if
- /// is RTL then control will get a mirror presentation.
- /// For controls that want to avoid this behavior, override this property and return true.
- ///
- protected virtual bool BypassFlowDirectionPolicies => false;
-
///
void ISetterValue.Initialize(ISetter setter)
{
@@ -571,45 +525,6 @@ namespace Avalonia.Controls
RaiseEvent(sizeChangedEventArgs);
}
}
- else if (change.Property == FlowDirectionProperty)
- {
- InvalidateMirrorTransform();
-
- foreach (var visual in VisualChildren)
- {
- if (visual is Control child)
- {
- child.InvalidateMirrorTransform();
- }
- }
- }
- }
-
- ///
- /// Computes the value according to the
- /// and
- ///
- public virtual void InvalidateMirrorTransform()
- {
- var flowDirection = this.FlowDirection;
- var parentFlowDirection = FlowDirection.LeftToRight;
-
- bool bypassFlowDirectionPolicies = BypassFlowDirectionPolicies;
- bool parentBypassFlowDirectionPolicies = false;
-
- var parent = this.VisualParent as Control;
- if (parent != null)
- {
- parentFlowDirection = parent.FlowDirection;
- parentBypassFlowDirectionPolicies = parent.BypassFlowDirectionPolicies;
- }
-
- bool thisShouldBeMirrored = flowDirection == FlowDirection.RightToLeft && !bypassFlowDirectionPolicies;
- bool parentShouldBeMirrored = parentFlowDirection == FlowDirection.RightToLeft && !parentBypassFlowDirectionPolicies;
-
- bool shouldApplyMirrorTransform = thisShouldBeMirrored != parentShouldBeMirrored;
-
- HasMirrorTransform = shouldApplyMirrorTransform;
}
}
}
diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs
index 8d246d35f4..7737fdac2e 100644
--- a/src/Avalonia.Controls/Grid.cs
+++ b/src/Avalonia.Controls/Grid.cs
@@ -1165,7 +1165,7 @@ namespace Avalonia.Controls
///
/// For "Auto" definitions MinWidth is used in place of PreferredSize.
///
- private double GetMeasureSizeForRange(
+ private static double GetMeasureSizeForRange(
IReadOnlyList definitions,
int start,
int count)
@@ -1192,7 +1192,7 @@ namespace Avalonia.Controls
/// Starting index of the range.
/// Number of definitions included in the range.
/// Length type for given range.
- private LayoutTimeSizeType GetLengthTypeForRange(
+ private static LayoutTimeSizeType GetLengthTypeForRange(
IReadOnlyList definitions,
int start,
int count)
@@ -1721,7 +1721,7 @@ namespace Avalonia.Controls
///
/// Array of definitions to use for calculations.
/// Desired size.
- private double CalculateDesiredSize(
+ private static double CalculateDesiredSize(
IReadOnlyList definitions)
{
double desiredSize = 0;
@@ -2281,7 +2281,7 @@ namespace Avalonia.Controls
/// Start of the range.
/// Number of items in the range.
/// Final size.
- private double GetFinalSizeForRange(
+ private static double GetFinalSizeForRange(
IReadOnlyList definitions,
int start,
int count)
diff --git a/src/Avalonia.Controls/GridSplitter.cs b/src/Avalonia.Controls/GridSplitter.cs
index 9bdefed6b6..4684304725 100644
--- a/src/Avalonia.Controls/GridSplitter.cs
+++ b/src/Avalonia.Controls/GridSplitter.cs
@@ -516,7 +516,7 @@ namespace Avalonia.Controls
///
/// Retrieves the ActualWidth or ActualHeight of the definition depending on its type Column or Row.
///
- private double GetActualLength(DefinitionBase definition)
+ private static double GetActualLength(DefinitionBase definition)
{
var column = definition as ColumnDefinition;
diff --git a/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs b/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs
index 4cc6a20082..381f1799d4 100644
--- a/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs
+++ b/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Controls
///
/// The registered access keys.
///
- private readonly List> _registered = new List>();
+ private readonly List<(string AccessKey, IInputElement Element)> _registered = new();
///
/// The window to which the handler belongs.
@@ -59,12 +59,12 @@ namespace Avalonia.Controls
{
var existing = _registered.FirstOrDefault(x => x.Item2 == element);
- if (existing != null)
+ if (existing != default)
{
_registered.Remove(existing);
}
- _registered.Add(Tuple.Create(accessKey.ToString().ToUpper(), element));
+ _registered.Add((accessKey.ToString().ToUpperInvariant(), element));
}
///
@@ -88,9 +88,10 @@ namespace Avalonia.Controls
{
if (!string.IsNullOrWhiteSpace(e.Text))
{
- var text = e.Text.ToUpper();
+ var text = e.Text;
var focus = _registered
- .FirstOrDefault(x => x.Item1 == text && x.Item2.IsEffectivelyVisible)?.Item2;
+ .FirstOrDefault(x => string.Equals(x.AccessKey, text, StringComparison.OrdinalIgnoreCase)
+ && x.Element.IsEffectivelyVisible).Element;
focus?.RaiseEvent(new RoutedEventArgs(AccessKeyHandler.AccessKeyPressedEvent));
diff --git a/src/Avalonia.Controls/NativeMenuBar.cs b/src/Avalonia.Controls/NativeMenuBar.cs
index ae473f8500..8b3e875e5a 100644
--- a/src/Avalonia.Controls/NativeMenuBar.cs
+++ b/src/Avalonia.Controls/NativeMenuBar.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using Avalonia.Controls.Primitives;
using Avalonia.Interactivity;
@@ -21,7 +22,16 @@ namespace Avalonia.Controls
item.Click -= OnMenuItemClick;
});
}
-
+
+ [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NativeMenu))]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NativeMenuItem))]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NativeMenuItemBase))]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NativeMenuItemSeparator))]
+ public NativeMenuBar()
+ {
+
+ }
+
public static void SetEnableMenuItemClickForwarding(MenuItem menuItem, bool enable)
{
menuItem.SetValue(EnableMenuItemClickForwardingProperty, enable);
diff --git a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
index 45beaa0b2f..46c772f3b1 100644
--- a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
+++ b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
@@ -146,7 +146,11 @@ namespace Avalonia.Controls.Notifications
{
var adornerLayer = host.FindDescendantOfType()?.AdornerLayer;
- adornerLayer?.Children.Add(this);
+ if (adornerLayer is not null)
+ {
+ adornerLayer.Children.Add(this);
+ AdornerLayer.SetAdornedElement(this, adornerLayer);
+ }
}
private void UpdatePseudoClasses(NotificationPosition position)
diff --git a/src/Avalonia.Controls/Platform/InProcessDragSource.cs b/src/Avalonia.Controls/Platform/InProcessDragSource.cs
index 676a1587a8..5b2356a7ce 100644
--- a/src/Avalonia.Controls/Platform/InProcessDragSource.cs
+++ b/src/Avalonia.Controls/Platform/InProcessDragSource.cs
@@ -69,7 +69,7 @@ namespace Avalonia.Platform
return effect;
}
- private DragDropEffects GetPreferredEffect(DragDropEffects effect, RawInputModifiers modifiers)
+ private static DragDropEffects GetPreferredEffect(DragDropEffects effect, RawInputModifiers modifiers)
{
if (effect == DragDropEffects.Copy || effect == DragDropEffects.Move || effect == DragDropEffects.Link || effect == DragDropEffects.None)
return effect; // No need to check for the modifiers.
@@ -80,7 +80,7 @@ namespace Avalonia.Platform
return DragDropEffects.Move;
}
- private StandardCursorType GetCursorForDropEffect(DragDropEffects effects)
+ private static StandardCursorType GetCursorForDropEffect(DragDropEffects effects)
{
if (effects.HasAllFlags(DragDropEffects.Copy))
return StandardCursorType.DragCopy;
diff --git a/src/Avalonia.Controls/Primitives/Popup.cs b/src/Avalonia.Controls/Primitives/Popup.cs
index 337ff54985..3c329a9a3e 100644
--- a/src/Avalonia.Controls/Primitives/Popup.cs
+++ b/src/Avalonia.Controls/Primitives/Popup.cs
@@ -1,6 +1,5 @@
using System;
using System.ComponentModel;
-using System.Linq;
using System.Reactive.Disposables;
using Avalonia.Automation.Peers;
using Avalonia.Controls.Mixins;
@@ -15,7 +14,6 @@ using Avalonia.Metadata;
using Avalonia.Platform;
using Avalonia.VisualTree;
using Avalonia.Media;
-using Avalonia.Utilities;
namespace Avalonia.Controls.Primitives
{
@@ -639,7 +637,7 @@ namespace Avalonia.Controls.Primitives
return Disposable.Create((unsubscribe, target, handler), state => state.unsubscribe(state.target, state.handler));
}
- private void WindowManagerAddShadowHintChanged(IPopupHost host, bool hint)
+ private static void WindowManagerAddShadowHintChanged(IPopupHost host, bool hint)
{
if(host is PopupRoot pr && pr.PlatformImpl is not null)
{
@@ -769,7 +767,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void PassThroughEvent(PointerPressedEventArgs e)
+ private static void PassThroughEvent(PointerPressedEventArgs e)
{
if (e.Source is LightDismissOverlayLayer layer &&
layer.GetVisualRoot() is InputElement root)
diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
index f8951b3fa3..44fa78ac21 100644
--- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
+++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
@@ -588,7 +588,7 @@ namespace Avalonia.Controls.Primitives
}
else if (e.Key == Key.Space || e.Key == Key.Enter)
{
- e.Handled = UpdateSelectionFromEventSource(
+ UpdateSelectionFromEventSource(
e.Source,
true,
e.KeyModifiers.HasFlag(KeyModifiers.Shift),
diff --git a/src/Avalonia.Controls/ProgressBar.cs b/src/Avalonia.Controls/ProgressBar.cs
index 71a7a58da4..165bec3a95 100644
--- a/src/Avalonia.Controls/ProgressBar.cs
+++ b/src/Avalonia.Controls/ProgressBar.cs
@@ -270,15 +270,16 @@ namespace Avalonia.Controls
double percent = Maximum == Minimum ? 1.0 : (Value - Minimum) / (Maximum - Minimum);
// When the Orientation changed, the indicator's Width or Height should set to double.NaN.
+ // Indicator size calculation should consider the ProgressBar's Padding property setting
if (Orientation == Orientation.Horizontal)
{
- _indicator.Width = barSize.Width * percent;
+ _indicator.Width = (barSize.Width - _indicator.Margin.Left - _indicator.Margin.Right) * percent;
_indicator.Height = double.NaN;
}
else
{
_indicator.Width = double.NaN;
- _indicator.Height = barSize.Height * percent;
+ _indicator.Height = (barSize.Height - _indicator.Margin.Top - _indicator.Margin.Bottom) * percent;
}
diff --git a/src/Avalonia.Controls/Repeater/RecyclingElementFactory.cs b/src/Avalonia.Controls/Repeater/RecyclingElementFactory.cs
index 35bd5aeecb..9132bef3d9 100644
--- a/src/Avalonia.Controls/Repeater/RecyclingElementFactory.cs
+++ b/src/Avalonia.Controls/Repeater/RecyclingElementFactory.cs
@@ -87,7 +87,7 @@ namespace Avalonia.Controls
protected virtual string OnSelectTemplateKeyCore(object? dataContext, Control? owner)
{
- if (SelectTemplateKey is object)
+ if (SelectTemplateKey is not null)
{
_args ??= new SelectTemplateEventArgs();
_args.TemplateKey = null;
diff --git a/src/Avalonia.Controls/SplitView.cs b/src/Avalonia.Controls/SplitView.cs
index 29add8720b..fcadafaab5 100644
--- a/src/Avalonia.Controls/SplitView.cs
+++ b/src/Avalonia.Controls/SplitView.cs
@@ -1,14 +1,11 @@
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
-using Avalonia.Input.Raw;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Metadata;
-using Avalonia.Platform;
using Avalonia.VisualTree;
using System;
-using System.Reactive.Disposables;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
using Avalonia.LogicalTree;
@@ -431,7 +428,7 @@ namespace Avalonia.Controls
}
}
- private string GetPseudoClass(SplitViewDisplayMode mode)
+ private static string GetPseudoClass(SplitViewDisplayMode mode)
{
return mode switch
{
@@ -443,7 +440,7 @@ namespace Avalonia.Controls
};
}
- private string GetPseudoClass(SplitViewPanePlacement placement)
+ private static string GetPseudoClass(SplitViewPanePlacement placement)
{
return placement switch
{
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index 358bcfdad7..699170df5a 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -1588,7 +1588,7 @@ namespace Avalonia.Controls
private int CoerceCaretIndex(int value) => CoerceCaretIndex(value, Text);
- private int CoerceCaretIndex(int value, string? text)
+ private static int CoerceCaretIndex(int value, string? text)
{
if (text == null)
{
diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs
index 0e04d92d6e..d2d5a8309c 100644
--- a/src/Avalonia.Controls/TopLevel.cs
+++ b/src/Avalonia.Controls/TopLevel.cs
@@ -357,12 +357,6 @@ namespace Avalonia.Controls
///
protected virtual ILayoutManager CreateLayoutManager() => new LayoutManager(this);
- public override void InvalidateMirrorTransform()
- {
- }
-
- protected override bool BypassFlowDirectionPolicies => true;
-
///
/// Handles a paint notification from .
///
@@ -427,7 +421,7 @@ namespace Avalonia.Controls
LayoutHelper.InvalidateSelfAndChildrenMeasure(this);
}
- private bool TransparencyLevelsMatch (WindowTransparencyLevel requested, WindowTransparencyLevel received)
+ private static bool TransparencyLevelsMatch (WindowTransparencyLevel requested, WindowTransparencyLevel received)
{
if(requested == received)
{
diff --git a/src/Avalonia.Controls/UserControl.cs b/src/Avalonia.Controls/UserControl.cs
index 7b9cc2da1c..e9339d5f4b 100644
--- a/src/Avalonia.Controls/UserControl.cs
+++ b/src/Avalonia.Controls/UserControl.cs
@@ -1,4 +1,3 @@
-using System;
using Avalonia.Styling;
namespace Avalonia.Controls
diff --git a/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj b/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
index 0be695e0a1..867c94b126 100644
--- a/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
+++ b/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
@@ -7,7 +7,7 @@
need change when there are breaking changes to designer support api.
-->
0.7.0
- CS1591
+ $(NoWarn);CS1591
true
Avalonia
diff --git a/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs b/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs
index ca2c2c7fb2..543d07f958 100644
--- a/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs
+++ b/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Reflection;
using System.Threading;
@@ -150,10 +151,20 @@ namespace Avalonia.DesignerSupport.Remote
}
if (args.Method == Methods.Win32)
- builder.UseWindowingSubsystem("Avalonia.Win32");
+ builder.UseWindowingSubsystem(GetInitializer("Avalonia.Win32"), "Win32");
builder.SetupWithoutStarting();
return transport;
}
+
+ private static Action GetInitializer(string assemblyName) => () =>
+ {
+ var assembly = Assembly.Load(new AssemblyName(assemblyName));
+ var platformClassName = assemblyName.Replace("Avalonia.", string.Empty) + "Platform";
+ var platformClassFullName = assemblyName + "." + platformClassName;
+ var platformClass = assembly.GetType(platformClassFullName);
+ var init = platformClass!.GetRuntimeMethod("Initialize", Type.EmptyTypes);
+ init!.Invoke(null, null);
+ };
}
private const string BuilderMethodName = "BuildAvaloniaApp";
diff --git a/src/Avalonia.Desktop/Avalonia.Desktop.csproj b/src/Avalonia.Desktop/Avalonia.Desktop.csproj
index d423aa7dae..d180e6e34d 100644
--- a/src/Avalonia.Desktop/Avalonia.Desktop.csproj
+++ b/src/Avalonia.Desktop/Avalonia.Desktop.csproj
@@ -12,5 +12,7 @@
-
+
+
+
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Screenshots/FilePickerHandler.cs b/src/Avalonia.Diagnostics/Diagnostics/Screenshots/FilePickerHandler.cs
index 444e65e623..2117996b96 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Screenshots/FilePickerHandler.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/Screenshots/FilePickerHandler.cs
@@ -47,7 +47,7 @@ namespace Avalonia.Diagnostics.Screenshots
///
public string Title { get; } = "Save Screenshot to ...";
- Window GetWindow(Control control)
+ static Window GetWindow(Control control)
{
var window = control.VisualRoot as Window;
var app = Application.Current;
diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs
index 0206ede277..5cf9e17ecf 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs
@@ -82,7 +82,7 @@ namespace Avalonia.Diagnostics.ViewModels
{
var setterValue = regularSetter.Value;
- var resourceInfo = GetResourceInfo(setterValue);
+ var resourceInfo = GetResourceInfo(setterValue);
SetterViewModel setterVm;
@@ -121,7 +121,7 @@ namespace Avalonia.Diagnostics.ViewModels
public bool CanNavigateToParentProperty => _selectedEntitiesStack.Count >= 1;
- private (object resourceKey, bool isDynamic)? GetResourceInfo(object? value)
+ private static (object resourceKey, bool isDynamic)? GetResourceInfo(object? value)
{
if (value is StaticResourceExtension staticResource)
{
@@ -136,7 +136,7 @@ namespace Avalonia.Diagnostics.ViewModels
return null;
}
- private bool IsBinding(object? value)
+ private static bool IsBinding(object? value)
{
switch (value)
{
@@ -253,7 +253,7 @@ namespace Avalonia.Diagnostics.ViewModels
}
}
- private IEnumerable GetAvaloniaProperties(object o)
+ private static IEnumerable GetAvaloniaProperties(object o)
{
if (o is AvaloniaObject ao)
{
@@ -267,7 +267,7 @@ namespace Avalonia.Diagnostics.ViewModels
}
}
- private IEnumerable GetClrProperties(object o, bool showImplementedInterfaces)
+ private static IEnumerable GetClrProperties(object o, bool showImplementedInterfaces)
{
foreach (var p in GetClrProperties(o, o.GetType()))
{
@@ -286,7 +286,7 @@ namespace Avalonia.Diagnostics.ViewModels
}
}
- private IEnumerable GetClrProperties(object o, Type t)
+ private static IEnumerable GetClrProperties(object o, Type t)
{
return t.GetProperties()
.Where(x => x.GetIndexParameters().Length == 0)
@@ -411,7 +411,7 @@ namespace Avalonia.Diagnostics.ViewModels
}
}
- private int GroupIndex(string? group)
+ private static int GroupIndex(string? group)
{
switch (group)
{
diff --git a/src/Avalonia.Dialogs/Avalonia.Dialogs.csproj b/src/Avalonia.Dialogs/Avalonia.Dialogs.csproj
index a311efdfb0..99cf1538ae 100644
--- a/src/Avalonia.Dialogs/Avalonia.Dialogs.csproj
+++ b/src/Avalonia.Dialogs/Avalonia.Dialogs.csproj
@@ -16,4 +16,5 @@
+
diff --git a/src/Avalonia.Dialogs/ManagedStorageProvider.cs b/src/Avalonia.Dialogs/ManagedStorageProvider.cs
index 2c88251cca..e45d5c1b4a 100644
--- a/src/Avalonia.Dialogs/ManagedStorageProvider.cs
+++ b/src/Avalonia.Dialogs/ManagedStorageProvider.cs
@@ -29,7 +29,7 @@ public class ManagedStorageProvider : BclStorageProvider where T : Window, ne
public override async Task> OpenFilePickerAsync(FilePickerOpenOptions options)
{
var model = new ManagedFileChooserViewModel(options, _managedOptions);
- var results = await Show(model, _parent);
+ var results = await ManagedStorageProvider.Show(model, _parent);
return results.Select(f => new BclStorageFile(new FileInfo(f))).ToArray();
}
@@ -37,7 +37,7 @@ public class ManagedStorageProvider : BclStorageProvider where T : Window, ne
public override async Task SaveFilePickerAsync(FilePickerSaveOptions options)
{
var model = new ManagedFileChooserViewModel(options, _managedOptions);
- var results = await Show(model, _parent);
+ var results = await ManagedStorageProvider.Show(model, _parent);
return results.FirstOrDefault() is { } result
? new BclStorageFile(new FileInfo(result))
@@ -47,12 +47,12 @@ public class ManagedStorageProvider : BclStorageProvider where T : Window, ne
public override async Task> OpenFolderPickerAsync(FolderPickerOpenOptions options)
{
var model = new ManagedFileChooserViewModel(options, _managedOptions);
- var results = await Show(model, _parent);
+ var results = await ManagedStorageProvider.Show(model, _parent);
return results.Select(f => new BclStorageFolder(new DirectoryInfo(f))).ToArray();
}
- private async Task Show(ManagedFileChooserViewModel model, Window parent)
+ private static async Task Show(ManagedFileChooserViewModel model, Window parent)
{
var dialog = new T
{
diff --git a/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoListener.cs b/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoListener.cs
index 39ddd9d769..34c1506a67 100644
--- a/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoListener.cs
+++ b/src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoListener.cs
@@ -34,14 +34,14 @@ namespace Avalonia.FreeDesktop
Poll(0);
}
- private string GetSymlinkTarget(string x) => Path.GetFullPath(Path.Combine(DevByLabelDir, NativeMethods.ReadLink(x)));
+ private static string GetSymlinkTarget(string x) => Path.GetFullPath(Path.Combine(DevByLabelDir, NativeMethods.ReadLink(x)));
- private string UnescapeString(string input, string regexText, int escapeBase) =>
+ private static string UnescapeString(string input, string regexText, int escapeBase) =>
new Regex(regexText).Replace(input, m => Convert.ToChar(Convert.ToByte(m.Groups[1].Value, escapeBase)).ToString());
- private string UnescapePathFromProcMounts(string input) => UnescapeString(input, @"\\(\d{3})", 8);
+ private static string UnescapePathFromProcMounts(string input) => UnescapeString(input, @"\\(\d{3})", 8);
- private string UnescapeDeviceLabel(string input) => UnescapeString(input, @"\\x([0-9a-f]{2})", 16);
+ private static string UnescapeDeviceLabel(string input) => UnescapeString(input, @"\\x([0-9a-f]{2})", 16);
private void Poll(long _)
{
diff --git a/src/Avalonia.Headless.Vnc/Avalonia.Headless.Vnc.csproj b/src/Avalonia.Headless.Vnc/Avalonia.Headless.Vnc.csproj
index 273910eb59..c713440dc9 100644
--- a/src/Avalonia.Headless.Vnc/Avalonia.Headless.Vnc.csproj
+++ b/src/Avalonia.Headless.Vnc/Avalonia.Headless.Vnc.csproj
@@ -9,4 +9,5 @@
+
diff --git a/src/Avalonia.Headless/Avalonia.Headless.csproj b/src/Avalonia.Headless/Avalonia.Headless.csproj
index 2e33b5790a..95f7b79009 100644
--- a/src/Avalonia.Headless/Avalonia.Headless.csproj
+++ b/src/Avalonia.Headless/Avalonia.Headless.csproj
@@ -5,5 +5,9 @@
-
+
+
+
+
+
diff --git a/src/Avalonia.MicroCom/Avalonia.MicroCom.csproj b/src/Avalonia.MicroCom/Avalonia.MicroCom.csproj
index 14dafb7284..b801f8401a 100644
--- a/src/Avalonia.MicroCom/Avalonia.MicroCom.csproj
+++ b/src/Avalonia.MicroCom/Avalonia.MicroCom.csproj
@@ -13,4 +13,6 @@
+
+
diff --git a/src/Avalonia.MicroCom/CallbackBase.cs b/src/Avalonia.MicroCom/CallbackBase.cs
index 6c5ab225f6..5279569e83 100644
--- a/src/Avalonia.MicroCom/CallbackBase.cs
+++ b/src/Avalonia.MicroCom/CallbackBase.cs
@@ -38,7 +38,7 @@ namespace Avalonia.MicroCom
}
}
- public MicroComShadow Shadow { get; set; }
+ public MicroComShadow? Shadow { get; set; }
public void OnReferencedFromNative()
{
lock (_lock)
diff --git a/src/Avalonia.Native/Avalonia.Native.csproj b/src/Avalonia.Native/Avalonia.Native.csproj
index c924ef3a45..93fba4a57c 100644
--- a/src/Avalonia.Native/Avalonia.Native.csproj
+++ b/src/Avalonia.Native/Avalonia.Native.csproj
@@ -29,4 +29,5 @@
+
diff --git a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
index d8753efe25..7c7b32f7e4 100644
--- a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
+++ b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
@@ -65,7 +65,7 @@ namespace Avalonia.Native
}
}
- private NativeMenu CreateDefaultAppMenu()
+ private static NativeMenu CreateDefaultAppMenu()
{
var result = new NativeMenu();
diff --git a/src/Avalonia.Native/IAvnMenu.cs b/src/Avalonia.Native/IAvnMenu.cs
index 7ce50c5126..3e46e0c5c6 100644
--- a/src/Avalonia.Native/IAvnMenu.cs
+++ b/src/Avalonia.Native/IAvnMenu.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reactive.Disposables;
using Avalonia.Controls;
-using Avalonia.Platform.Interop;
namespace Avalonia.Native.Interop
{
@@ -112,7 +111,7 @@ namespace Avalonia.Native.Interop.Impl
return result;
}
- private __MicroComIAvnMenuItemProxy CreateNew(IAvaloniaNativeFactory factory, NativeMenuItemBase item)
+ private static __MicroComIAvnMenuItemProxy CreateNew(IAvaloniaNativeFactory factory, NativeMenuItemBase item)
{
var nativeItem = (__MicroComIAvnMenuItemProxy)(item is NativeMenuItemSeparator ?
factory.CreateMenuItemSeparator() :
diff --git a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
index bacb10c792..a9136c2c99 100644
--- a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
+++ b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
@@ -12,4 +12,5 @@
+
diff --git a/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs b/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs
index 279e7e750d..e13ee80864 100644
--- a/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs
+++ b/src/Avalonia.OpenGL/Controls/OpenGlControlBase.cs
@@ -38,7 +38,7 @@ namespace Avalonia.OpenGL.Controls
base.Render(context);
}
- private void CheckError(GlInterface gl)
+ private static void CheckError(GlInterface gl)
{
int err;
while ((err = gl.GetError()) != GL_NO_ERROR)
@@ -197,7 +197,7 @@ namespace Avalonia.OpenGL.Controls
}
}
- private bool CheckFramebufferStatus(GlInterface gl)
+ private static bool CheckFramebufferStatus(GlInterface gl)
{
var status = gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
diff --git a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
index 348f5f3a10..22ee548823 100644
--- a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
+++ b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
@@ -11,4 +11,5 @@
+
diff --git a/src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj b/src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj
index d746c6db7e..baeb8820f8 100644
--- a/src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj
+++ b/src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj
@@ -8,6 +8,8 @@
+
+
\ No newline at end of file
diff --git a/src/Avalonia.Remote.Protocol/BsonStreamTransport.cs b/src/Avalonia.Remote.Protocol/BsonStreamTransport.cs
index c58aafa4e0..c18a76711e 100644
--- a/src/Avalonia.Remote.Protocol/BsonStreamTransport.cs
+++ b/src/Avalonia.Remote.Protocol/BsonStreamTransport.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -6,6 +7,7 @@ using Metsys.Bson;
namespace Avalonia.Remote.Protocol
{
+ [RequiresUnreferencedCode("Bson uses reflection")]
class BsonStreamTransportConnection : IAvaloniaRemoteTransportConnection
{
private readonly IMessageTypeResolver _resolver;
diff --git a/src/Avalonia.Remote.Protocol/BsonTcpTransport.cs b/src/Avalonia.Remote.Protocol/BsonTcpTransport.cs
index e647f75997..040f90e4bd 100644
--- a/src/Avalonia.Remote.Protocol/BsonTcpTransport.cs
+++ b/src/Avalonia.Remote.Protocol/BsonTcpTransport.cs
@@ -1,9 +1,11 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
namespace Avalonia.Remote.Protocol
{
+ [RequiresUnreferencedCode("Bson uses reflection")]
public class BsonTcpTransport : TcpTransportBase
{
public BsonTcpTransport(IMessageTypeResolver resolver) : base(resolver)
@@ -24,4 +26,4 @@ namespace Avalonia.Remote.Protocol
return wrap;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Remote.Protocol/DefaultMessageTypeResolver.cs b/src/Avalonia.Remote.Protocol/DefaultMessageTypeResolver.cs
index 8e17dbccfd..3e8b90c741 100644
--- a/src/Avalonia.Remote.Protocol/DefaultMessageTypeResolver.cs
+++ b/src/Avalonia.Remote.Protocol/DefaultMessageTypeResolver.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
@@ -9,6 +10,9 @@ namespace Avalonia.Remote.Protocol
{
private readonly Dictionary _guidsToTypes = new Dictionary();
private readonly Dictionary _typesToGuids = new Dictionary();
+
+ [UnconditionalSuppressMessage("Trimming", "IL2026",
+ Justification = "If type was trimmed, we don't need to resolve it in the remove protocol")]
public DefaultMessageTypeResolver(params Assembly[] assemblies)
{
foreach (var asm in
diff --git a/src/Avalonia.Remote.Protocol/MetsysBson.cs b/src/Avalonia.Remote.Protocol/MetsysBson.cs
index 6abece6bf3..d011a963be 100644
--- a/src/Avalonia.Remote.Protocol/MetsysBson.cs
+++ b/src/Avalonia.Remote.Protocol/MetsysBson.cs
@@ -32,6 +32,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
@@ -71,7 +72,7 @@ namespace Metsys.Bson
namespace Metsys.Bson
{
-
+ [RequiresUnreferencedCode("Bson uses reflection")]
internal class Serializer
{
private static readonly IDictionary _typeMap = new Dictionary
@@ -562,7 +563,7 @@ namespace Metsys.Bson
{
if (_string == null && Value != null)
{
- _string = BitConverter.ToString(Value).Replace("-", string.Empty).ToLower();
+ _string = BitConverter.ToString(Value).Replace("-", string.Empty).ToLowerInvariant();
}
return _string;
@@ -687,6 +688,7 @@ namespace Metsys.Bson
namespace Metsys.Bson
{
+ [RequiresUnreferencedCode("Bson uses reflection")]
internal class TypeHelper
{
private static readonly IDictionary _cachedTypeLookup = new Dictionary();
@@ -787,6 +789,7 @@ namespace Metsys.Bson
namespace Metsys.Bson
{
+ [RequiresUnreferencedCode("Bson uses reflection")]
internal class ListWrapper : BaseWrapper
{
private IList _list;
@@ -821,6 +824,7 @@ namespace Metsys.Bson
namespace Metsys.Bson
{
+ [RequiresUnreferencedCode("Bson uses reflection")]
internal static class ListHelper
{
public static Type GetListItemType(Type enumerableType)
@@ -865,6 +869,7 @@ namespace Metsys.Bson
namespace Metsys.Bson
{
+ [RequiresUnreferencedCode("Bson uses reflection")]
internal class CollectionWrapper : BaseWrapper
{
private ICollection _list;
@@ -892,6 +897,7 @@ namespace Metsys.Bson
namespace Metsys.Bson
{
+ [RequiresUnreferencedCode("Bson uses reflection")]
internal abstract class BaseWrapper
{
public static BaseWrapper Create(Type type, Type itemType, object existingContainer)
@@ -948,7 +954,7 @@ namespace Metsys.Bson
namespace Metsys.Bson
{
-
+ [RequiresUnreferencedCode("Bson uses reflection")]
internal class ArrayWrapper : BaseWrapper
{
private readonly List _list = new List();
@@ -1000,6 +1006,7 @@ namespace Metsys.Bson
namespace Metsys.Bson
{
+ [RequiresUnreferencedCode("Bson uses reflection")]
internal class Deserializer
{
internal class Options
diff --git a/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj b/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj
index 597fab22f8..ab543703d9 100644
--- a/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj
+++ b/src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj
@@ -1,6 +1,8 @@
net6.0;netstandard2.0
+
+ $(NoWarn);IL2026
@@ -14,4 +16,5 @@
+
diff --git a/src/Avalonia.Themes.Fluent/FluentTheme.xaml.cs b/src/Avalonia.Themes.Fluent/FluentTheme.xaml.cs
index 728e81b198..eea3d3ad08 100644
--- a/src/Avalonia.Themes.Fluent/FluentTheme.xaml.cs
+++ b/src/Avalonia.Themes.Fluent/FluentTheme.xaml.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Styling;
@@ -31,9 +32,10 @@ namespace Avalonia.Themes.Fluent
///
/// Initializes a new instance of the class.
///
- public FluentTheme()
+ /// The parent's service provider.
+ public FluentTheme(IServiceProvider? sp = null)
{
- AvaloniaXamlLoader.Load(this);
+ AvaloniaXamlLoader.Load(sp, this);
_baseDark = (IResourceDictionary)GetAndRemove("BaseDark");
_fluentDark = (IResourceDictionary)GetAndRemove("FluentDark");
diff --git a/src/Avalonia.Themes.Simple/Avalonia.Themes.Simple.csproj b/src/Avalonia.Themes.Simple/Avalonia.Themes.Simple.csproj
index e614dad4d9..1dd6426b39 100644
--- a/src/Avalonia.Themes.Simple/Avalonia.Themes.Simple.csproj
+++ b/src/Avalonia.Themes.Simple/Avalonia.Themes.Simple.csproj
@@ -1,6 +1,8 @@
net6.0;netstandard2.0
+
+ $(NoWarn);IL2026
@@ -13,4 +15,5 @@
+
diff --git a/src/Avalonia.Themes.Simple/SimpleTheme.xaml.cs b/src/Avalonia.Themes.Simple/SimpleTheme.xaml.cs
index af9d305043..56c4cbeac6 100644
--- a/src/Avalonia.Themes.Simple/SimpleTheme.xaml.cs
+++ b/src/Avalonia.Themes.Simple/SimpleTheme.xaml.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Styling;
@@ -16,9 +17,10 @@ namespace Avalonia.Themes.Simple
///
/// Initializes a new instance of the class.
///
- public SimpleTheme()
+ /// The parent's service provider.
+ public SimpleTheme(IServiceProvider? sp = null)
{
- AvaloniaXamlLoader.Load(this);
+ AvaloniaXamlLoader.Load(sp, this);
_simpleDark = (IResourceDictionary)GetAndRemove("BaseDark");
_simpleLight = (IResourceDictionary)GetAndRemove("BaseLight");
diff --git a/src/Avalonia.X11/Avalonia.X11.csproj b/src/Avalonia.X11/Avalonia.X11.csproj
index 621e6fabd7..c762349c1c 100644
--- a/src/Avalonia.X11/Avalonia.X11.csproj
+++ b/src/Avalonia.X11/Avalonia.X11.csproj
@@ -12,4 +12,5 @@
+
diff --git a/src/Avalonia.X11/X11IconLoader.cs b/src/Avalonia.X11/X11IconLoader.cs
index 632a7d39a2..4ae1c1599f 100644
--- a/src/Avalonia.X11/X11IconLoader.cs
+++ b/src/Avalonia.X11/X11IconLoader.cs
@@ -9,7 +9,7 @@ namespace Avalonia.X11
{
class X11IconLoader : IPlatformIconLoader
{
- IWindowIconImpl LoadIcon(Bitmap bitmap)
+ static IWindowIconImpl LoadIcon(Bitmap bitmap)
{
var rv = new X11IconData(bitmap);
bitmap.Dispose();
diff --git a/src/Avalonia.X11/X11Platform.cs b/src/Avalonia.X11/X11Platform.cs
index 96dc16e186..cbb782edd0 100644
--- a/src/Avalonia.X11/X11Platform.cs
+++ b/src/Avalonia.X11/X11Platform.cs
@@ -5,7 +5,6 @@ using System.Reflection;
using System.Runtime.InteropServices;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
-using Avalonia.Dialogs;
using Avalonia.FreeDesktop;
using Avalonia.FreeDesktop.DBusIme;
using Avalonia.Input;
@@ -85,7 +84,7 @@ namespace Avalonia.X11
.Bind().ToConstant(new LinuxMountedVolumeInfoProvider())
.Bind().ToConstant(new X11PlatformLifetimeEvents(this));
- X11Screens = Avalonia.X11.X11Screens.Init(this);
+ X11Screens = X11.X11Screens.Init(this);
Screens = new X11Screens(X11Screens);
if (Info.XInputVersion != null)
{
@@ -143,7 +142,7 @@ namespace Avalonia.X11
throw new NotSupportedException();
}
- bool EnableIme(X11PlatformOptions options)
+ static bool EnableIme(X11PlatformOptions options)
{
// Disable if explicitly asked by user
var avaloniaImModule = Environment.GetEnvironmentVariable("AVALONIA_IM_MODULE");
@@ -164,8 +163,8 @@ namespace Avalonia.X11
return isCjkLocale;
}
-
- bool ShouldUseXim()
+
+ static bool ShouldUseXim()
{
// Check if we are forbidden from using IME
if (Environment.GetEnvironmentVariable("AVALONIA_IM_MODULE") == "none"
diff --git a/src/Avalonia.X11/X11Structs.cs b/src/Avalonia.X11/X11Structs.cs
index 3f0a6aeb67..7e46606c36 100644
--- a/src/Avalonia.X11/X11Structs.cs
+++ b/src/Avalonia.X11/X11Structs.cs
@@ -34,6 +34,7 @@ using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Diagnostics.CodeAnalysis;
// ReSharper disable FieldCanBeMadeReadOnly.Global
// ReSharper disable IdentifierTypo
// ReSharper disable MemberCanBePrivate.Global
@@ -654,7 +655,8 @@ namespace Avalonia.X11 {
return type.ToString ();
}
}
-
+
+ [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = TrimmingMessages.IgnoreNativeAotSupressWarningMessage)]
public static string ToString (object ev)
{
string result = string.Empty;
diff --git a/src/Avalonia.X11/X11Window.Ime.cs b/src/Avalonia.X11/X11Window.Ime.cs
index ca987d0a07..257580a5ec 100644
--- a/src/Avalonia.X11/X11Window.Ime.cs
+++ b/src/Avalonia.X11/X11Window.Ime.cs
@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
-using System.Threading.Tasks;
using Avalonia.FreeDesktop;
using Avalonia.Input;
using Avalonia.Input.Raw;
diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs
index 330494d5dc..2f84e15b32 100644
--- a/src/Avalonia.X11/X11Window.cs
+++ b/src/Avalonia.X11/X11Window.cs
@@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Linq;
-using System.Reactive.Disposables;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
@@ -683,7 +681,7 @@ namespace Avalonia.X11
}
- RawInputModifiers TranslateModifiers(XModifierMask state)
+ static RawInputModifiers TranslateModifiers(XModifierMask state)
{
var rv = default(RawInputModifiers);
if (state.HasAllFlags(XModifierMask.Button1Mask))
diff --git a/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj b/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
index 4537f8d73e..a2f1b55b6f 100644
--- a/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
+++ b/src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
@@ -11,6 +11,7 @@
+
diff --git a/src/Browser/Avalonia.Browser/Avalonia.Browser.csproj b/src/Browser/Avalonia.Browser/Avalonia.Browser.csproj
index 2564140a03..014d387cb2 100644
--- a/src/Browser/Avalonia.Browser/Avalonia.Browser.csproj
+++ b/src/Browser/Avalonia.Browser/Avalonia.Browser.csproj
@@ -15,6 +15,7 @@
+
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj b/src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj
index 5cebbb6829..366669d10d 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj
@@ -8,5 +8,6 @@
-
+
+
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj b/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
index 1dc7ce5e99..d74cc0b747 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
@@ -1,4 +1,4 @@
-
+
net6.0;netstandard2.0
@@ -13,6 +13,7 @@
+
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
index 1ee4402481..2bb91e8a32 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
@@ -209,7 +209,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
};
var parsedDocuments = new List();
- var rootInstances = new List();
+ var originalDocuments = new List();
foreach (var document in documents)
{
@@ -234,8 +234,8 @@ namespace Avalonia.Markup.Xaml.XamlIl
parsedDocuments.Add(new XamlDocumentResource(parsed, document.BaseUri?.ToString(), null, null,
builder,
compiler.DefinePopulateMethod(builder, parsed, AvaloniaXamlIlCompiler.PopulateName, true),
- compiler.DefineBuildMethod(builder, parsed, AvaloniaXamlIlCompiler.BuildName, true)));
- rootInstances.Add(document.RootInstance);
+ document.RootInstance is null ? compiler.DefineBuildMethod(builder, parsed, AvaloniaXamlIlCompiler.BuildName, true) : null));
+ originalDocuments.Add(document);
}
compiler.TransformGroup(parsedDocuments);
@@ -251,7 +251,9 @@ namespace Avalonia.Markup.Xaml.XamlIl
indexerClosureType.CreateTypeInfo();
trampolineBuilder.CreateTypeInfo();
- return createdTypes.Zip(rootInstances, (l, r) => (l, r)).Select(t => LoadOrPopulate(t.Item1, t.Item2)).ToArray();
+ return createdTypes.Zip(originalDocuments, (l, r) => (l, r))
+ .Select(t => LoadOrPopulate(t.Item1, t.Item2.RootInstance, t.Item2.ServiceProvider))
+ .ToArray();
}
static object LoadSreCore(RuntimeXamlLoaderDocument document, RuntimeXamlLoaderConfiguration configuration)
@@ -260,7 +262,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
}
#endif
- static object LoadOrPopulate(Type created, object rootInstance)
+ static object LoadOrPopulate(Type created, object rootInstance, IServiceProvider parentServiceProvider)
{
var isp = Expression.Parameter(typeof(IServiceProvider));
@@ -271,6 +273,8 @@ namespace Avalonia.Markup.Xaml.XamlIl
var populateCb = Expression.Lambda>(
Expression.Call(populate, isp, Expression.Convert(epar, populate.GetParameters()[1].ParameterType)),
isp, epar).Compile();
+
+ var serviceProvider = XamlIlRuntimeHelpers.CreateRootServiceProviderV3(parentServiceProvider);
if (rootInstance == null)
{
@@ -282,7 +286,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
{
overrideField.SetValue(null,
new Action(
- target => { populateCb(XamlIlRuntimeHelpers.CreateRootServiceProviderV2(), target); }));
+ target => { populateCb(serviceProvider, target); }));
try
{
return Activator.CreateInstance(targetType);
@@ -296,11 +300,11 @@ namespace Avalonia.Markup.Xaml.XamlIl
var createCb = Expression.Lambda>(
Expression.Convert(Expression.Call(
created.GetMethod(AvaloniaXamlIlCompiler.BuildName), isp), typeof(object)), isp).Compile();
- return createCb(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
+ return createCb(serviceProvider);
}
else
{
- populateCb(XamlIlRuntimeHelpers.CreateRootServiceProviderV2(), rootInstance);
+ populateCb(serviceProvider, rootInstance);
return rootInstance;
}
}
@@ -411,7 +415,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
var loaded = Assembly.LoadFile(asmPath)
.GetTypes().First(x => x.Name == safeUri);
_cecilGeneratedCache[safeUri] = loaded;
- return LoadOrPopulate(loaded, rootInstance);
+ return LoadOrPopulate(loaded, rootInstance, null);
}
#endif
}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/XamlIncludeGroupTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/XamlIncludeGroupTransformer.cs
index cc29d5ccb5..1bb05e238c 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/XamlIncludeGroupTransformer.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/XamlIncludeGroupTransformer.cs
@@ -163,8 +163,9 @@ internal class AvaloniaXamlIncludeTransformer : IXamlAstGroupTransformer
public bool NeedsParentStack => true;
public XamlILNodeEmitResult Emit(XamlEmitContext context, IXamlILEmitter codeGen)
{
+ codeGen.Ldloc(context.ContextLocal);
var method = context.GetAvaloniaTypes().RuntimeHelpers
- .FindMethod(m => m.Name == "CreateRootServiceProviderV2");
+ .FindMethod(m => m.Name == "CreateRootServiceProviderV3");
codeGen.EmitCall(method);
return XamlILNodeEmitResult.Type(0, Type.GetClrType());
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
index 6c9d510ba0..264361e743 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
@@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Xml;
using Avalonia.Markup.Xaml.Parsers;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
using Avalonia.Utilities;
-using XamlX;
using XamlX.Ast;
using XamlX.Transform;
using XamlX.Transform.Transformers;
@@ -67,10 +65,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
string propertyName, IXamlAstTypeReference selectorTypeReference, IXamlLineInfo lineInfo)
{
XamlAstNamePropertyReference forgedReference;
-
- var parser = new PropertyParser();
-
- var parsedPropertyName = parser.Parse(new CharacterReader(propertyName.AsSpan()));
+
+ var parsedPropertyName = PropertyParser.Parse(new CharacterReader(propertyName.AsSpan()));
if(parsedPropertyName.owner == null)
forgedReference = new XamlAstNamePropertyReference(lineInfo, selectorTypeReference,
propertyName, selectorTypeReference);
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github b/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
index 491de981dd..5e498f8bcc 160000
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
@@ -1 +1 @@
-Subproject commit 491de981dd4433ee58bc9540e2cd4a5d168f8168
+Subproject commit 5e498f8bcca403a34aff5efc825cbb4e12b7fa8e
diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
index 0ab00007e7..c59542c0f3 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
+++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
@@ -6,10 +6,9 @@
$(DefineConstants);RUNTIME_XAML_CECIL
False
false
- CS1591
+ $(NoWarn);CS1591
-
@@ -69,12 +68,9 @@
+
-
-
-
-
diff --git a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
index 388ff61400..0b6a2c522f 100644
--- a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using Avalonia.Platform;
#nullable enable
@@ -23,6 +24,17 @@ namespace Avalonia.Markup.Xaml
throw new XamlLoadException(
$"No precompiled XAML found for {obj.GetType()}, make sure to specify x:Class and include your XAML file as AvaloniaResource");
}
+
+ ///
+ /// Loads the XAML into a Avalonia component.
+ ///
+ /// The parent's service provider.
+ /// The object to load the XAML into.
+ public static void Load(IServiceProvider? sp, object obj)
+ {
+ throw new XamlLoadException(
+ $"No precompiled XAML found for {obj.GetType()}, make sure to specify x:Class and include your XAML file as AvaloniaResource");
+ }
///
/// Loads XAML from a URI.
@@ -32,7 +44,23 @@ namespace Avalonia.Markup.Xaml
/// A base URI to use if is relative.
///
/// The loaded object.
+ [RequiresUnreferencedCode(TrimmingMessages.AvaloniaXamlLoaderRequiresUnreferenceCodeMessage)]
public static object Load(Uri uri, Uri? baseUri = null)
+ {
+ return Load(null, uri, baseUri);
+ }
+
+ ///
+ /// Loads XAML from a URI.
+ ///
+ /// The parent's service provider.
+ /// The URI of the XAML file.
+ ///
+ /// A base URI to use if is relative.
+ ///
+ /// The loaded object.
+ [RequiresUnreferencedCode(TrimmingMessages.AvaloniaXamlLoaderRequiresUnreferenceCodeMessage)]
+ public static object Load(IServiceProvider? sp, Uri uri, Uri? baseUri = null)
{
if (uri is null)
throw new ArgumentNullException(nameof(uri));
@@ -51,13 +79,25 @@ namespace Avalonia.Markup.Xaml
var compiledLoader = assetLocator.GetAssembly(uri, baseUri)
?.GetType("CompiledAvaloniaXaml.!XamlLoader")
- ?.GetMethod("TryLoad", new[] {typeof(string)});
+ ?.GetMethod("TryLoad", new[] { typeof(System.IServiceProvider), typeof(string) });
if (compiledLoader != null)
{
- var compiledResult = compiledLoader.Invoke(null, new object[] {absoluteUri.ToString()});
+ var compiledResult = compiledLoader.Invoke(null, new object?[] { sp, absoluteUri.ToString()});
if (compiledResult != null)
return compiledResult;
}
+ else
+ {
+ compiledLoader = assetLocator.GetAssembly(uri, baseUri)
+ ?.GetType("CompiledAvaloniaXaml.!XamlLoader")
+ ?.GetMethod("TryLoad", new[] {typeof(string)});
+ if (compiledLoader != null)
+ {
+ var compiledResult = compiledLoader.Invoke(null, new object?[] {absoluteUri.ToString()});
+ if (compiledResult != null)
+ return compiledResult;
+ }
+ }
// This is intended for unit-tests only
var runtimeLoader = AvaloniaLocator.Current.GetService();
@@ -66,10 +106,9 @@ namespace Avalonia.Markup.Xaml
var asset = assetLocator.OpenAndGetAssembly(uri, baseUri);
using (var stream = asset.stream)
{
- return runtimeLoader.Load(new RuntimeXamlLoaderDocument(absoluteUri, stream), new RuntimeXamlLoaderConfiguration
- {
- LocalAssembly = asset.assembly
- });
+ var document = new RuntimeXamlLoaderDocument(absoluteUri, stream) { ServiceProvider = sp };
+ var configuration = new RuntimeXamlLoaderConfiguration { LocalAssembly = asset.assembly };
+ return runtimeLoader.Load(document, configuration);
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs
index 45ca1c4adc..5b660af887 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs
@@ -1,9 +1,9 @@
using System;
using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using Avalonia.Controls;
using Avalonia.Logging;
-using Avalonia.Markup.Parsers;
using Avalonia.Markup.Xaml.Parsers;
using Avalonia.Markup.Xaml.Templates;
using Avalonia.Styling;
@@ -11,6 +11,7 @@ using Avalonia.Utilities;
namespace Avalonia.Markup.Xaml.Converters
{
+ [RequiresUnreferencedCode(TrimmingMessages.XamlTypeResolvedRequiresUnreferenceCodeMessage)]
public class AvaloniaPropertyTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
@@ -21,8 +22,7 @@ namespace Avalonia.Markup.Xaml.Converters
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var registry = AvaloniaPropertyRegistry.Instance;
- var parser = new PropertyParser();
- var (ns, owner, propertyName) = parser.Parse(new CharacterReader(((string)value).AsSpan()));
+ var (ns, owner, propertyName) = PropertyParser.Parse(new CharacterReader(((string)value).AsSpan()));
var ownerType = TryResolveOwnerByName(context, ns, owner);
var targetType = context.GetFirstParent()?.TargetType ??
context.GetFirstParent
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleWithServiceProvider.xaml.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleWithServiceProvider.xaml.cs
new file mode 100644
index 0000000000..42da1604b9
--- /dev/null
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleWithServiceProvider.xaml.cs
@@ -0,0 +1,16 @@
+using System;
+using Avalonia.Controls;
+using Avalonia.Styling;
+
+namespace Avalonia.Markup.Xaml.UnitTests.Xaml;
+
+public class StyleWithServiceProvider : Style
+{
+ public IServiceProvider ServiceProvider { get; }
+
+ public StyleWithServiceProvider(IServiceProvider sp = null)
+ {
+ ServiceProvider = sp;
+ AvaloniaXamlLoader.Load(sp, this);
+ }
+}
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs
index 77a4932ccc..4b32a8cdca 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/XamlIlTests.cs
@@ -9,6 +9,7 @@ using Avalonia.Data.Converters;
using Avalonia.Data.Core;
using Avalonia.Input;
using Avalonia.Interactivity;
+using Avalonia.Markup.Xaml.UnitTests.Xaml;
using Avalonia.Media;
using Avalonia.Styling;
using Avalonia.Threading;
@@ -162,7 +163,7 @@ namespace Avalonia.Markup.Xaml.UnitTests
}
- void AssertThrows(Action callback, Func check)
+ static void AssertThrows(Action callback, Func check)
{
try
{
@@ -314,6 +315,26 @@ namespace Avalonia.Markup.Xaml.UnitTests
Assert.NotNull(parsed.ItemTemplate);
}
+
+ [Fact]
+ public void Runtime_Loader_Should_Pass_Parents_From_ServiceProvider()
+ {
+ var sp = new TestServiceProvider
+ {
+ Parents = new List
+ {
+ new UserControl { Resources = { ["Resource1"] = new SolidColorBrush(Colors.Blue) } }
+ }
+ };
+ var document = new RuntimeXamlLoaderDocument(@"
+")
+ {
+ ServiceProvider = sp
+ };
+
+ var parsed = (Button)AvaloniaRuntimeXamlLoader.Load(document);
+ Assert.Equal(Colors.Blue, ((ISolidColorBrush)parsed.Background!).Color);
+ }
}
public class XamlIlBugTestsEventHandlerCodeBehind : Window
diff --git a/tests/Avalonia.ReactiveUI.UnitTests/TransitioningContentControlTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/TransitioningContentControlTest.cs
index 812290bf33..e1ab54f775 100644
--- a/tests/Avalonia.ReactiveUI.UnitTests/TransitioningContentControlTest.cs
+++ b/tests/Avalonia.ReactiveUI.UnitTests/TransitioningContentControlTest.cs
@@ -32,7 +32,7 @@ namespace Avalonia.ReactiveUI.UnitTests
Assert.IsType(child);
}
- private FuncControlTemplate GetTemplate()
+ private static FuncControlTemplate GetTemplate()
{
return new FuncControlTemplate((parent, scope) =>
{
diff --git a/tests/Avalonia.RenderTests/Media/GeometryDrawingTests.cs b/tests/Avalonia.RenderTests/Media/GeometryDrawingTests.cs
index 06e46c1a06..f6e7ba0c48 100644
--- a/tests/Avalonia.RenderTests/Media/GeometryDrawingTests.cs
+++ b/tests/Avalonia.RenderTests/Media/GeometryDrawingTests.cs
@@ -17,7 +17,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
{
}
- private GeometryDrawing CreateGeometryDrawing()
+ private static GeometryDrawing CreateGeometryDrawing()
{
GeometryDrawing geometryDrawing = new GeometryDrawing();
EllipseGeometry ellipse = new EllipseGeometry();
diff --git a/tests/Avalonia.RenderTests/Media/TextFormatting/TextLayoutTests.cs b/tests/Avalonia.RenderTests/Media/TextFormatting/TextLayoutTests.cs
index b668f4d39e..f921d9fa64 100644
--- a/tests/Avalonia.RenderTests/Media/TextFormatting/TextLayoutTests.cs
+++ b/tests/Avalonia.RenderTests/Media/TextFormatting/TextLayoutTests.cs
@@ -39,7 +39,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
{
}
- private TextLayout Create(string text,
+ private static TextLayout Create(string text,
string fontFamily,
double fontSize,
FontStyle fontStyle,
@@ -56,7 +56,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
return formattedText;
}
- private TextLayout Create(string text, double fontSize)
+ private static TextLayout Create(string text, double fontSize)
{
return Create(text, FontName, fontSize,
FontStyle.Normal, TextAlignment.Left,
@@ -64,7 +64,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
-1);
}
- private TextLayout Create(string text, double fontSize, TextAlignment alignment, double widthConstraint)
+ private static TextLayout Create(string text, double fontSize, TextAlignment alignment, double widthConstraint)
{
return Create(text, FontName, fontSize,
FontStyle.Normal, alignment,
@@ -72,7 +72,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
widthConstraint);
}
- private TextLayout Create(string text, double fontSize, TextWrapping wrap, double widthConstraint)
+ private static TextLayout Create(string text, double fontSize, TextWrapping wrap, double widthConstraint)
{
return Create(text, FontName, fontSize,
FontStyle.Normal, TextAlignment.Left,
diff --git a/tests/Avalonia.RenderTests/TestBase.cs b/tests/Avalonia.RenderTests/TestBase.cs
index 4d6b313ffc..3f918e2a73 100644
--- a/tests/Avalonia.RenderTests/TestBase.cs
+++ b/tests/Avalonia.RenderTests/TestBase.cs
@@ -237,7 +237,7 @@ namespace Avalonia.Direct2D1.RenderTests
return Math.Sqrt(meanSquaresError);
}
- private string GetTestsDirectory()
+ private static string GetTestsDirectory()
{
var path = Directory.GetCurrentDirectory();
diff --git a/tests/Avalonia.Skia.UnitTests/DrawingContextImplTests.cs b/tests/Avalonia.Skia.UnitTests/DrawingContextImplTests.cs
index df0cc2fc1a..68595a2f57 100644
--- a/tests/Avalonia.Skia.UnitTests/DrawingContextImplTests.cs
+++ b/tests/Avalonia.Skia.UnitTests/DrawingContextImplTests.cs
@@ -21,7 +21,7 @@ namespace Avalonia.Skia.UnitTests
target.DrawRectangle(Brushes.Black, new Pen(Brushes.Black, 0), new RoundedRect(new Rect(0, 0, 100, 100), new CornerRadius(4)));
}
- private DrawingContextImpl CreateTarget()
+ private static DrawingContextImpl CreateTarget()
{
var canvas = new SKCanvas(new SKBitmap(100, 100));
return (DrawingContextImpl)DrawingContextHelper.WrapSkiaCanvas(canvas, new Vector(96, 96));
diff --git a/tests/Avalonia.UnitTests/ModuleInitializer.cs b/tests/Avalonia.UnitTests/ModuleInitializer.cs
new file mode 100644
index 0000000000..8e9386afa0
--- /dev/null
+++ b/tests/Avalonia.UnitTests/ModuleInitializer.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace Avalonia.Base.UnitTests
+{
+ internal static class ModuleInitializer
+ {
+ [ModuleInitializer]
+ internal static void TestInit()
+ {
+ Trace.Listeners.Insert(0, new ThrowListener());
+ }
+
+ private class ThrowListener : TextWriterTraceListener
+ {
+ public override void Fail(string message)
+ {
+ throw new Exception("Assertion Failed. " + message);
+ }
+
+ public override void Fail(string message, string detailMessage)
+ {
+ throw new Exception("Assertion Failed. " + message + detailMessage);
+ }
+ }
+ }
+}