diff --git a/Avalonia.sln b/Avalonia.sln
index 4e7b4cc318..0354e20d4f 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -60,20 +60,17 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DEF5-D50F-4975-8B72-124C9EB54066}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
+ src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI", "src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}"
EndProject
-Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "PlatformSupport", "src\Shared\PlatformSupport\PlatformSupport.shproj", "{E4D9629C-F168-4224-3F51-A5E482FFBC42}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup", "src\Markup\Avalonia.Markup\Avalonia.Markup.csproj", "{6417E941-21BC-467B-A771-0DE389353CE6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.UnitTests", "tests\Avalonia.Markup.UnitTests\Avalonia.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BindingDemo", "samples\BindingDemo\BindingDemo.csproj", "{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}"
EndProject
-Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "RenderHelpers", "src\Shared\RenderHelpers\RenderHelpers.shproj", "{3C4C0CB4-0C0F-4450-A37B-148C84FF905F}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Skia", "Skia", "{3743B0F2-CC41-4F14-A8C8-267F579BF91E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}"
@@ -235,15 +232,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsInteropTest", "sampl
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlSamples", "samples\SampleControls\ControlSamples.csproj", "{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.PlatformSupport", "src\Avalonia.PlatformSupport\Avalonia.PlatformSupport.csproj", "{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}"
+EndProject
Global
- GlobalSection(SharedMSBuildProjectFiles) = preSolution
- src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
- src\Shared\RenderHelpers\RenderHelpers.projitems*{3e908f67-5543-4879-a1dc-08eace79b3cd}*SharedItemsImports = 5
- src\Shared\PlatformSupport\PlatformSupport.projitems*{7b92af71-6287-4693-9dcb-bd5b6e927e23}*SharedItemsImports = 5
- src\Shared\RenderHelpers\RenderHelpers.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 5
- src\Shared\PlatformSupport\PlatformSupport.projitems*{88060192-33d5-4932-b0f9-8bd2763e857d}*SharedItemsImports = 5
- src\Shared\PlatformSupport\PlatformSupport.projitems*{e4d9629c-f168-4224-3f51-a5e482ffbc42}*SharedItemsImports = 13
- EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
Ad-Hoc|iPhone = Ad-Hoc|iPhone
@@ -2169,6 +2160,30 @@ Global
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}.Release|iPhone.Build.0 = Release|Any CPU
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhone.Build.0 = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2187,11 +2202,9 @@ Global
{EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{99135EAB-653D-47E4-A378-C96E1278CA44} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{3E53A01A-B331-47F3-B828-4A5717E77A24} = {8B6A8209-894F-4BA1-B880-965FD453982C}
- {E4D9629C-F168-4224-3F51-A5E482FFBC42} = {A689DEF5-D50F-4975-8B72-124C9EB54066}
{6417E941-21BC-467B-A771-0DE389353CE6} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{8EF392D5-1416-45AA-9956-7CBBC3229E8A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162} = {9B9E3891-2366-4253-A952-D08BCEB71098}
- {3C4C0CB4-0C0F-4450-A37B-148C84FF905F} = {A689DEF5-D50F-4975-8B72-124C9EB54066}
{7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}
{FF69B927-C545-49AE-8E16-3D14D621AA12} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}
{4488AD85-1495-4809-9AA4-DDFE0A48527E} = {0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1}
diff --git a/build/CoreLibraries.props b/build/CoreLibraries.props
index fff00041c3..3fccad2641 100644
--- a/build/CoreLibraries.props
+++ b/build/CoreLibraries.props
@@ -17,5 +17,6 @@
+
diff --git a/build/System.Drawing.Common.props b/build/System.Drawing.Common.props
index 2b3707d38a..108a0f41e0 100644
--- a/build/System.Drawing.Common.props
+++ b/build/System.Drawing.Common.props
@@ -1,5 +1,6 @@
-
+
+
diff --git a/readme.md b/readme.md
index b38552a010..96c7937559 100644
--- a/readme.md
+++ b/readme.md
@@ -3,13 +3,11 @@
[](https://www.nuget.org/packages/Avalonia) [](https://www.nuget.org/packages/Avalonia) [](https://www.myget.org/gallery/avalonia-ci) 
-## 📖 About AvaloniaUI
+## 📖 About
-Avalonia is a cross-platform XAML-based UI framework providing a flexible styling system and supporting a wide range of Operating Systems such as Windows via .NET Framework and .NET Core, Linux via Xorg, macOS. Avalonia is ready for **General-Purpose Desktop App Development**. However, there may be some bugs and breaking changes as we continue along into this project's development.
+Avalonia is a cross-platform UI framework for dotnet, providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, MacOs. Avalonia is mature and production ready. We also have in beta release support for iOS, Android and in early stages support for browser via WASM.
-
-
-([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
+
To see the status of some of our features, please see our [Roadmap](https://github.com/AvaloniaUI/Avalonia/issues/2239). You can also see what [breaking changes](https://github.com/AvaloniaUI/Avalonia/issues/3538) we have planned and what our [past breaking changes](https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes) have been. [Awesome Avalonia](https://github.com/AvaloniaCommunity/awesome-avalonia) is community-curated list of awesome Avalonia UI tools, libraries, projects and resources. Go and see what people are building with Avalonia!
@@ -28,18 +26,15 @@ Install-Package Avalonia.Desktop
## Showcase
Examples of UIs built with Avalonia
-
-
-([Synfonia](https://github.com/jmacato/Synfonia))
+
+([Lunacy](https://icons8.com/lunacy))
-
-([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
+
+([PlasticSCM](https://www.plasticscm.com/))
-
-([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
+
+([WasabiWallet](https://www.wasabiwallet.io/))
-
-([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
## JetBrains Rider
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index 3d869bb723..7beb496ab5 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -22,8 +22,8 @@
-
-
+
+
diff --git a/samples/ControlCatalog/Pages/ButtonPage.xaml b/samples/ControlCatalog/Pages/ButtonPage.xaml
deleted file mode 100644
index 2ce1469118..0000000000
--- a/samples/ControlCatalog/Pages/ButtonPage.xaml
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
- A button control
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlCatalog/Pages/ButtonsPage.xaml b/samples/ControlCatalog/Pages/ButtonsPage.xaml
new file mode 100644
index 0000000000..7de0872eae
--- /dev/null
+++ b/samples/ControlCatalog/Pages/ButtonsPage.xaml
@@ -0,0 +1,224 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A standard button control
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A button control with multiple states: checked, unchecked or indeterminate.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A button control that raises its Click event repeatedly when it is pressed and held.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A button with primary and secondary parts that can each be pressed separately. The primary part behaves like a Button and the secondary part opens a flyout.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A button with primary and secondary parts that can each be pressed separately. The primary part behaves like a ToggleButton with two states and the secondary part opens a flyout.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/ButtonPage.xaml.cs b/samples/ControlCatalog/Pages/ButtonsPage.xaml.cs
similarity index 90%
rename from samples/ControlCatalog/Pages/ButtonPage.xaml.cs
rename to samples/ControlCatalog/Pages/ButtonsPage.xaml.cs
index 5e555c8c91..5594bab176 100644
--- a/samples/ControlCatalog/Pages/ButtonPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ButtonsPage.xaml.cs
@@ -3,11 +3,11 @@ using Avalonia.Markup.Xaml;
namespace ControlCatalog.Pages
{
- public class ButtonPage : UserControl
+ public class ButtonsPage : UserControl
{
private int repeatButtonClickCount = 0;
- public ButtonPage()
+ public ButtonsPage()
{
InitializeComponent();
diff --git a/samples/ControlCatalog/Pages/ComboBoxPage.xaml b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
index decbd763a1..64e80a8e11 100644
--- a/samples/ControlCatalog/Pages/ComboBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
@@ -1,77 +1,95 @@
-
-
- A drop-down list.
+
+
+ A drop-down list.
-
-
-
-
-
- Inline Items
- Inline Item 2
- Inline Item 3
- Inline Item 4
-
+
+
+
+
+
-
-
-
-
- Hello
- World
-
-
-
-
-
-
-
-
-
-
-
+
+ Inline Items
+ Inline Item 2
+ Inline Item 3
+ Inline Item 4
+
-
-
-
-
- Control Items
-
-
-
-
-
-
-
-
-
+
+
+
+
+ Hello
+ World
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
- Inline Items
- Inline Item 2
- Inline Item 3
- Inline Item 4
-
-
-
-
-
+
+
+
+
+ Control Items
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+ Inline Items
+ Inline Item 2
+ Inline Item 3
+ Inline Item 4
+
+
+
+
+
+
+ WrapSelection
+
+
+
diff --git a/samples/ControlCatalog/Pages/ComboBoxPage.xaml.cs b/samples/ControlCatalog/Pages/ComboBoxPage.xaml.cs
index d50b051d9f..d304bf227d 100644
--- a/samples/ControlCatalog/Pages/ComboBoxPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ComboBoxPage.xaml.cs
@@ -2,6 +2,7 @@ using System.Linq;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
+using ControlCatalog.ViewModels;
namespace ControlCatalog.Pages
{
@@ -10,6 +11,7 @@ namespace ControlCatalog.Pages
public ComboBoxPage()
{
this.InitializeComponent();
+ DataContext = new ComboBoxPageViewModel();
}
private void InitializeComponent()
diff --git a/samples/ControlCatalog/Pages/ListBoxPage.xaml b/samples/ControlCatalog/Pages/ListBoxPage.xaml
index 41658329df..433592345a 100644
--- a/samples/ControlCatalog/Pages/ListBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/ListBoxPage.xaml
@@ -21,6 +21,7 @@
Toggle
AlwaysSelected
AutoScrollToSelectedItem
+ WrapSelection
@@ -30,6 +31,7 @@
+ SelectionMode="{Binding SelectionMode^}"
+ WrapSelection="{Binding WrapSelection}"/>
diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs
index 4edb0f137a..caad8b0854 100644
--- a/samples/ControlCatalog/Pages/ScreenPage.cs
+++ b/samples/ControlCatalog/Pages/ScreenPage.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
@@ -49,25 +50,33 @@ namespace ControlCatalog.Pages
context.DrawRectangle(p, boundsRect);
context.DrawRectangle(p, workingAreaRect);
- var text = new FormattedText() { Typeface = new Typeface("Arial"), FontSize = 18 };
- text.Text = $"Bounds: {screen.Bounds.TopLeft} {screen.Bounds.Width}:{screen.Bounds.Height}";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height), text);
-
- text.Text = $"WorkArea: {screen.WorkingArea.TopLeft} {screen.WorkingArea.Width}:{screen.WorkingArea.Height}";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 20), text);
+ var formattedText = CreateFormattedText($"Bounds: {screen.Bounds.Width}:{screen.Bounds.Height}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height));
- text.Text = $"Scaling: {screen.PixelDensity * 100}%";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text);
-
- text.Text = $"Primary: {screen.Primary}";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text);
-
- text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}";
- context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 80), text);
+ formattedText =
+ CreateFormattedText($"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 20));
+
+ formattedText = CreateFormattedText($"Scaling: {screen.PixelDensity * 100}%");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 40));
+
+ formattedText = CreateFormattedText($"Primary: {screen.Primary}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 60));
+
+ formattedText =
+ CreateFormattedText(
+ $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}");
+ context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 80));
}
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)
+ {
+ return new FormattedText(textToFormat, CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
+ Typeface.Default, 12, Brushes.Green);
+ }
}
}
diff --git a/samples/ControlCatalog/Pages/ToggleSwitchPage.xaml b/samples/ControlCatalog/Pages/ToggleSwitchPage.xaml
index 4db755b6fc..6afe6dd135 100644
--- a/samples/ControlCatalog/Pages/ToggleSwitchPage.xaml
+++ b/samples/ControlCatalog/Pages/ToggleSwitchPage.xaml
@@ -11,7 +11,7 @@
-
+
diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml b/samples/ControlCatalog/Pages/ViewboxPage.xaml
index 81e5046636..e7e3007d35 100644
--- a/samples/ControlCatalog/Pages/ViewboxPage.xaml
+++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml
@@ -1,5 +1,6 @@
@@ -12,8 +13,8 @@
+ Stretch="{Binding #StretchSelector.SelectedItem, FallbackValue={x:Static Stretch.Uniform}}"
+ StretchDirection="{Binding #StretchDirectionSelector.SelectedItem, FallbackValue={x:Static StretchDirection.Both}}">
@@ -25,9 +26,22 @@
-
+
+
+ Uniform
+ UniformToFill
+ Fill
+ None
+
+
-
+
+
+ Both
+ DownOnly
+ UpOnly
+
+
diff --git a/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs b/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
index 94b3f3ea14..12b5086e12 100644
--- a/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ViewboxPage.xaml.cs
@@ -1,6 +1,5 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
-using Avalonia.Media;
namespace ControlCatalog.Pages
{
@@ -9,24 +8,6 @@ namespace ControlCatalog.Pages
public ViewboxPage()
{
InitializeComponent();
-
- var stretchSelector = this.FindControl("StretchSelector");
-
- stretchSelector.Items = new[]
- {
- Stretch.Uniform, Stretch.UniformToFill, Stretch.Fill, Stretch.None
- };
-
- stretchSelector.SelectedIndex = 0;
-
- var stretchDirectionSelector = this.FindControl("StretchDirectionSelector");
-
- stretchDirectionSelector.Items = new[]
- {
- StretchDirection.Both, StretchDirection.DownOnly, StretchDirection.UpOnly
- };
-
- stretchDirectionSelector.SelectedIndex = 0;
}
private void InitializeComponent()
diff --git a/samples/ControlCatalog/ViewModels/ComboBoxPageViewModel.cs b/samples/ControlCatalog/ViewModels/ComboBoxPageViewModel.cs
new file mode 100644
index 0000000000..bbe970afd6
--- /dev/null
+++ b/samples/ControlCatalog/ViewModels/ComboBoxPageViewModel.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reactive;
+using Avalonia.Controls;
+using Avalonia.Controls.Selection;
+using MiniMvvm;
+
+namespace ControlCatalog.ViewModels
+{
+ public class ComboBoxPageViewModel : ViewModelBase
+ {
+ private bool _wrapSelection;
+
+ public bool WrapSelection
+ {
+ get => _wrapSelection;
+ set => this.RaiseAndSetIfChanged(ref _wrapSelection, value);
+ }
+ }
+}
diff --git a/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs b/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
index 7f2d6e9572..59489ebcc0 100644
--- a/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
@@ -14,6 +14,7 @@ namespace ControlCatalog.ViewModels
private bool _toggle;
private bool _alwaysSelected;
private bool _autoScrollToSelectedItem = true;
+ private bool _wrapSelection;
private int _counter;
private IObservable _selectionMode;
@@ -85,6 +86,12 @@ namespace ControlCatalog.ViewModels
set => this.RaiseAndSetIfChanged(ref _autoScrollToSelectedItem, value);
}
+ public bool WrapSelection
+ {
+ get => _wrapSelection;
+ set => this.RaiseAndSetIfChanged(ref _wrapSelection, value);
+ }
+
public MiniCommand AddItemCommand { get; }
public MiniCommand RemoveItemCommand { get; }
public MiniCommand SelectRandomItemCommand { get; }
diff --git a/samples/RenderDemo/MainWindow.xaml b/samples/RenderDemo/MainWindow.xaml
index 2b5bba928a..9298c9762e 100644
--- a/samples/RenderDemo/MainWindow.xaml
+++ b/samples/RenderDemo/MainWindow.xaml
@@ -57,6 +57,9 @@
+
+
+
diff --git a/samples/RenderDemo/Pages/ClippingPage.xaml b/samples/RenderDemo/Pages/ClippingPage.xaml
index 10225f7c49..698e18d496 100644
--- a/samples/RenderDemo/Pages/ClippingPage.xaml
+++ b/samples/RenderDemo/Pages/ClippingPage.xaml
@@ -19,30 +19,36 @@
-
+
+
+
+
diff --git a/samples/RenderDemo/Pages/ClippingPage.xaml.cs b/samples/RenderDemo/Pages/ClippingPage.xaml.cs
index 5357181838..c5b669343a 100644
--- a/samples/RenderDemo/Pages/ClippingPage.xaml.cs
+++ b/samples/RenderDemo/Pages/ClippingPage.xaml.cs
@@ -1,35 +1,18 @@
-using System;
-using System.Reactive.Linq;
-using Avalonia;
-using Avalonia.Animation;
using Avalonia.Controls;
-using Avalonia.Data;
using Avalonia.Markup.Xaml;
-using Avalonia.Media;
namespace RenderDemo.Pages
{
public class ClippingPage : UserControl
{
- private Geometry _clip;
-
public ClippingPage()
{
InitializeComponent();
- WireUpCheckbox();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
-
- private void WireUpCheckbox()
- {
- var useMask = this.FindControl("useMask");
- var clipped = this.FindControl("clipped");
- _clip = clipped.Clip;
- useMask.Click += (s, e) => clipped.Clip = clipped.Clip == null ? _clip : null;
- }
}
}
diff --git a/samples/RenderDemo/Pages/CustomSkiaPage.cs b/samples/RenderDemo/Pages/CustomSkiaPage.cs
index 2e59d934a1..9c524a7932 100644
--- a/samples/RenderDemo/Pages/CustomSkiaPage.cs
+++ b/samples/RenderDemo/Pages/CustomSkiaPage.cs
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
+using System.Globalization;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
@@ -41,7 +42,10 @@ namespace RenderDemo.Pages
{
var canvas = (context as ISkiaDrawingContextImpl)?.SkCanvas;
if (canvas == null)
- context.DrawText(Brushes.Black, new Point(), _noSkia.PlatformImpl);
+ using (var c = new DrawingContext(context, false))
+ {
+ c.DrawText(_noSkia, new Point());
+ }
else
{
canvas.Save();
@@ -108,10 +112,9 @@ namespace RenderDemo.Pages
public override void Render(DrawingContext context)
{
- var noSkia = new FormattedText()
- {
- Text = "Current rendering API is not Skia"
- };
+ var noSkia = new FormattedText("Current rendering API is not Skia", CultureInfo.CurrentCulture,
+ FlowDirection.LeftToRight, Typeface.Default, 12, Brushes.Black);
+
context.Custom(new CustomDrawOp(new Rect(0, 0, Bounds.Width, Bounds.Height), noSkia));
Dispatcher.UIThread.InvokeAsync(InvalidateVisual, DispatcherPriority.Background);
}
diff --git a/samples/RenderDemo/Pages/FormattedTextPage.axaml b/samples/RenderDemo/Pages/FormattedTextPage.axaml
new file mode 100644
index 0000000000..92775bec9e
--- /dev/null
+++ b/samples/RenderDemo/Pages/FormattedTextPage.axaml
@@ -0,0 +1,7 @@
+
+
diff --git a/samples/RenderDemo/Pages/FormattedTextPage.axaml.cs b/samples/RenderDemo/Pages/FormattedTextPage.axaml.cs
new file mode 100644
index 0000000000..25e29c67a9
--- /dev/null
+++ b/samples/RenderDemo/Pages/FormattedTextPage.axaml.cs
@@ -0,0 +1,60 @@
+using System.Globalization;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using Avalonia.Media;
+
+namespace RenderDemo.Pages
+{
+ public class FormattedTextPage : UserControl
+ {
+ public FormattedTextPage()
+ {
+ this.InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public override void Render(DrawingContext context)
+ {
+ const string testString = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor";
+
+ // Create the initial formatted text string.
+ var formattedText = new FormattedText(
+ testString,
+ CultureInfo.GetCultureInfo("en-us"),
+ FlowDirection.LeftToRight,
+ new Typeface("Verdana"),
+ 32,
+ Brushes.Black) { MaxTextWidth = 300, MaxTextHeight = 240 };
+
+ // Set a maximum width and height. If the text overflows these values, an ellipsis "..." appears.
+
+ // Use a larger font size beginning at the first (zero-based) character and continuing for 5 characters.
+ // The font size is calculated in terms of points -- not as device-independent pixels.
+ formattedText.SetFontSize(36 * (96.0 / 72.0), 0, 5);
+
+ // Use a Bold font weight beginning at the 6th character and continuing for 11 characters.
+ formattedText.SetFontWeight(FontWeight.Bold, 6, 11);
+
+ var gradient = new LinearGradientBrush
+ {
+ GradientStops =
+ new GradientStops { new GradientStop(Colors.Orange, 0), new GradientStop(Colors.Teal, 1) },
+ StartPoint = new RelativePoint(0,0, RelativeUnit.Relative),
+ EndPoint = new RelativePoint(0,1, RelativeUnit.Relative)
+ };
+
+ // Use a linear gradient brush beginning at the 6th character and continuing for 11 characters.
+ formattedText.SetForegroundBrush(gradient, 6, 11);
+
+ // Use an Italic font style beginning at the 28th character and continuing for 28 characters.
+ formattedText.SetFontStyle(FontStyle.Italic, 28, 28);
+
+ context.DrawText(formattedText, new Point(10, 0));
+ }
+ }
+}
diff --git a/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs b/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
index 857358f6b2..7f85606957 100644
--- a/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
+++ b/samples/RenderDemo/Pages/GlyphRunPage.xaml.cs
@@ -13,6 +13,7 @@ namespace RenderDemo.Pages
private GlyphTypeface _glyphTypeface = Typeface.Default.GlyphTypeface;
private readonly Random _rand = new Random();
private ushort[] _glyphIndices = new ushort[1];
+ private char[] _characters = new char[1];
private float _fontSize = 20;
private int _direction = 10;
@@ -38,7 +39,7 @@ namespace RenderDemo.Pages
private void UpdateGlyphRun()
{
- var c = (uint)_rand.Next(65, 90);
+ var c = (char)_rand.Next(65, 90);
if (_fontSize + _direction > 200)
{
@@ -54,6 +55,8 @@ namespace RenderDemo.Pages
_glyphIndices[0] = _glyphTypeface.GetGlyph(c);
+ _characters[0] = c;
+
var scale = (double)_fontSize / _glyphTypeface.DesignEmHeight;
var drawingGroup = new DrawingGroup();
@@ -61,7 +64,7 @@ namespace RenderDemo.Pages
var glyphRunDrawing = new GlyphRunDrawing
{
Foreground = Brushes.Black,
- GlyphRun = new GlyphRun(_glyphTypeface, _fontSize, _glyphIndices),
+ GlyphRun = new GlyphRun(_glyphTypeface, _fontSize, _characters, _glyphIndices)
};
drawingGroup.Children.Add(glyphRunDrawing);
diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs
index 6a940a54f1..2d4f6a305f 100644
--- a/src/Android/Avalonia.Android/AndroidPlatform.cs
+++ b/src/Android/Avalonia.Android/AndroidPlatform.cs
@@ -10,7 +10,7 @@ using Avalonia.Input.Platform;
using Avalonia.OpenGL.Egl;
using Avalonia.Platform;
using Avalonia.Rendering;
-using Avalonia.Shared.PlatformSupport;
+using Avalonia.PlatformSupport;
using Avalonia.Skia;
namespace Avalonia
@@ -59,8 +59,7 @@ namespace Avalonia.Android
.Bind().ToSingleton()
.Bind().ToConstant(new ChoreographerTimer())
.Bind().ToConstant(new RenderLoop())
- .Bind().ToSingleton()
- .Bind().ToConstant(new AssetLoader(appType.Assembly));
+ .Bind().ToSingleton();
SkiaPlatform.Initialize();
diff --git a/src/Android/Avalonia.Android/AppBuilder.cs b/src/Android/Avalonia.Android/AppBuilder.cs
index 805bb61655..04f1ff00d0 100644
--- a/src/Android/Avalonia.Android/AppBuilder.cs
+++ b/src/Android/Avalonia.Android/AppBuilder.cs
@@ -1,5 +1,5 @@
using Avalonia.Controls;
-using Avalonia.Shared.PlatformSupport;
+using Avalonia.PlatformSupport;
namespace Avalonia
{
diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj
index 8c6775733f..5c33dbcea6 100644
--- a/src/Android/Avalonia.Android/Avalonia.Android.csproj
+++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj
@@ -5,9 +5,11 @@
+
+ TargetFramework=netstandard2.0
+
-
diff --git a/src/Android/Avalonia.Android/RuntimeInfo.cs b/src/Android/Avalonia.Android/RuntimeInfo.cs
deleted file mode 100644
index bb2466c357..0000000000
--- a/src/Android/Avalonia.Android/RuntimeInfo.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Avalonia.Platform;
-
-namespace Avalonia.Shared.PlatformSupport
-{
- internal partial class StandardRuntimePlatform
- {
- public RuntimePlatformInfo GetRuntimeInfo() => new RuntimePlatformInfo
- {
- IsCoreClr = false,
- IsDesktop = false,
- IsMobile = true,
- IsDotNetFramework = false,
- IsMono = true,
- IsUnix = true,
- OperatingSystem = OperatingSystemType.Android
- };
- }
-}
\ No newline at end of file
diff --git a/src/Avalonia.Base/Platform/IRuntimePlatform.cs b/src/Avalonia.Base/Platform/IRuntimePlatform.cs
index a0d5d611b3..850757a1ee 100644
--- a/src/Avalonia.Base/Platform/IRuntimePlatform.cs
+++ b/src/Avalonia.Base/Platform/IRuntimePlatform.cs
@@ -1,5 +1,4 @@
using System;
-using System.Reflection;
namespace Avalonia.Platform
{
@@ -23,6 +22,7 @@ namespace Avalonia.Platform
public OperatingSystemType OperatingSystem { get; set; }
public bool IsDesktop { get; set; }
public bool IsMobile { get; set; }
+ public bool IsBrowser { get; set; }
public bool IsCoreClr { get; set; }
public bool IsMono { get; set; }
public bool IsDotNetFramework { get; set; }
@@ -36,6 +36,7 @@ namespace Avalonia.Platform
Linux,
OSX,
Android,
- iOS
+ iOS,
+ Browser
}
}
diff --git a/src/Avalonia.Base/Utilities/ImmutableReadOnlyListStructEnumerator.cs b/src/Avalonia.Base/Utilities/ImmutableReadOnlyListStructEnumerator.cs
index 90d1c52ff5..251dfe4351 100644
--- a/src/Avalonia.Base/Utilities/ImmutableReadOnlyListStructEnumerator.cs
+++ b/src/Avalonia.Base/Utilities/ImmutableReadOnlyListStructEnumerator.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace Avalonia.Utilities
{
- public struct ImmutableReadOnlyListStructEnumerator : IEnumerator, IEnumerator
+ public struct ImmutableReadOnlyListStructEnumerator : IEnumerator
{
private readonly IReadOnlyList _readOnlyList;
private int _pos;
diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs
index 95ee73be4e..5d71a499e3 100644
--- a/src/Avalonia.Controls.DataGrid/DataGrid.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs
@@ -2215,7 +2215,14 @@ namespace Avalonia.Controls
/// PointerWheelEventArgs
protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
{
- e.Handled = e.Handled || UpdateScroll(e.Delta * DATAGRID_mouseWheelDelta);
+ if(UpdateScroll(e.Delta * DATAGRID_mouseWheelDelta))
+ {
+ e.Handled = true;
+ }
+ else
+ {
+ e.Handled = e.Handled || !ScrollViewer.GetIsScrollChainingEnabled(this);
+ }
}
internal bool UpdateScroll(Vector delta)
diff --git a/src/Avalonia.Controls/ApiCompatBaseline.txt b/src/Avalonia.Controls/ApiCompatBaseline.txt
index a7560c37f2..2c206b53f6 100644
--- a/src/Avalonia.Controls/ApiCompatBaseline.txt
+++ b/src/Avalonia.Controls/ApiCompatBaseline.txt
@@ -43,6 +43,10 @@ MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.Off
MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.AvaloniaProperty Avalonia.AvaloniaProperty Avalonia.Controls.Notifications.NotificationCard.CloseOnClickProperty' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.Platform.ITopLevelNativeMenuExporter.SetNativeMenu(Avalonia.Controls.NativeMenu)' is present in the contract but not in the implementation.
+MembersMustExist : Member 'protected Avalonia.Media.FormattedText Avalonia.Controls.Presenters.TextPresenter.CreateFormattedText()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'public Avalonia.Media.FormattedText Avalonia.Controls.Presenters.TextPresenter.FormattedText.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'public System.Int32 Avalonia.Controls.Presenters.TextPresenter.GetCaretIndex(Avalonia.Point)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'protected void Avalonia.Controls.Presenters.TextPresenter.InvalidateFormattedText()' does not exist in the implementation but it does exist in the contract.
CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Primitives.PopupRoot' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract.
EnumValuesMustMatch : Enum value 'Avalonia.Platform.ExtendClientAreaChromeHints Avalonia.Platform.ExtendClientAreaChromeHints.Default' is (System.Int32)2 in the implementation but (System.Int32)1 in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Nullable Avalonia.Platform.ITopLevelImpl.FrameSize' is present in the implementation but not in the contract.
@@ -63,4 +67,4 @@ InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platfor
MembersMustExist : Member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size)' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size, Avalonia.Platform.PlatformResizeReason)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.ITrayIconImpl Avalonia.Platform.IWindowingPlatform.CreateTrayIcon()' is present in the implementation but not in the contract.
-Total Issues: 64
+Total Issues: 68
diff --git a/src/Avalonia.Controls/AppBuilderBase.cs b/src/Avalonia.Controls/AppBuilderBase.cs
index d44b2ab0db..8779ae9122 100644
--- a/src/Avalonia.Controls/AppBuilderBase.cs
+++ b/src/Avalonia.Controls/AppBuilderBase.cs
@@ -14,9 +14,9 @@ namespace Avalonia.Controls
public abstract class AppBuilderBase where TAppBuilder : AppBuilderBase, new()
{
private static bool s_setupWasAlreadyCalled;
- private Action _optionsInitializers;
- private Func _appFactory;
- private IApplicationLifetime _lifetime;
+ private Action? _optionsInitializers;
+ private Func? _appFactory;
+ private IApplicationLifetime? _lifetime;
///
/// Gets or sets the instance.
@@ -31,32 +31,32 @@ namespace Avalonia.Controls
///
/// Gets the instance being initialized.
///
- public Application Instance { get; private set; }
+ public Application? Instance { get; private set; }
///
/// Gets the type of the Instance (even if it's not created yet)
///
- public Type ApplicationType { get; private set; }
+ public Type? ApplicationType { get; private set; }
///
/// Gets or sets a method to call the initialize the windowing subsystem.
///
- public Action WindowingSubsystemInitializer { get; private set; }
+ public Action? WindowingSubsystemInitializer { get; private set; }
///
/// Gets the name of the currently selected windowing subsystem.
///
- public string WindowingSubsystemName { get; private set; }
+ public string? WindowingSubsystemName { get; private set; }
///
/// Gets or sets a method to call the initialize the windowing subsystem.
///
- public Action RenderingSubsystemInitializer { get; private set; }
+ public Action? RenderingSubsystemInitializer { get; private set; }
///
/// Gets the name of the currently selected rendering subsystem.
///
- public string RenderingSubsystemName { get; private set; }
+ public string? RenderingSubsystemName { get; private set; }
///
/// Gets or sets a method to call after the is setup.
@@ -126,7 +126,7 @@ namespace Avalonia.Controls
/// The window type.
/// A delegate that will be called to create a data context for the window (optional).
[Obsolete("Use either lifetimes or AppMain overload. See see https://github.com/AvaloniaUI/Avalonia/wiki/Application-lifetimes for details")]
- public void Start(Func
/// The object that raised the event.
/// The event data.
- private void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void ItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
// Update the cache
if (e.Action == NotifyCollectionChangedAction.Remove && e.OldItems != null)
{
for (int index = 0; index < e.OldItems.Count; index++)
{
- _items.RemoveAt(e.OldStartingIndex);
+ _items!.RemoveAt(e.OldStartingIndex);
}
}
- if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null && _items.Count >= e.NewStartingIndex)
+ if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null && _items!.Count >= e.NewStartingIndex)
{
for (int index = 0; index < e.NewItems.Count; index++)
{
- _items.Insert(e.NewStartingIndex + index, e.NewItems[index]);
+ _items.Insert(e.NewStartingIndex + index, e.NewItems[index]!);
}
}
if (e.Action == NotifyCollectionChangedAction.Replace && e.NewItems != null && e.OldItems != null)
{
for (int index = 0; index < e.NewItems.Count; index++)
{
- _items[e.NewStartingIndex] = e.NewItems[index];
+ _items![e.NewStartingIndex] = e.NewItems[index]!;
}
}
@@ -2228,7 +2229,7 @@ namespace Avalonia.Controls
{
for (int index = 0; index < e.OldItems.Count; index++)
{
- _view.Remove(e.OldItems[index]);
+ _view!.Remove(e.OldItems[index]!);
}
}
@@ -2270,7 +2271,7 @@ namespace Avalonia.Controls
RefreshView();
// Fire the Populated event containing the read-only view data.
- PopulatedEventArgs populated = new PopulatedEventArgs(new ReadOnlyCollection(_view));
+ PopulatedEventArgs populated = new PopulatedEventArgs(new ReadOnlyCollection(_view!));
OnPopulated(populated);
if (SelectionAdapter != null && SelectionAdapter.Items != _view)
@@ -2278,7 +2279,7 @@ namespace Avalonia.Controls
SelectionAdapter.Items = _view;
}
- bool isDropDownOpen = _userCalledPopulate && (_view.Count > 0);
+ bool isDropDownOpen = _userCalledPopulate && (_view!.Count > 0);
if (isDropDownOpen != IsDropDownOpen)
{
_ignorePropertyChange = true;
@@ -2306,20 +2307,20 @@ namespace Avalonia.Controls
private void UpdateTextCompletion(bool userInitiated)
{
// By default this method will clear the selected value
- object newSelectedItem = null;
- string text = Text;
+ object? newSelectedItem = null;
+ string? text = Text;
// Text search is StartsWith explicit and only when enabled, in
// line with WPF's ComboBox lookup. When in use it will associate
// a Value with the Text if it is found in ItemsSource. This is
// only valid when there is data and the user initiated the action.
- if (_view.Count > 0)
+ if (_view!.Count > 0)
{
if (IsTextCompletionEnabled && TextBox != null && userInitiated)
{
int currentLength = TextBox.Text?.Length ?? 0;
int selectionStart = TextBoxSelectionStart;
- if (selectionStart == text.Length && selectionStart > _textSelectionStart)
+ if (selectionStart == text?.Length && selectionStart > _textSelectionStart)
{
// When the FilterMode dependency property is set to
// either StartsWith or StartsWithCaseSensitive, the
@@ -2327,7 +2328,7 @@ namespace Avalonia.Controls
// performance on the lookup. It assumes that the
// FilterMode the user has selected is an acceptable
// case sensitive matching function for their scenario.
- object top = FilterMode == AutoCompleteFilterMode.StartsWith || FilterMode == AutoCompleteFilterMode.StartsWithCaseSensitive
+ object? top = FilterMode == AutoCompleteFilterMode.StartsWith || FilterMode == AutoCompleteFilterMode.StartsWithCaseSensitive
? _view[0]
: TryGetMatch(text, _view, AutoCompleteSearch.GetFilter(AutoCompleteFilterMode.StartsWith));
@@ -2335,18 +2336,18 @@ namespace Avalonia.Controls
if (top != null)
{
newSelectedItem = top;
- string topString = FormatValue(top, true);
+ string? topString = FormatValue(top, true);
// Only replace partially when the two words being the same
- int minLength = Math.Min(topString.Length, Text.Length);
- if (AutoCompleteSearch.Equals(Text.Substring(0, minLength), topString.Substring(0, minLength)))
+ int minLength = Math.Min(topString?.Length ?? 0, Text?.Length ?? 0);
+ if (AutoCompleteSearch.Equals(Text?.Substring(0, minLength), topString?.Substring(0, minLength)))
{
// Update the text
UpdateTextValue(topString);
// Select the text past the user's caret
TextBox.SelectionStart = currentLength;
- TextBox.SelectionEnd = topString.Length;
+ TextBox.SelectionEnd = topString?.Length ?? 0;
}
}
}
@@ -2392,8 +2393,11 @@ namespace Avalonia.Controls
/// The predicate to use for the partial or
/// exact match.
/// Returns the object or null.
- private object TryGetMatch(string searchText, AvaloniaList view, AutoCompleteFilterPredicate predicate)
+ private object? TryGetMatch(string? searchText, AvaloniaList view, AutoCompleteFilterPredicate? predicate)
{
+ if (predicate is null)
+ return null;
+
if (view != null && view.Count > 0)
{
foreach (object o in view)
@@ -2428,9 +2432,9 @@ namespace Avalonia.Controls
/// that is displayed in the text box part.
///
/// The new item.
- private void OnSelectedItemChanged(object newItem)
+ private void OnSelectedItemChanged(object? newItem)
{
- string text;
+ string? text;
if (newItem == null)
{
@@ -2461,9 +2465,9 @@ namespace Avalonia.Controls
///
/// The source object.
/// The selection changed event data.
- private void OnAdapterSelectionChanged(object sender, SelectionChangedEventArgs e)
+ private void OnAdapterSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
- SelectedItem = _adapter.SelectedItem;
+ SelectedItem = _adapter!.SelectedItem;
}
//TODO Check UpdateTextCompletion
@@ -2472,7 +2476,7 @@ namespace Avalonia.Controls
///
/// The source object.
/// The event data.
- private void OnAdapterSelectionComplete(object sender, RoutedEventArgs e)
+ private void OnAdapterSelectionComplete(object? sender, RoutedEventArgs e)
{
IsDropDownOpen = false;
@@ -2482,7 +2486,7 @@ namespace Avalonia.Controls
// Text should not be selected
ClearTextBoxSelection();
- TextBox.Focus();
+ TextBox!.Focus();
}
///
@@ -2490,7 +2494,7 @@ namespace Avalonia.Controls
///
/// The source object.
/// The event data.
- private void OnAdapterSelectionCanceled(object sender, RoutedEventArgs e)
+ private void OnAdapterSelectionCanceled(object? sender, RoutedEventArgs e)
{
UpdateTextValue(SearchText);
@@ -2510,7 +2514,7 @@ namespace Avalonia.Controls
///
/// The built-in search mode.
/// Returns the string-based comparison function.
- public static AutoCompleteFilterPredicate GetFilter(AutoCompleteFilterMode FilterMode)
+ public static AutoCompleteFilterPredicate? GetFilter(AutoCompleteFilterMode FilterMode)
{
switch (FilterMode)
{
@@ -2566,9 +2570,11 @@ namespace Avalonia.Controls
/// The string value to search for.
/// The string comparison type.
/// Returns true when the substring is found.
- private static bool Contains(string s, string value, StringComparison comparison)
+ private static bool Contains(string? s, string? value, StringComparison comparison)
{
- return s.IndexOf(value, comparison) >= 0;
+ if (s is not null && value is not null)
+ return s.IndexOf(value, comparison) >= 0;
+ return false;
}
///
@@ -2577,9 +2583,11 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool StartsWith(string text, string value)
+ public static bool StartsWith(string? text, string? value)
{
- return value.StartsWith(text, StringComparison.CurrentCultureIgnoreCase);
+ if (value is not null && text is not null)
+ return value.StartsWith(text, StringComparison.CurrentCultureIgnoreCase);
+ return false;
}
///
@@ -2588,9 +2596,11 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool StartsWithCaseSensitive(string text, string value)
+ public static bool StartsWithCaseSensitive(string? text, string? value)
{
- return value.StartsWith(text, StringComparison.CurrentCulture);
+ if (value is not null && text is not null)
+ return value.StartsWith(text, StringComparison.CurrentCulture);
+ return false;
}
///
@@ -2599,9 +2609,11 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool StartsWithOrdinal(string text, string value)
+ public static bool StartsWithOrdinal(string? text, string? value)
{
- return value.StartsWith(text, StringComparison.OrdinalIgnoreCase);
+ if (value is not null && text is not null)
+ return value.StartsWith(text, StringComparison.OrdinalIgnoreCase);
+ return false;
}
///
@@ -2610,9 +2622,11 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool StartsWithOrdinalCaseSensitive(string text, string value)
+ public static bool StartsWithOrdinalCaseSensitive(string? text, string? value)
{
- return value.StartsWith(text, StringComparison.Ordinal);
+ if (value is not null && text is not null)
+ return value.StartsWith(text, StringComparison.Ordinal);
+ return false;
}
///
@@ -2622,7 +2636,7 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool Contains(string text, string value)
+ public static bool Contains(string? text, string? value)
{
return Contains(value, text, StringComparison.CurrentCultureIgnoreCase);
}
@@ -2633,7 +2647,7 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool ContainsCaseSensitive(string text, string value)
+ public static bool ContainsCaseSensitive(string? text, string? value)
{
return Contains(value, text, StringComparison.CurrentCulture);
}
@@ -2644,7 +2658,7 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool ContainsOrdinal(string text, string value)
+ public static bool ContainsOrdinal(string? text, string? value)
{
return Contains(value, text, StringComparison.OrdinalIgnoreCase);
}
@@ -2655,7 +2669,7 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool ContainsOrdinalCaseSensitive(string text, string value)
+ public static bool ContainsOrdinalCaseSensitive(string? text, string? value)
{
return Contains(value, text, StringComparison.Ordinal);
}
@@ -2666,9 +2680,9 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool Equals(string text, string value)
+ public static bool Equals(string? text, string? value)
{
- return value.Equals(text, StringComparison.CurrentCultureIgnoreCase);
+ return string.Equals(value, text, StringComparison.CurrentCultureIgnoreCase);
}
///
@@ -2677,9 +2691,9 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool EqualsCaseSensitive(string text, string value)
+ public static bool EqualsCaseSensitive(string? text, string? value)
{
- return value.Equals(text, StringComparison.CurrentCulture);
+ return string.Equals(value, text, StringComparison.CurrentCulture);
}
///
@@ -2688,9 +2702,9 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool EqualsOrdinal(string text, string value)
+ public static bool EqualsOrdinal(string? text, string? value)
{
- return value.Equals(text, StringComparison.OrdinalIgnoreCase);
+ return string.Equals(value, text, StringComparison.OrdinalIgnoreCase);
}
///
@@ -2699,9 +2713,9 @@ namespace Avalonia.Controls
/// The AutoCompleteBox prefix text.
/// The item's string value.
/// Returns true if the condition is met.
- public static bool EqualsOrdinalCaseSensitive(string text, string value)
+ public static bool EqualsOrdinalCaseSensitive(string? text, string? value)
{
- return value.Equals(text, StringComparison.Ordinal);
+ return string.Equals(value, text, StringComparison.Ordinal);
}
}
@@ -2715,7 +2729,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the string value binding used by the control.
///
- private IBinding _binding;
+ private IBinding? _binding;
#region public T Value
@@ -2739,13 +2753,14 @@ namespace Avalonia.Controls
///
/// Gets or sets the value binding.
///
- public IBinding ValueBinding
+ public IBinding? ValueBinding
{
get { return _binding; }
set
{
_binding = value;
- AvaloniaObjectExtensions.Bind(this, ValueProperty, value);
+ if (value is not null)
+ AvaloniaObjectExtensions.Bind(this, ValueProperty, value);
}
}
@@ -2760,7 +2775,7 @@ namespace Avalonia.Controls
/// setting the initial binding to the provided parameter.
///
/// The initial string value binding.
- public BindingEvaluator(IBinding binding)
+ public BindingEvaluator(IBinding? binding)
: this()
{
ValueBinding = binding;
@@ -2802,7 +2817,7 @@ namespace Avalonia.Controls
/// The object to use as the data context.
/// Returns the evaluated T value of the bound dependency
/// property.
- public T GetDynamicValue(object o)
+ public T GetDynamicValue(object? o)
{
DataContext = o;
return Value;
diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj
index e2c6a714aa..543a513d57 100644
--- a/src/Avalonia.Controls/Avalonia.Controls.csproj
+++ b/src/Avalonia.Controls/Avalonia.Controls.csproj
@@ -18,4 +18,5 @@
+
diff --git a/src/Avalonia.Controls/Border.cs b/src/Avalonia.Controls/Border.cs
index ee67f303f3..ee3be1d5b3 100644
--- a/src/Avalonia.Controls/Border.cs
+++ b/src/Avalonia.Controls/Border.cs
@@ -17,14 +17,14 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty BackgroundProperty =
- AvaloniaProperty.Register(nameof(Background));
+ public static readonly StyledProperty BackgroundProperty =
+ AvaloniaProperty.Register(nameof(Background));
///
/// Defines the property.
///
- public static readonly StyledProperty BorderBrushProperty =
- AvaloniaProperty.Register(nameof(BorderBrush));
+ public static readonly StyledProperty BorderBrushProperty =
+ AvaloniaProperty.Register(nameof(BorderBrush));
///
/// Defines the property.
@@ -91,7 +91,7 @@ namespace Avalonia.Controls
///
/// Gets or sets a brush with which to paint the background.
///
- public IBrush Background
+ public IBrush? Background
{
get { return GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
@@ -100,7 +100,7 @@ namespace Avalonia.Controls
///
/// Gets or sets a brush with which to paint the border.
///
- public IBrush BorderBrush
+ public IBrush? BorderBrush
{
get { return GetValue(BorderBrushProperty); }
set { SetValue(BorderBrushProperty, value); }
diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs
index 8537c9acbc..a7a4759182 100644
--- a/src/Avalonia.Controls/Button.cs
+++ b/src/Avalonia.Controls/Button.cs
@@ -42,30 +42,30 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly DirectProperty
/// The event sender.
/// The event args.
- private void RootDefaultKeyDown(object sender, KeyEventArgs e)
+ private void RootDefaultKeyDown(object? sender, KeyEventArgs e)
{
if (e.Key == Key.Enter && IsVisible && IsEnabled)
{
@@ -558,7 +542,7 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- private void RootCancelKeyDown(object sender, KeyEventArgs e)
+ private void RootCancelKeyDown(object? sender, KeyEventArgs e)
{
if (e.Key == Key.Escape && IsVisible && IsEnabled)
{
@@ -566,6 +550,9 @@ namespace Avalonia.Controls
}
}
+ ///
+ /// Updates the visual state of the control by applying latest PseudoClasses.
+ ///
private void UpdatePseudoClasses(bool isPressed)
{
PseudoClasses.Set(":pressed", isPressed);
diff --git a/src/Avalonia.Controls/ButtonSpinner.cs b/src/Avalonia.Controls/ButtonSpinner.cs
index f1c1a55a17..31aba024ae 100644
--- a/src/Avalonia.Controls/ButtonSpinner.cs
+++ b/src/Avalonia.Controls/ButtonSpinner.cs
@@ -42,11 +42,11 @@ namespace Avalonia.Controls
UpdatePseudoClasses(ButtonSpinnerLocation);
}
- private Button _decreaseButton;
+ private Button? _decreaseButton;
///
/// Gets or sets the DecreaseButton template part.
///
- private Button DecreaseButton
+ private Button? DecreaseButton
{
get { return _decreaseButton; }
set
@@ -63,11 +63,11 @@ namespace Avalonia.Controls
}
}
- private Button _increaseButton;
+ private Button? _increaseButton;
///
/// Gets or sets the IncreaseButton template part.
///
- private Button IncreaseButton
+ private Button? IncreaseButton
{
get
{
@@ -241,8 +241,8 @@ namespace Avalonia.Controls
{
if (e.Sender is ButtonSpinner spinner)
{
- var oldValue = (bool)e.OldValue;
- var newValue = (bool)e.NewValue;
+ var oldValue = (bool)e.OldValue!;
+ var newValue = (bool)e.NewValue!;
spinner.OnAllowSpinChanged(oldValue, newValue);
}
}
@@ -268,7 +268,7 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- private void OnButtonClick(object sender, RoutedEventArgs e)
+ private void OnButtonClick(object? sender, RoutedEventArgs e)
{
if (AllowSpin)
{
diff --git a/src/Avalonia.Controls/Calendar/Calendar.cs b/src/Avalonia.Controls/Calendar/Calendar.cs
index 2c8a7c0831..6c83308b39 100644
--- a/src/Avalonia.Controls/Calendar/Calendar.cs
+++ b/src/Avalonia.Controls/Calendar/Calendar.cs
@@ -240,11 +240,11 @@ namespace Avalonia.Controls
private bool _isShiftPressed;
private bool _displayDateIsChanging = false;
- internal CalendarDayButton FocusButton { get; set; }
- internal CalendarButton FocusCalendarButton { get; set; }
+ internal CalendarDayButton? FocusButton { get; set; }
+ internal CalendarButton? FocusCalendarButton { get; set; }
- internal Panel Root { get; set; }
- internal CalendarItem MonthControl
+ internal Panel? Root { get; set; }
+ internal CalendarItem? MonthControl
{
get
{
@@ -280,7 +280,7 @@ namespace Avalonia.Controls
private void OnFirstDayOfWeekChanged(AvaloniaPropertyChangedEventArgs e)
{
- if (IsValidFirstDayOfWeek(e.NewValue))
+ if (IsValidFirstDayOfWeek(e.NewValue!))
{
UpdateMonths();
}
@@ -373,9 +373,9 @@ namespace Avalonia.Controls
/// The DependencyPropertyChangedEventArgs.
private void OnDisplayModePropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
- CalendarMode mode = (CalendarMode)e.NewValue;
- CalendarMode oldMode = (CalendarMode)e.OldValue;
- CalendarItem monthControl = MonthControl;
+ CalendarMode mode = (CalendarMode)e.NewValue!;
+ CalendarMode oldMode = (CalendarMode)e.OldValue!;
+ CalendarItem? monthControl = MonthControl;
if (monthControl != null)
{
@@ -459,7 +459,7 @@ namespace Avalonia.Controls
}
private void OnSelectionModeChanged(AvaloniaPropertyChangedEventArgs e)
{
- if (IsValidSelectionMode(e.NewValue))
+ if (IsValidSelectionMode(e.NewValue!))
{
_displayDateIsChanging = true;
SelectedDate = null;
@@ -656,7 +656,7 @@ namespace Avalonia.Controls
{
FocusButton.IsCurrent = false;
}
- FocusButton = FindDayButtonFromDay(LastSelectedDate.Value);
+ FocusButton = FindDayButtonFromDay(LastSelectedDate!.Value);
if (FocusButton != null)
{
FocusButton.IsCurrent = HasFocusInternal;
@@ -754,11 +754,11 @@ namespace Avalonia.Controls
private void OnDisplayDateChanged(AvaloniaPropertyChangedEventArgs e)
{
- UpdateDisplayDate(this, (DateTime)e.NewValue, (DateTime)e.OldValue);
+ UpdateDisplayDate(this, (DateTime)e.NewValue!, (DateTime)e.OldValue!);
}
private static void UpdateDisplayDate(Calendar c, DateTime addedDate, DateTime removedDate)
{
- Contract.Requires(c != null);
+ _ = c ?? throw new ArgumentNullException(nameof(c));
// If DisplayDate < DisplayDateStart, DisplayDate = DisplayDateStart
if (DateTime.Compare(addedDate, c.DisplayDateRangeStart) < 0)
@@ -871,7 +871,7 @@ namespace Avalonia.Controls
if (cal.SelectedDates.Count > 0)
{
selectedDateMin = cal.SelectedDates[0];
- Debug.Assert(DateTime.Compare(cal.SelectedDate.Value, selectedDateMin) == 0, "The SelectedDate should be the minimum selected date!");
+ Debug.Assert(DateTime.Compare(cal.SelectedDate!.Value, selectedDateMin) == 0, "The SelectedDate should be the minimum selected date!");
}
else
{
@@ -959,7 +959,7 @@ namespace Avalonia.Controls
if (cal.SelectedDates.Count > 0)
{
selectedDateMax = cal.SelectedDates[0];
- Debug.Assert(DateTime.Compare(cal.SelectedDate.Value, selectedDateMax) == 0, "The SelectedDate should be the maximum SelectedDate!");
+ Debug.Assert(DateTime.Compare(cal.SelectedDate!.Value, selectedDateMax) == 0, "The SelectedDate should be the maximum SelectedDate!");
}
else
{
@@ -1003,9 +1003,9 @@ namespace Avalonia.Controls
///
internal bool CalendarDatePickerDisplayDateFlag { get; set; }
- internal CalendarDayButton FindDayButtonFromDay(DateTime day)
+ internal CalendarDayButton? FindDayButtonFromDay(DateTime day)
{
- CalendarItem monthControl = MonthControl;
+ CalendarItem? monthControl = MonthControl;
// REMOVE_RTM: should be updated if we support MultiCalendar
int count = RowsPerMonth * ColumnsPerMonth;
@@ -1054,7 +1054,7 @@ namespace Avalonia.Controls
internal void OnHeaderClick()
{
Debug.Assert(DisplayMode == CalendarMode.Year || DisplayMode == CalendarMode.Decade, "The DisplayMode should be Year or Decade");
- CalendarItem monthControl = MonthControl;
+ CalendarItem? monthControl = MonthControl;
if (monthControl != null && monthControl.MonthView != null && monthControl.YearView != null)
{
monthControl.MonthView.IsVisible = false;
@@ -1065,7 +1065,7 @@ namespace Avalonia.Controls
internal void ResetStates()
{
- CalendarItem monthControl = MonthControl;
+ CalendarItem? monthControl = MonthControl;
int count = RowsPerMonth * ColumnsPerMonth;
if (monthControl != null)
{
@@ -1083,7 +1083,7 @@ namespace Avalonia.Controls
internal void UpdateMonths()
{
- CalendarItem monthControl = MonthControl;
+ CalendarItem? monthControl = MonthControl;
if (monthControl != null)
{
switch (DisplayMode)
@@ -1163,6 +1163,8 @@ namespace Avalonia.Controls
{
if (HoverEnd != null && HoverStart != null)
{
+ Debug.Assert(MonthControl is not null);
+
int startIndex, endIndex, i;
CalendarItem monthControl = MonthControl;
@@ -1173,7 +1175,7 @@ namespace Avalonia.Controls
for (i = startIndex; i <= endIndex; i++)
{
- if (monthControl.MonthView.Children[i] is CalendarDayButton b)
+ if (monthControl.MonthView!.Children[i] is CalendarDayButton b)
{
b.IsSelected = true;
var d = b.DataContext as DateTime?;
@@ -1201,6 +1203,8 @@ namespace Avalonia.Controls
{
if (HoverEnd != null && HoverStart != null)
{
+ Debug.Assert(MonthControl is not null);
+
CalendarItem monthControl = MonthControl;
if (HoverEndIndex != null && HoverStartIndex != null)
@@ -1212,7 +1216,7 @@ namespace Avalonia.Controls
{
for (i = startIndex; i <= endIndex; i++)
{
- if (monthControl.MonthView.Children[i] is CalendarDayButton b)
+ if (monthControl.MonthView!.Children[i] is CalendarDayButton b)
{
var d = b.DataContext as DateTime?;
@@ -1231,7 +1235,7 @@ namespace Avalonia.Controls
// It is SingleRange
for (i = startIndex; i <= endIndex; i++)
{
- ((CalendarDayButton)monthControl.MonthView.Children[i]).IsSelected = false;
+ ((CalendarDayButton)monthControl.MonthView!.Children[i]).IsSelected = false;
}
}
}
@@ -1239,6 +1243,11 @@ namespace Avalonia.Controls
}
internal void SortHoverIndexes(out int startIndex, out int endIndex)
{
+ Debug.Assert(HoverStart.HasValue);
+ Debug.Assert(HoverEnd.HasValue);
+ Debug.Assert(HoverStartIndex.HasValue);
+ Debug.Assert(HoverEndIndex.HasValue);
+
if (DateTimeHelper.CompareDays(HoverEnd.Value, HoverStart.Value) > 0)
{
startIndex = HoverStartIndex.Value;
@@ -1373,6 +1382,8 @@ namespace Avalonia.Controls
}
private void OnMonthClick()
{
+ Debug.Assert(MonthControl is not null);
+
CalendarItem monthControl = MonthControl;
if (monthControl != null && monthControl.YearView != null && monthControl.MonthView != null)
{
@@ -1400,7 +1411,7 @@ namespace Avalonia.Controls
}
}
- public event EventHandler SelectedDatesChanged;
+ public event EventHandler? SelectedDatesChanged;
///
/// Occurs when the
@@ -1410,19 +1421,19 @@ namespace Avalonia.Controls
///
/// This event occurs after DisplayDate is assigned its new value.
///
- public event EventHandler DisplayDateChanged;
+ public event EventHandler? DisplayDateChanged;
///
/// Occurs when the
///
/// property is changed.
///
- public event EventHandler DisplayModeChanged;
+ public event EventHandler? DisplayModeChanged;
///
/// Inherited code: Requires comment.
///
- internal event EventHandler DayButtonMouseUp;
+ internal event EventHandler? DayButtonMouseUp;
///
/// This method adds the days that were selected by Keyboard to the
@@ -1461,7 +1472,7 @@ namespace Avalonia.Controls
SelectedDates.ClearInternal();
if (shift)
{
- CalendarDayButton b;
+ CalendarDayButton? b;
_isShiftPressed = true;
if (HoverStart == null)
{
@@ -1513,6 +1524,8 @@ namespace Avalonia.Controls
}
else
{
+ Debug.Assert(HoverEndInternal is not null);
+
// For Home, End, PageUp and PageDown Keys there
// is no easy way to predict the index value
b = FindDayButtonFromDay(HoverEndInternal.Value);
@@ -1524,6 +1537,7 @@ namespace Avalonia.Controls
}
}
+ Debug.Assert(HoverEnd is not null);
OnDayClick(HoverEnd.Value);
HighlightDays();
}
@@ -1557,7 +1571,7 @@ namespace Avalonia.Controls
base.OnPointerReleased(e);
if (!HasFocusInternal && e.InitialPressMouseButton == MouseButton.Left)
{
- FocusManager.Instance.Focus(this);
+ FocusManager.Instance?.Focus(this);
}
}
@@ -1876,8 +1890,8 @@ namespace Avalonia.Controls
// since DisplayDate is not equal to
// DateTime.MaxValue we are sure selectedDate is\
// not null
- selectedDate = DateTimeHelper.AddMonths(selectedDate.Value, 1).Value;
- selectedDate = DateTimeHelper.AddDays(selectedDate.Value, -1).Value;
+ selectedDate = DateTimeHelper.AddMonths(selectedDate.Value, 1)!.Value;
+ selectedDate = DateTimeHelper.AddDays(selectedDate.Value, -1)!.Value;
}
else
{
@@ -2098,7 +2112,7 @@ namespace Avalonia.Controls
if (Root != null)
{
- CalendarItem month = e.NameScope.Find(PART_ElementMonth);
+ CalendarItem? month = e.NameScope.Find(PART_ElementMonth);
if (month != null)
{
diff --git a/src/Avalonia.Controls/Calendar/CalendarButton.cs b/src/Avalonia.Controls/Calendar/CalendarButton.cs
index 76af933b55..0a8e4dfae8 100644
--- a/src/Avalonia.Controls/Calendar/CalendarButton.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarButton.cs
@@ -45,7 +45,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets or sets the Calendar associated with this button.
///
- internal Calendar Owner { get; set; }
+ internal Calendar? Owner { get; set; }
///
/// Gets or sets a value indicating whether the button is focused.
@@ -120,7 +120,7 @@ namespace Avalonia.Controls.Primitives
/// stylus touches the tablet PC) while the mouse pointer is over a
/// UIElement.
///
- public event EventHandler CalendarLeftMouseButtonDown;
+ public event EventHandler? CalendarLeftMouseButtonDown;
///
/// Occurs when the left mouse button is released (or the tip of the
@@ -128,7 +128,7 @@ namespace Avalonia.Controls.Primitives
/// stylus) is over a UIElement (or while a UIElement holds mouse
/// capture).
///
- public event EventHandler CalendarLeftMouseButtonUp;
+ public event EventHandler? CalendarLeftMouseButtonUp;
///
/// Provides class handling for the MouseLeftButtonDown event that
diff --git a/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs b/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs
index cd9c80d3e0..c1f487c32d 100644
--- a/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs
@@ -123,15 +123,15 @@ namespace Avalonia.Controls
private const string ElementPopup = "PART_Popup";
private const string ElementCalendar = "PART_Calendar";
- private Calendar _calendar;
+ private Calendar? _calendar;
private string _defaultText;
- private Button _dropDownButton;
+ private Button? _dropDownButton;
//private Canvas _outsideCanvas;
//private Canvas _outsidePopupCanvas;
- private Popup _popUp;
- private TextBox _textBox;
- private IDisposable _textBoxTextChangedSubscription;
- private IDisposable _buttonPointerPressedSubscription;
+ private Popup? _popUp;
+ private TextBox? _textBox;
+ private IDisposable? _textBoxTextChangedSubscription;
+ private IDisposable? _buttonPointerPressedSubscription;
private DateTime? _onOpenSelectedDate;
private bool _settingSelectedDate;
@@ -141,7 +141,7 @@ namespace Avalonia.Controls
private DateTime? _displayDateEnd;
private bool _isDropDownOpen;
private DateTime? _selectedDate;
- private string _text;
+ private string? _text;
private bool _suspendTextChangeHandler = false;
private bool _isPopupClosing = false;
private bool _ignoreButtonClick = false;
@@ -153,7 +153,7 @@ namespace Avalonia.Controls
/// A collection of dates that cannot be selected. The default value is
/// an empty collection.
///
- public CalendarBlackoutDatesCollection BlackoutDates { get; private set; }
+ public CalendarBlackoutDatesCollection? BlackoutDates { get; private set; }
public static readonly DirectProperty DisplayDateProperty =
AvaloniaProperty.RegisterDirect(
@@ -200,12 +200,12 @@ namespace Avalonia.Controls
defaultValue: "d",
validate: IsValidDateFormatString);
- public static readonly DirectProperty TextProperty =
- AvaloniaProperty.RegisterDirect(
+ public static readonly DirectProperty TextProperty =
+ AvaloniaProperty.RegisterDirect(
nameof(Text),
o => o.Text,
(o, v) => o.Text = v);
- public static readonly StyledProperty WatermarkProperty =
+ public static readonly StyledProperty WatermarkProperty =
TextBox.WatermarkProperty.AddOwner();
public static readonly StyledProperty UseFloatingWatermarkProperty =
TextBox.UseFloatingWatermarkProperty.AddOwner();
@@ -361,13 +361,13 @@ namespace Avalonia.Controls
///
/// The text entered parses to a date that is not selectable.
///
- public string Text
+ public string? Text
{
get { return _text; }
set { SetAndRaise(TextProperty, ref _text, value); }
}
- public string Watermark
+ public string? Watermark
{
get { return GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
@@ -401,26 +401,26 @@ namespace Avalonia.Controls
/// Occurs when the drop-down
/// is closed.
///
- public event EventHandler CalendarClosed;
+ public event EventHandler? CalendarClosed;
///
/// Occurs when the drop-down
/// is opened.
///
- public event EventHandler CalendarOpened;
+ public event EventHandler? CalendarOpened;
///
/// Occurs when
/// is assigned a value that cannot be interpreted as a date.
///
- public event EventHandler DateValidationError;
+ public event EventHandler? DateValidationError;
///
/// Occurs when the
///
/// property is changed.
///
- public event EventHandler SelectedDateChanged;
+ public event EventHandler? SelectedDateChanged;
static CalendarDatePicker()
{
@@ -579,14 +579,14 @@ namespace Avalonia.Controls
private void OnIsDropDownOpenChanged(AvaloniaPropertyChangedEventArgs e)
{
- var oldValue = (bool)e.OldValue;
- var value = (bool)e.NewValue;
+ var oldValue = (bool)e.OldValue!;
+ var value = (bool)e.NewValue!;
if (_popUp != null && _popUp.Child != null)
{
if (value != oldValue)
{
- if (_calendar.DisplayMode != CalendarMode.Month)
+ if (_calendar!.DisplayMode != CalendarMode.Month)
{
_calendar.DisplayMode = CalendarMode.Month;
}
@@ -660,7 +660,7 @@ namespace Avalonia.Controls
if (date != null)
{
- string s = DateTimeToString((DateTime)date);
+ string? s = DateTimeToString((DateTime)date);
Text = s;
}
}
@@ -679,8 +679,8 @@ namespace Avalonia.Controls
}
private void OnTextChanged(AvaloniaPropertyChangedEventArgs e)
{
- var oldValue = (string)e.OldValue;
- var value = (string)e.NewValue;
+ var oldValue = (string?)e.OldValue;
+ var value = (string?)e.NewValue;
if (!_suspendTextChangeHandler)
{
@@ -731,7 +731,7 @@ namespace Avalonia.Controls
}
private void OnDateSelected(DateTime? addedDate, DateTime? removedDate)
{
- EventHandler handler = this.SelectedDateChanged;
+ EventHandler? handler = this.SelectedDateChanged;
if (null != handler)
{
Collection addedItems = new Collection();
@@ -759,23 +759,23 @@ namespace Avalonia.Controls
CalendarOpened?.Invoke(this, e);
}
- private void Calendar_DayButtonMouseUp(object sender, PointerReleasedEventArgs e)
+ private void Calendar_DayButtonMouseUp(object? sender, PointerReleasedEventArgs e)
{
Focus();
IsDropDownOpen = false;
}
- private void Calendar_DisplayDateChanged(object sender, CalendarDateChangedEventArgs e)
+ private void Calendar_DisplayDateChanged(object? sender, CalendarDateChangedEventArgs e)
{
if (e.AddedDate != this.DisplayDate)
{
- SetValue(DisplayDateProperty, (DateTime) e.AddedDate);
+ SetValue(DisplayDateProperty, (DateTime) e.AddedDate!);
}
}
- private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
+ private void Calendar_SelectedDatesChanged(object? sender, SelectionChangedEventArgs e)
{
Debug.Assert(e.AddedItems.Count < 2, "There should be less than 2 AddedItems!");
- if (e.AddedItems.Count > 0 && SelectedDate.HasValue && DateTime.Compare((DateTime)e.AddedItems[0], SelectedDate.Value) != 0)
+ if (e.AddedItems.Count > 0 && SelectedDate.HasValue && DateTime.Compare((DateTime)e.AddedItems[0]!, SelectedDate.Value) != 0)
{
SelectedDate = (DateTime?)e.AddedItems[0];
}
@@ -796,7 +796,7 @@ namespace Avalonia.Controls
}
}
}
- private void Calendar_PointerReleased(object sender, PointerReleasedEventArgs e)
+ private void Calendar_PointerReleased(object? sender, PointerReleasedEventArgs e)
{
if (e.InitialPressMouseButton == MouseButton.Left)
@@ -804,10 +804,9 @@ namespace Avalonia.Controls
e.Handled = true;
}
}
- private void Calendar_KeyDown(object sender, KeyEventArgs e)
+ private void Calendar_KeyDown(object? sender, KeyEventArgs e)
{
- Calendar c = sender as Calendar;
- Contract.Requires(c != null);
+ Calendar? c = sender as Calendar ?? throw new ArgumentException("Sender must be Calendar.", nameof(sender));
if (!e.Handled && (e.Key == Key.Enter || e.Key == Key.Space || e.Key == Key.Escape) && c.DisplayMode == CalendarMode.Month)
{
@@ -820,11 +819,11 @@ namespace Avalonia.Controls
}
}
}
- private void TextBox_GotFocus(object sender, RoutedEventArgs e)
+ private void TextBox_GotFocus(object? sender, RoutedEventArgs e)
{
IsDropDownOpen = false;
}
- private void TextBox_KeyDown(object sender, KeyEventArgs e)
+ private void TextBox_KeyDown(object? sender, KeyEventArgs e)
{
if (!e.Handled)
{
@@ -840,11 +839,11 @@ namespace Avalonia.Controls
_suspendTextChangeHandler = false;
}
}
- private void DropDownButton_PointerPressed(object sender, PointerPressedEventArgs e)
+ private void DropDownButton_PointerPressed(object? sender, PointerPressedEventArgs e)
{
_ignoreButtonClick = _isPopupClosing;
}
- private void DropDownButton_Click(object sender, RoutedEventArgs e)
+ private void DropDownButton_Click(object? sender, RoutedEventArgs e)
{
if (!_ignoreButtonClick)
{
@@ -855,7 +854,7 @@ namespace Avalonia.Controls
_ignoreButtonClick = false;
}
}
- private void PopUp_Closed(object sender, EventArgs e)
+ private void PopUp_Closed(object? sender, EventArgs e)
{
IsDropDownOpen = false;
@@ -891,7 +890,7 @@ namespace Avalonia.Controls
private void OpenPopUp()
{
_onOpenSelectedDate = SelectedDate;
- _popUp.IsOpen = true;
+ _popUp!.IsOpen = true;
}
///
@@ -914,7 +913,7 @@ namespace Avalonia.Controls
{
newSelectedDate = DateTime.Parse(text, DateTimeHelper.GetCurrentDateFormat());
- if (Calendar.IsValidDateSelection(this._calendar, newSelectedDate))
+ if (Calendar.IsValidDateSelection(this._calendar!, newSelectedDate))
{
return newSelectedDate;
}
@@ -941,7 +940,7 @@ namespace Avalonia.Controls
}
return null;
}
- private string DateTimeToString(DateTime d)
+ private string? DateTimeToString(DateTime d)
{
DateTimeFormatInfo dtfi = DateTimeHelper.GetCurrentDateFormat();
@@ -982,7 +981,7 @@ namespace Avalonia.Controls
{
SetSelectedDate();
IsDropDownOpen = true;
- _calendar.Focus();
+ _calendar!.Focus();
}
private void SetSelectedDate()
{
@@ -1001,7 +1000,7 @@ namespace Avalonia.Controls
// ex: SelectedDate = DateTime(1008,12,19) but when
// "12/19/08" is parsed it is interpreted as
// DateTime(2008,12,19)
- string selectedDate = DateTimeToString(SelectedDate.Value);
+ string? selectedDate = DateTimeToString(SelectedDate.Value);
if (selectedDate == s)
{
return;
@@ -1053,7 +1052,7 @@ namespace Avalonia.Controls
// SelectedDate value:
if (SelectedDate != null)
{
- string newtext = this.DateTimeToString(SelectedDate.Value);
+ string? newtext = this.DateTimeToString(SelectedDate.Value);
SetValue(TextProperty, newtext);
return SelectedDate;
}
diff --git a/src/Avalonia.Controls/Calendar/CalendarDateRange.cs b/src/Avalonia.Controls/Calendar/CalendarDateRange.cs
index 47a0ad047b..88bc5ed7bd 100644
--- a/src/Avalonia.Controls/Calendar/CalendarDateRange.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarDateRange.cs
@@ -65,7 +65,7 @@ namespace Avalonia.Controls
/// Inherited code: Requires comment 2.
internal bool ContainsAny(CalendarDateRange range)
{
- Contract.Requires(range != null);
+ _ = range ?? throw new ArgumentNullException(nameof(range));
int start = DateTime.Compare(Start, range.Start);
diff --git a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs
index d5748bb9e4..2ba4e36260 100644
--- a/src/Avalonia.Controls/Calendar/CalendarDayButton.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarDayButton.cs
@@ -40,7 +40,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets or sets the Calendar associated with this button.
///
- internal Calendar Owner { get; set; }
+ internal Calendar? Owner { get; set; }
internal int Index { get; set; }
///
@@ -177,7 +177,7 @@ namespace Avalonia.Controls.Primitives
/// stylus touches the tablet PC) while the mouse pointer is over a
/// UIElement.
///
- public event EventHandler CalendarDayButtonMouseDown;
+ public event EventHandler? CalendarDayButtonMouseDown;
///
/// Occurs when the left mouse button is released (or the tip of the
@@ -185,7 +185,7 @@ namespace Avalonia.Controls.Primitives
/// stylus) is over a UIElement (or while a UIElement holds mouse
/// capture).
///
- public event EventHandler CalendarDayButtonMouseUp;
+ public event EventHandler? CalendarDayButtonMouseUp;
///
/// Provides class handling for the MouseLeftButtonDown event that
diff --git a/src/Avalonia.Controls/Calendar/CalendarItem.cs b/src/Avalonia.Controls/Calendar/CalendarItem.cs
index e830717b95..616b9083ff 100644
--- a/src/Avalonia.Controls/Calendar/CalendarItem.cs
+++ b/src/Avalonia.Controls/Calendar/CalendarItem.cs
@@ -33,10 +33,10 @@ namespace Avalonia.Controls.Primitives
private const string PART_ElementMonthView = "MonthView";
private const string PART_ElementYearView = "YearView";
- private Button _headerButton;
- private Button _nextButton;
- private Button _previousButton;
- private ITemplate _dayTitleTemplate;
+ private Button? _headerButton;
+ private Button? _nextButton;
+ private Button? _previousButton;
+ private ITemplate? _dayTitleTemplate;
private DateTime _currentMonth;
private bool _isMouseLeftButtonDown = false;
@@ -45,11 +45,11 @@ namespace Avalonia.Controls.Primitives
private System.Globalization.Calendar _calendar = new System.Globalization.GregorianCalendar();
- private PointerPressedEventArgs _downEventArg;
- private PointerPressedEventArgs _downEventArgYearView;
+ private PointerPressedEventArgs? _downEventArg;
+ private PointerPressedEventArgs? _downEventArgYearView;
- internal Calendar Owner { get; set; }
- internal CalendarDayButton CurrentButton { get; set; }
+ internal Calendar? Owner { get; set; }
+ internal CalendarDayButton? CurrentButton { get; set; }
public static readonly StyledProperty HeaderBackgroundProperty = Calendar.HeaderBackgroundProperty.AddOwner();
public IBrush HeaderBackground
@@ -57,13 +57,13 @@ namespace Avalonia.Controls.Primitives
get { return GetValue(HeaderBackgroundProperty); }
set { SetValue(HeaderBackgroundProperty, value); }
}
- public static readonly DirectProperty> DayTitleTemplateProperty =
- AvaloniaProperty.RegisterDirect>(
+ public static readonly DirectProperty?> DayTitleTemplateProperty =
+ AvaloniaProperty.RegisterDirect?>(
nameof(DayTitleTemplate),
o => o.DayTitleTemplate,
(o,v) => o.DayTitleTemplate = v,
defaultBindingMode: BindingMode.OneTime);
- public ITemplate DayTitleTemplate
+ public ITemplate? DayTitleTemplate
{
get { return _dayTitleTemplate; }
set { SetAndRaise(DayTitleTemplateProperty, ref _dayTitleTemplate, value); }
@@ -73,7 +73,7 @@ namespace Avalonia.Controls.Primitives
/// Gets the button that allows switching between month mode, year mode,
/// and decade mode.
///
- internal Button HeaderButton
+ internal Button? HeaderButton
{
get { return _headerButton; }
private set
@@ -94,7 +94,7 @@ namespace Avalonia.Controls.Primitives
/// Gets the button that displays the next page of the calendar when it
/// is clicked.
///
- internal Button NextButton
+ internal Button? NextButton
{
get { return _nextButton; }
private set
@@ -125,7 +125,7 @@ namespace Avalonia.Controls.Primitives
/// Gets the button that displays the previous page of the calendar when
/// it is clicked.
///
- internal Button PreviousButton
+ internal Button? PreviousButton
{
get { return _previousButton; }
private set
@@ -156,11 +156,11 @@ namespace Avalonia.Controls.Primitives
///
/// Gets the Grid that hosts the content when in month mode.
///
- internal Grid MonthView { get; set; }
+ internal Grid? MonthView { get; set; }
///
/// Gets the Grid that hosts the content when in year or decade mode.
///
- internal Grid YearView { get; set; }
+ internal Grid? YearView { get; set; }
private void PopulateGrids()
{
@@ -294,7 +294,7 @@ namespace Avalonia.Controls.Primitives
{
for (int childIndex = 0; childIndex < Calendar.ColumnsPerMonth; childIndex++)
{
- var daytitle = MonthView.Children[childIndex];
+ var daytitle = MonthView!.Children[childIndex];
if (daytitle != null)
{
if (Owner != null)
@@ -495,8 +495,7 @@ namespace Avalonia.Controls.Primitives
for (int childIndex = Calendar.ColumnsPerMonth; childIndex < count; childIndex++)
{
- CalendarDayButton childButton = MonthView.Children[childIndex] as CalendarDayButton;
- Contract.Requires(childButton != null);
+ CalendarDayButton childButton = (CalendarDayButton)MonthView!.Children[childIndex];
childButton.Index = childIndex;
SetButtonState(childButton, dateToAdd);
@@ -532,8 +531,7 @@ namespace Avalonia.Controls.Primitives
childIndex++;
for (int i = childIndex; i < count; i++)
{
- childButton = MonthView.Children[i] as CalendarDayButton;
- Contract.Requires(childButton != null);
+ childButton = (CalendarDayButton)MonthView.Children[i];
// button needs a content to occupy the necessary space
// for the content presenter
childButton.Content = i.ToString(DateTimeHelper.GetCurrentDateFormat());
@@ -626,10 +624,9 @@ namespace Avalonia.Controls.Primitives
private void SetMonthButtonsForYearMode()
{
int count = 0;
- foreach (object child in YearView.Children)
+ foreach (object child in YearView!.Children)
{
- CalendarButton childButton = child as CalendarButton;
- Contract.Requires(childButton != null);
+ CalendarButton childButton = (CalendarButton)child;
// There should be no time component. Time is 12:00 AM
DateTime day = new DateTime(_currentMonth.Year, count + 1, 1);
childButton.DataContext = day;
@@ -703,7 +700,7 @@ namespace Avalonia.Controls.Primitives
{
if (Owner != null && calendarButton != null && calendarButton.DataContext != null)
{
- Owner.FocusCalendarButton.IsCalendarButtonFocused = false;
+ Owner.FocusCalendarButton!.IsCalendarButtonFocused = false;
Owner.FocusCalendarButton = calendarButton;
calendarButton.IsCalendarButtonFocused = Owner.HasFocusInternal;
@@ -722,10 +719,9 @@ namespace Avalonia.Controls.Primitives
{
int year;
int count = -1;
- foreach (object child in YearView.Children)
+ foreach (object child in YearView!.Children)
{
- CalendarButton childButton = child as CalendarButton;
- Contract.Requires(childButton != null);
+ CalendarButton childButton = (CalendarButton)child;
year = decade + count;
if (year <= DateTime.MaxValue.Year && year >= DateTime.MinValue.Year)
@@ -797,7 +793,7 @@ namespace Avalonia.Controls.Primitives
}
}
- internal void HeaderButton_Click(object sender, RoutedEventArgs e)
+ internal void HeaderButton_Click(object? sender, RoutedEventArgs e)
{
if (Owner != null)
{
@@ -805,7 +801,7 @@ namespace Avalonia.Controls.Primitives
{
Owner.Focus();
}
- Button b = (Button)sender;
+ Button b = (Button)sender!;
DateTime d;
if (b.IsEnabled)
@@ -833,7 +829,7 @@ namespace Avalonia.Controls.Primitives
}
}
}
- internal void PreviousButton_Click(object sender, RoutedEventArgs e)
+ internal void PreviousButton_Click(object? sender, RoutedEventArgs e)
{
if (Owner != null)
{
@@ -842,14 +838,14 @@ namespace Avalonia.Controls.Primitives
Owner.Focus();
}
- Button b = (Button)sender;
+ Button b = (Button)sender!;
if (b.IsEnabled)
{
Owner.OnPreviousClick();
}
}
}
- internal void NextButton_Click(object sender, RoutedEventArgs e)
+ internal void NextButton_Click(object? sender, RoutedEventArgs e)
{
if (Owner != null)
{
@@ -857,7 +853,7 @@ namespace Avalonia.Controls.Primitives
{
Owner.Focus();
}
- Button b = (Button)sender;
+ Button b = (Button)sender!;
if (b.IsEnabled)
{
@@ -866,7 +862,7 @@ namespace Avalonia.Controls.Primitives
}
}
- internal void Cell_MouseEnter(object sender, PointerEventArgs e)
+ internal void Cell_MouseEnter(object? sender, PointerEventArgs e)
{
if (Owner != null)
{
@@ -878,7 +874,7 @@ namespace Avalonia.Controls.Primitives
{
case CalendarSelectionMode.SingleDate:
{
- DateTime selectedDate = (DateTime)b.DataContext;
+ DateTime selectedDate = (DateTime)b.DataContext!;
Owner.CalendarDatePickerDisplayDateFlag = true;
if (Owner.SelectedDates.Count == 0)
{
@@ -906,7 +902,7 @@ namespace Avalonia.Controls.Primitives
}
}
- internal void Cell_MouseLeftButtonDown(object sender, PointerPressedEventArgs e)
+ internal void Cell_MouseLeftButtonDown(object? sender, PointerPressedEventArgs e)
{
if (Owner != null)
{
@@ -917,15 +913,14 @@ namespace Avalonia.Controls.Primitives
bool ctrl, shift;
CalendarExtensions.GetMetaKeyState(e.KeyModifiers, out ctrl, out shift);
- CalendarDayButton b = sender as CalendarDayButton;
+ CalendarDayButton b = (CalendarDayButton)sender!;
if (b != null)
{
_isControlPressed = ctrl;
if (b.IsEnabled && !b.IsBlackout)
{
- DateTime selectedDate = (DateTime)b.DataContext;
- Contract.Requires(selectedDate != null);
+ DateTime selectedDate = (DateTime)b.DataContext!;
_isMouseLeftButtonDown = true;
// null check is added for unit tests
if (e != null)
@@ -1027,7 +1022,7 @@ namespace Avalonia.Controls.Primitives
if (Owner != null)
{
Owner.HoverEndIndex = b.Index;
- Owner.HoverEnd = (DateTime)b.DataContext;
+ Owner.HoverEnd = (DateTime)b.DataContext!;
if (Owner.HoverEnd != null && Owner.HoverStart != null)
{
@@ -1041,11 +1036,11 @@ namespace Avalonia.Controls.Primitives
}
}
}
- internal void Cell_MouseLeftButtonUp(object sender, PointerReleasedEventArgs e)
+ internal void Cell_MouseLeftButtonUp(object? sender, PointerReleasedEventArgs e)
{
if (Owner != null)
{
- CalendarDayButton b = sender as CalendarDayButton;
+ CalendarDayButton? b = sender as CalendarDayButton;
if (b != null && !b.IsBlackout)
{
Owner.OnDayButtonMouseUp(e);
@@ -1094,14 +1089,13 @@ namespace Avalonia.Controls.Primitives
}
}
}
- private void Cell_Click(object sender, RoutedEventArgs e)
+ private void Cell_Click(object? sender, RoutedEventArgs e)
{
if (Owner != null)
{
if (_isControlPressed && Owner.SelectionMode == CalendarSelectionMode.MultipleRange)
{
- CalendarDayButton b = sender as CalendarDayButton;
- Contract.Requires(b != null);
+ CalendarDayButton b = (CalendarDayButton)sender!;
if (b.IsSelected)
{
@@ -1118,10 +1112,9 @@ namespace Avalonia.Controls.Primitives
_isControlPressed = false;
}
- private void Month_CalendarButtonMouseDown(object sender, PointerPressedEventArgs e)
+ private void Month_CalendarButtonMouseDown(object? sender, PointerPressedEventArgs e)
{
- CalendarButton b = sender as CalendarButton;
- Contract.Requires(b != null);
+ CalendarButton b = (CalendarButton)sender!;
_isMouseLeftButtonDownYearView = true;
@@ -1133,13 +1126,13 @@ namespace Avalonia.Controls.Primitives
UpdateYearViewSelection(b);
}
- internal void Month_CalendarButtonMouseUp(object sender, PointerReleasedEventArgs e)
+ internal void Month_CalendarButtonMouseUp(object? sender, PointerReleasedEventArgs e)
{
_isMouseLeftButtonDownYearView = false;
if (Owner != null)
{
- DateTime newmonth = (DateTime)((CalendarButton)sender).DataContext;
+ DateTime newmonth = (DateTime)((CalendarButton)sender!).DataContext!;
if (Owner.DisplayMode == CalendarMode.Year)
{
@@ -1155,12 +1148,11 @@ namespace Avalonia.Controls.Primitives
}
}
- private void Month_MouseEnter(object sender, PointerEventArgs e)
+ private void Month_MouseEnter(object? sender, PointerEventArgs e)
{
if (_isMouseLeftButtonDownYearView)
{
- CalendarButton b = sender as CalendarButton;
- Contract.Requires(b != null);
+ CalendarButton b = (CalendarButton)sender!;
UpdateYearViewSelection(b);
}
}
diff --git a/src/Avalonia.Controls/Calendar/DateTimeHelper.cs b/src/Avalonia.Controls/Calendar/DateTimeHelper.cs
index 033bfc5726..eb90f6c399 100644
--- a/src/Avalonia.Controls/Calendar/DateTimeHelper.cs
+++ b/src/Avalonia.Controls/Calendar/DateTimeHelper.cs
@@ -5,6 +5,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
namespace Avalonia.Controls
@@ -73,6 +74,7 @@ namespace Avalonia.Controls
return newD;
}
+ [return: NotNullIfNotNull("d")]
public static DateTime? DiscardTime(DateTime? d)
{
if (d == null)
diff --git a/src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs b/src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs
index 3573c67057..c7c35718e0 100644
--- a/src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs
+++ b/src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs
@@ -49,7 +49,7 @@ namespace Avalonia.Controls.Primitives
private void InvokeCollectionChanged(System.Collections.IList removedItems, System.Collections.IList addedItems)
{
- _owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(null, removedItems, addedItems));
+ _owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(SelectingItemsControl.SelectionChangedEvent, removedItems, addedItems));
}
///
@@ -119,7 +119,7 @@ namespace Avalonia.Controls.Primitives
}
}
- _owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(null, _owner.RemovedItems, _addedItems));
+ _owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(SelectingItemsControl.SelectionChangedEvent, _owner.RemovedItems, _addedItems));
_owner.RemovedItems.Clear();
_owner.UpdateMonths();
_isRangeAdded = false;
diff --git a/src/Avalonia.Controls/Canvas.cs b/src/Avalonia.Controls/Canvas.cs
index 5cc823a6af..fabf8978c7 100644
--- a/src/Avalonia.Controls/Canvas.cs
+++ b/src/Avalonia.Controls/Canvas.cs
@@ -135,7 +135,7 @@ namespace Avalonia.Controls
/// The control from which movement begins.
/// Whether to wrap around when the first or last item is reached.
/// The control.
- IInputElement INavigableContainer.GetControl(NavigationDirection direction, IInputElement from, bool wrap)
+ IInputElement? INavigableContainer.GetControl(NavigationDirection direction, IInputElement? from, bool wrap)
{
// TODO: Implement this
return null;
diff --git a/src/Avalonia.Controls/Chrome/CaptionButtons.cs b/src/Avalonia.Controls/Chrome/CaptionButtons.cs
index be15d3d444..1cad1a4c69 100644
--- a/src/Avalonia.Controls/Chrome/CaptionButtons.cs
+++ b/src/Avalonia.Controls/Chrome/CaptionButtons.cs
@@ -3,8 +3,6 @@ using System.Reactive.Disposables;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
-#nullable enable
-
namespace Avalonia.Controls.Chrome
{
///
diff --git a/src/Avalonia.Controls/Chrome/TitleBar.cs b/src/Avalonia.Controls/Chrome/TitleBar.cs
index fbddb06952..4da50e7220 100644
--- a/src/Avalonia.Controls/Chrome/TitleBar.cs
+++ b/src/Avalonia.Controls/Chrome/TitleBar.cs
@@ -3,8 +3,6 @@ using System.Reactive.Disposables;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
-#nullable enable
-
namespace Avalonia.Controls.Chrome
{
///
@@ -36,7 +34,7 @@ namespace Avalonia.Controls.Chrome
}
}
- IsVisible = window.PlatformImpl.NeedsManagedDecorations;
+ IsVisible = window.PlatformImpl?.NeedsManagedDecorations ?? false;
}
}
diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs
index 274696d501..72b09b7a3c 100644
--- a/src/Avalonia.Controls/ComboBox.cs
+++ b/src/Avalonia.Controls/ComboBox.cs
@@ -10,9 +10,7 @@ using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
-using Avalonia.LogicalTree;
using Avalonia.Media;
-using Avalonia.Threading;
using Avalonia.VisualTree;
namespace Avalonia.Controls
@@ -46,8 +44,8 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly DirectProperty SelectionBoxItemProperty =
- AvaloniaProperty.RegisterDirect(nameof(SelectionBoxItem), o => o.SelectionBoxItem);
+ public static readonly DirectProperty SelectionBoxItemProperty =
+ AvaloniaProperty.RegisterDirect(nameof(SelectionBoxItem), o => o.SelectionBoxItem);
///
/// Defines the property.
@@ -58,14 +56,14 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty PlaceholderTextProperty =
- AvaloniaProperty.Register(nameof(PlaceholderText));
+ public static readonly StyledProperty PlaceholderTextProperty =
+ AvaloniaProperty.Register(nameof(PlaceholderText));
///
/// Defines the property.
///
- public static readonly StyledProperty PlaceholderForegroundProperty =
- AvaloniaProperty.Register(nameof(PlaceholderForeground));
+ public static readonly StyledProperty PlaceholderForegroundProperty =
+ AvaloniaProperty.Register(nameof(PlaceholderForeground));
///
/// Defines the property.
@@ -80,8 +78,8 @@ namespace Avalonia.Controls
ContentControl.VerticalContentAlignmentProperty.AddOwner();
private bool _isDropDownOpen;
- private Popup _popup;
- private object _selectionBoxItem;
+ private Popup? _popup;
+ private object? _selectionBoxItem;
private readonly CompositeDisposable _subscriptionsOnOpen = new CompositeDisposable();
///
@@ -91,7 +89,7 @@ namespace Avalonia.Controls
{
ItemsPanelProperty.OverrideDefaultValue(DefaultPanel);
FocusableProperty.OverrideDefaultValue(true);
- SelectedItemProperty.Changed.AddClassHandler((x,e) => x.SelectedItemChanged(e));
+ SelectedItemProperty.Changed.AddClassHandler((x, e) => x.SelectedItemChanged(e));
KeyDownEvent.AddClassHandler((x, e) => x.OnKeyDown(e), Interactivity.RoutingStrategies.Tunnel);
IsTextSearchEnabledProperty.OverrideDefaultValue(true);
}
@@ -117,7 +115,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the item to display as the control's content.
///
- protected object SelectionBoxItem
+ protected object? SelectionBoxItem
{
get { return _selectionBoxItem; }
set { SetAndRaise(SelectionBoxItemProperty, ref _selectionBoxItem, value); }
@@ -126,7 +124,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the PlaceHolder text.
///
- public string PlaceholderText
+ public string? PlaceholderText
{
get { return GetValue(PlaceholderTextProperty); }
set { SetValue(PlaceholderTextProperty, value); }
@@ -135,7 +133,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the Brush that renders the placeholder text.
///
- public IBrush PlaceholderForeground
+ public IBrush? PlaceholderForeground
{
get { return GetValue(PlaceholderForegroundProperty); }
set { SetValue(PlaceholderForegroundProperty, value); }
@@ -221,8 +219,9 @@ namespace Avalonia.Controls
e.Handled = true;
}
}
+ // This part of code is needed just to acquire initial focus, subsequent focus navigation will be done by ItemsControl.
else if (IsDropDownOpen && SelectedIndex < 0 && ItemCount > 0 &&
- (e.Key == Key.Up || e.Key == Key.Down))
+ (e.Key == Key.Up || e.Key == Key.Down) && IsFocused == true)
{
var firstChild = Presenter?.Panel?.Children.FirstOrDefault(c => CanFocus(c));
if (firstChild != null)
@@ -262,9 +261,9 @@ namespace Avalonia.Controls
///
protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
- if (!e.Handled)
+ if (!e.Handled && e.Source is IVisual source)
{
- if (_popup?.IsInsidePopup((IVisual)e.Source) == true)
+ if (_popup?.IsInsidePopup(source) == true)
{
if (UpdateSelectionFromEventSource(e.Source))
{
@@ -304,7 +303,7 @@ namespace Avalonia.Controls
}
}
- private void PopupClosed(object sender, EventArgs e)
+ private void PopupClosed(object? sender, EventArgs e)
{
_subscriptionsOnOpen.Clear();
@@ -314,7 +313,7 @@ namespace Avalonia.Controls
}
}
- private void PopupOpened(object sender, EventArgs e)
+ private void PopupOpened(object? sender, EventArgs e)
{
TryFocusSelectedItem();
@@ -326,7 +325,7 @@ namespace Avalonia.Controls
toplevel.AddDisposableHandler(PointerWheelChangedEvent, (s, ev) =>
{
//eat wheel scroll event outside dropdown popup while it's open
- if (IsDropDownOpen && (ev.Source as IVisual).GetVisualRoot() == toplevel)
+ if (IsDropDownOpen && (ev.Source as IVisual)?.GetVisualRoot() == toplevel)
{
ev.Handled = true;
}
@@ -377,7 +376,7 @@ namespace Avalonia.Controls
private bool CanFocus(IControl control) => control.Focusable && control.IsEffectivelyEnabled && control.IsVisible;
- private void UpdateSelectionBoxItem(object item)
+ private void UpdateSelectionBoxItem(object? item)
{
var contentControl = item as IContentControl;
@@ -430,7 +429,18 @@ namespace Avalonia.Controls
int next = SelectedIndex + 1;
if (next >= ItemCount)
- next = 0;
+ {
+ if (WrapSelection == true)
+ {
+ next = 0;
+ }
+ else
+ {
+ return;
+ }
+ }
+
+
SelectedIndex = next;
}
@@ -440,7 +450,16 @@ namespace Avalonia.Controls
int prev = SelectedIndex - 1;
if (prev < 0)
- prev = ItemCount - 1;
+ {
+ if (WrapSelection == true)
+ {
+ prev = ItemCount - 1;
+ }
+ else
+ {
+ return;
+ }
+ }
SelectedIndex = prev;
}
diff --git a/src/Avalonia.Controls/ContentControl.cs b/src/Avalonia.Controls/ContentControl.cs
index 1329bd91c7..ac7d24be92 100644
--- a/src/Avalonia.Controls/ContentControl.cs
+++ b/src/Avalonia.Controls/ContentControl.cs
@@ -17,14 +17,14 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty ContentProperty =
- AvaloniaProperty.Register(nameof(Content));
+ public static readonly StyledProperty ContentProperty =
+ AvaloniaProperty.Register(nameof(Content));
///
/// Defines the property.
///
- public static readonly StyledProperty ContentTemplateProperty =
- AvaloniaProperty.Register(nameof(ContentTemplate));
+ public static readonly StyledProperty ContentTemplateProperty =
+ AvaloniaProperty.Register(nameof(ContentTemplate));
///
/// Defines the property.
@@ -48,7 +48,7 @@ namespace Avalonia.Controls
///
[Content]
[DependsOn(nameof(ContentTemplate))]
- public object Content
+ public object? Content
{
get { return GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
@@ -57,7 +57,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the data template used to display the content of the control.
///
- public IDataTemplate ContentTemplate
+ public IDataTemplate? ContentTemplate
{
get { return GetValue(ContentTemplateProperty); }
set { SetValue(ContentTemplateProperty, value); }
@@ -66,7 +66,7 @@ namespace Avalonia.Controls
///
/// Gets the presenter from the control's template.
///
- public IContentPresenter Presenter
+ public IContentPresenter? Presenter
{
get;
private set;
diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs
index d94bff37df..dff06a6369 100644
--- a/src/Avalonia.Controls/ContextMenu.cs
+++ b/src/Avalonia.Controls/ContextMenu.cs
@@ -14,8 +14,6 @@ using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Styling;
-#nullable enable
-
namespace Avalonia.Controls
{
///
@@ -368,7 +366,7 @@ namespace Avalonia.Controls
});
}
- private void PopupOpened(object sender, EventArgs e)
+ private void PopupOpened(object? sender, EventArgs e)
{
_previousFocus = FocusManager.Instance?.Current;
Focus();
@@ -376,12 +374,12 @@ namespace Avalonia.Controls
_popupHostChangedHandler?.Invoke(_popup!.Host);
}
- private void PopupClosing(object sender, CancelEventArgs e)
+ private void PopupClosing(object? sender, CancelEventArgs e)
{
e.Cancel = CancelClosing();
}
- private void PopupClosed(object sender, EventArgs e)
+ private void PopupClosed(object? sender, EventArgs e)
{
foreach (var i in LogicalChildren)
{
@@ -411,7 +409,7 @@ namespace Avalonia.Controls
_popupHostChangedHandler?.Invoke(null);
}
- private void PopupKeyUp(object sender, KeyEventArgs e)
+ private void PopupKeyUp(object? sender, KeyEventArgs e)
{
if (IsOpen)
{
@@ -426,7 +424,7 @@ namespace Avalonia.Controls
}
}
- private static void ControlContextRequested(object sender, ContextRequestedEventArgs e)
+ private static void ControlContextRequested(object? sender, ContextRequestedEventArgs e)
{
if (sender is Control control
&& control.ContextMenu is ContextMenu contextMenu
@@ -439,7 +437,7 @@ namespace Avalonia.Controls
}
}
- private static void ControlDetachedFromVisualTree(object sender, VisualTreeAttachmentEventArgs e)
+ private static void ControlDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
if (sender is Control control
&& control.ContextMenu is ContextMenu contextMenu)
diff --git a/src/Avalonia.Controls/ContextRequestedEventArgs.cs b/src/Avalonia.Controls/ContextRequestedEventArgs.cs
index 8dc798245c..ad5ffef267 100644
--- a/src/Avalonia.Controls/ContextRequestedEventArgs.cs
+++ b/src/Avalonia.Controls/ContextRequestedEventArgs.cs
@@ -1,8 +1,6 @@
using Avalonia.Input;
using Avalonia.Interactivity;
-#nullable enable
-
namespace Avalonia.Controls
{
///
diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs
index 441421181c..b9f3bd8890 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -1,16 +1,16 @@
using System;
using System.ComponentModel;
+using System.Runtime.CompilerServices;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Interactivity;
+using Avalonia.Media;
using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls
{
///
@@ -60,7 +60,13 @@ namespace Avalonia.Controls
public static readonly RoutedEvent ContextRequestedEvent =
RoutedEvent.Register(nameof(ContextRequested),
RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
-
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly AttachedProperty FlowDirectionProperty =
+ AvaloniaProperty.RegisterAttached(nameof(FlowDirection), inherits: true);
+
private DataTemplates? _dataTemplates;
private IControl? _focusAdorner;
@@ -108,11 +114,20 @@ 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.
///
- public event EventHandler ContextRequested
+ public event EventHandler? ContextRequested
{
add => AddHandler(ContextRequestedEvent, value);
remove => RemoveHandler(ContextRequestedEvent, value);
diff --git a/src/Avalonia.Controls/ControlExtensions.cs b/src/Avalonia.Controls/ControlExtensions.cs
index c3cab0a729..1718679294 100644
--- a/src/Avalonia.Controls/ControlExtensions.cs
+++ b/src/Avalonia.Controls/ControlExtensions.cs
@@ -17,7 +17,7 @@ namespace Avalonia.Controls
/// The control.
public static void BringIntoView(this IControl control)
{
- Contract.Requires(control != null);
+ _ = control ?? throw new ArgumentNullException(nameof(control));
control.BringIntoView(new Rect(control.Bounds.Size));
}
@@ -29,7 +29,7 @@ namespace Avalonia.Controls
/// The area of the control to being into view.
public static void BringIntoView(this IControl control, Rect rect)
{
- Contract.Requires(control != null);
+ _ = control ?? throw new ArgumentNullException(nameof(control));
if (control.IsEffectivelyVisible)
{
@@ -51,10 +51,10 @@ namespace Avalonia.Controls
/// The control to look in.
/// The name of the control to find.
/// The control or null if not found.
- public static T FindControl(this IControl control, string name) where T : class, IControl
+ public static T? FindControl(this IControl control, string name) where T : class, IControl
{
- Contract.Requires(control != null);
- Contract.Requires(name != null);
+ _ = control ?? throw new ArgumentNullException(nameof(control));
+ _ = name ?? throw new ArgumentNullException(nameof(name));
var nameScope = control.FindNameScope();
@@ -66,6 +66,29 @@ namespace Avalonia.Controls
return nameScope.Find(name);
}
+ ///
+ /// Finds the named control in the scope of the specified control and throws if not found.
+ ///
+ /// The type of the control to find.
+ /// The control to look in.
+ /// The name of the control to find.
+ /// The control.
+ public static T GetControl(this IControl control, string name) where T : class, IControl
+ {
+ _ = control ?? throw new ArgumentNullException(nameof(control));
+ _ = name ?? throw new ArgumentNullException(nameof(name));
+
+ var nameScope = control.FindNameScope();
+
+ if (nameScope == null)
+ {
+ throw new InvalidOperationException("Could not find parent name scope.");
+ }
+
+ return nameScope.Find(name) ??
+ throw new ArgumentException($"Could not find control named '{name}'.");
+ }
+
///
/// Sets a pseudoclass depending on an observable trigger.
///
@@ -75,7 +98,7 @@ namespace Avalonia.Controls
/// A disposable used to cancel the subscription.
public static IDisposable Set(this IPseudoClasses classes, string name, IObservable trigger)
{
- Contract.Requires(classes != null);
+ _ = classes ?? throw new ArgumentNullException(nameof(classes));
return trigger.Subscribe(x => classes.Set(name, x));
}
diff --git a/src/Avalonia.Controls/Converters/CornerRadiusFilterConverter.cs b/src/Avalonia.Controls/Converters/CornerRadiusFilterConverter.cs
index 7587a9dacb..643c30178e 100644
--- a/src/Avalonia.Controls/Converters/CornerRadiusFilterConverter.cs
+++ b/src/Avalonia.Controls/Converters/CornerRadiusFilterConverter.cs
@@ -1,5 +1,4 @@
-#nullable enable
-using System;
+using System;
using System.Globalization;
using Avalonia.Data.Converters;
diff --git a/src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs b/src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs
index 46affcbe33..b0c30ea11f 100644
--- a/src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs
+++ b/src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs
@@ -16,7 +16,7 @@ namespace Avalonia.Controls.Converters
public bool Bottom { get; set; } = false;
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is int scalarDepth)
{
@@ -38,7 +38,7 @@ namespace Avalonia.Controls.Converters
}
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new System.NotImplementedException();
}
diff --git a/src/Avalonia.Controls/Converters/MenuScrollingVisibilityConverter.cs b/src/Avalonia.Controls/Converters/MenuScrollingVisibilityConverter.cs
index 65f95808ff..6ab2f4c517 100644
--- a/src/Avalonia.Controls/Converters/MenuScrollingVisibilityConverter.cs
+++ b/src/Avalonia.Controls/Converters/MenuScrollingVisibilityConverter.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Controls.Converters
{
public static readonly MenuScrollingVisibilityConverter Instance = new MenuScrollingVisibilityConverter();
- public object Convert(IList values, Type targetType, object parameter, CultureInfo culture)
+ public object? Convert(IList values, Type targetType, object? parameter, CultureInfo culture)
{
if (parameter == null ||
values == null ||
diff --git a/src/Avalonia.Controls/Converters/PlatformKeyGestureConverter.cs b/src/Avalonia.Controls/Converters/PlatformKeyGestureConverter.cs
index 2af8dba479..9a657cce68 100644
--- a/src/Avalonia.Controls/Converters/PlatformKeyGestureConverter.cs
+++ b/src/Avalonia.Controls/Converters/PlatformKeyGestureConverter.cs
@@ -13,7 +13,7 @@ namespace Avalonia.Controls.Converters
///
public class PlatformKeyGestureConverter : IValueConverter
{
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is null)
{
@@ -29,7 +29,7 @@ namespace Avalonia.Controls.Converters
}
}
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
diff --git a/src/Avalonia.Controls/DataValidationErrors.cs b/src/Avalonia.Controls/DataValidationErrors.cs
index 3c64691816..00a06101c5 100644
--- a/src/Avalonia.Controls/DataValidationErrors.cs
+++ b/src/Avalonia.Controls/DataValidationErrors.cs
@@ -21,8 +21,8 @@ namespace Avalonia.Controls
///
/// Defines the DataValidationErrors.Errors attached property.
///
- public static readonly AttachedProperty> ErrorsProperty =
- AvaloniaProperty.RegisterAttached>("Errors");
+ public static readonly AttachedProperty?> ErrorsProperty =
+ AvaloniaProperty.RegisterAttached?>("Errors");
///
/// Defines the DataValidationErrors.HasErrors attached property.
@@ -34,15 +34,15 @@ namespace Avalonia.Controls
AvaloniaProperty.Register(nameof(ErrorTemplate));
- private Control _owner;
+ private Control? _owner;
- public static readonly DirectProperty OwnerProperty =
- AvaloniaProperty.RegisterDirect(
+ public static readonly DirectProperty OwnerProperty =
+ AvaloniaProperty.RegisterDirect(
nameof(Owner),
o => o.Owner,
(o, v) => o.Owner = v);
- public Control Owner
+ public Control? Owner
{
get { return _owner; }
set { SetAndRaise(OwnerProperty, ref _owner, value); }
@@ -75,7 +75,7 @@ namespace Avalonia.Controls
private static void ErrorsChanged(AvaloniaPropertyChangedEventArgs e)
{
var control = (Control)e.Sender;
- var errors = (IEnumerable)e.NewValue;
+ var errors = (IEnumerable?)e.NewValue;
var hasErrors = false;
if (errors != null && errors.Any())
@@ -87,18 +87,18 @@ namespace Avalonia.Controls
{
var control = (Control)e.Sender;
var classes = (IPseudoClasses)control.Classes;
- classes.Set(":error", (bool)e.NewValue);
+ classes.Set(":error", (bool)e.NewValue!);
}
- public static IEnumerable GetErrors(Control control)
+ public static IEnumerable? GetErrors(Control control)
{
return control.GetValue(ErrorsProperty);
}
- public static void SetErrors(Control control, IEnumerable errors)
+ public static void SetErrors(Control control, IEnumerable? errors)
{
control.SetValue(ErrorsProperty, errors);
}
- public static void SetError(Control control, Exception error)
+ public static void SetError(Control control, Exception? error)
{
SetErrors(control, UnpackException(error));
}
@@ -111,7 +111,7 @@ namespace Avalonia.Controls
return control.GetValue(HasErrorsProperty);
}
- private static IEnumerable UnpackException(Exception exception)
+ private static IEnumerable? UnpackException(Exception? exception)
{
if (exception != null)
{
@@ -132,8 +132,9 @@ namespace Avalonia.Controls
private static object GetExceptionData(Exception exception)
{
- if (exception is DataValidationException dataValidationException)
- return dataValidationException.ErrorData;
+ if (exception is DataValidationException dataValidationException &&
+ dataValidationException.ErrorData is object data)
+ return data;
return exception;
}
diff --git a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs
index 5893a02b04..8c6ac17280 100644
--- a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs
+++ b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs
@@ -93,15 +93,15 @@ namespace Avalonia.Controls
defaultBindingMode: BindingMode.TwoWay);
// Template Items
- private Button _flyoutButton;
- private TextBlock _dayText;
- private TextBlock _monthText;
- private TextBlock _yearText;
- private Grid _container;
- private Rectangle _spacer1;
- private Rectangle _spacer2;
- private Popup _popup;
- private DatePickerPresenter _presenter;
+ private Button? _flyoutButton;
+ private TextBlock? _dayText;
+ private TextBlock? _monthText;
+ private TextBlock? _yearText;
+ private Grid? _container;
+ private Rectangle? _spacer1;
+ private Rectangle? _spacer2;
+ private Popup? _popup;
+ private DatePickerPresenter? _presenter;
private bool _areControlsAvailable;
@@ -256,7 +256,7 @@ namespace Avalonia.Controls
///
/// Raised when the changes
///
- public event EventHandler SelectedDateChanged;
+ public event EventHandler? SelectedDateChanged;
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
@@ -307,16 +307,16 @@ namespace Avalonia.Controls
}
}
- private void OnDismissPicker(object sender, EventArgs e)
+ private void OnDismissPicker(object? sender, EventArgs e)
{
- _popup.Close();
+ _popup!.Close();
Focus();
}
- private void OnConfirmed(object sender, EventArgs e)
+ private void OnConfirmed(object? sender, EventArgs e)
{
- _popup.Close();
- SelectedDate = _presenter.Date;
+ _popup!.Close();
+ SelectedDate = _presenter!.Date;
}
private void SetGrid()
@@ -325,7 +325,7 @@ namespace Avalonia.Controls
return;
var fmt = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
- var columns = new List<(TextBlock, int)>
+ var columns = new List<(TextBlock?, int)>
{
(_monthText, MonthVisible ? fmt.IndexOf("m", StringComparison.OrdinalIgnoreCase) : -1),
(_yearText, YearVisible ? fmt.IndexOf("y", StringComparison.OrdinalIgnoreCase) : -1),
@@ -366,11 +366,11 @@ namespace Avalonia.Controls
var isSpacer1Visible = columnIndex > 1;
var isSpacer2Visible = columnIndex > 2;
// ternary conditional operator is used to make sure grid cells will be validated
- Grid.SetColumn(_spacer1, isSpacer1Visible ? 1 : 0);
- Grid.SetColumn(_spacer2, isSpacer2Visible ? 3 : 0);
+ Grid.SetColumn(_spacer1!, isSpacer1Visible ? 1 : 0);
+ Grid.SetColumn(_spacer2!, isSpacer2Visible ? 3 : 0);
- _spacer1.IsVisible = isSpacer1Visible;
- _spacer2.IsVisible = isSpacer2Visible;
+ _spacer1!.IsVisible = isSpacer1Visible;
+ _spacer2!.IsVisible = isSpacer2Visible;
}
private void SetSelectedDateText()
@@ -382,37 +382,37 @@ namespace Avalonia.Controls
{
PseudoClasses.Set(":hasnodate", false);
var selDate = SelectedDate.Value;
- _monthText.Text = selDate.ToString(MonthFormat);
- _yearText.Text = selDate.ToString(YearFormat);
- _dayText.Text = selDate.ToString(DayFormat);
+ _monthText!.Text = selDate.ToString(MonthFormat);
+ _yearText!.Text = selDate.ToString(YearFormat);
+ _dayText!.Text = selDate.ToString(DayFormat);
}
else
{
PseudoClasses.Set(":hasnodate", true);
- _monthText.Text = "month";
- _yearText.Text = "year";
- _dayText.Text = "day";
+ _monthText!.Text = "month";
+ _yearText!.Text = "year";
+ _dayText!.Text = "day";
}
}
- private void OnFlyoutButtonClicked(object sender, RoutedEventArgs e)
+ private void OnFlyoutButtonClicked(object? sender, RoutedEventArgs e)
{
if (_presenter == null)
throw new InvalidOperationException("No DatePickerPresenter found");
_presenter.Date = SelectedDate ?? DateTimeOffset.Now;
- _popup.IsOpen = true;
+ _popup!.IsOpen = true;
var deltaY = _presenter.GetOffsetForPopup();
// The extra 5 px I think is related to default popup placement behavior
- _popup.Host.ConfigurePosition(_popup.PlacementTarget, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
+ _popup!.Host!.ConfigurePosition(_popup.PlacementTarget!, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
Primitives.PopupPositioning.PopupAnchor.Bottom, Primitives.PopupPositioning.PopupGravity.Bottom,
Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY);
}
- protected virtual void OnSelectedDateChanged(object sender, DatePickerSelectedValueChangedEventArgs e)
+ protected virtual void OnSelectedDateChanged(object? sender, DatePickerSelectedValueChangedEventArgs e)
{
SelectedDateChanged?.Invoke(sender, e);
}
diff --git a/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs b/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
index eec4615736..eac6d83074 100644
--- a/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
+++ b/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
@@ -78,23 +78,23 @@ namespace Avalonia.Controls
x.YearVisible, (x, v) => x.YearVisible = v);
// Template Items
- private Grid _pickerContainer;
- private Button _acceptButton;
- private Button _dismissButton;
- private Rectangle _spacer1;
- private Rectangle _spacer2;
- private Panel _monthHost;
- private Panel _yearHost;
- private Panel _dayHost;
- private DateTimePickerPanel _monthSelector;
- private DateTimePickerPanel _yearSelector;
- private DateTimePickerPanel _daySelector;
- private Button _monthUpButton;
- private Button _dayUpButton;
- private Button _yearUpButton;
- private Button _monthDownButton;
- private Button _dayDownButton;
- private Button _yearDownButton;
+ private Grid? _pickerContainer;
+ private Button? _acceptButton;
+ private Button? _dismissButton;
+ private Rectangle? _spacer1;
+ private Rectangle? _spacer2;
+ private Panel? _monthHost;
+ private Panel? _yearHost;
+ private Panel? _dayHost;
+ private DateTimePickerPanel? _monthSelector;
+ private DateTimePickerPanel? _yearSelector;
+ private DateTimePickerPanel? _daySelector;
+ private Button? _monthUpButton;
+ private Button? _dayUpButton;
+ private Button? _yearUpButton;
+ private Button? _monthDownButton;
+ private Button? _dayDownButton;
+ private Button? _yearDownButton;
private DateTimeOffset _date;
private string _dayFormat = "%d";
@@ -308,9 +308,12 @@ namespace Avalonia.Controls
e.Handled = true;
break;
case Key.Tab:
- var nextFocus = KeyboardNavigationHandler.GetNext(FocusManager.Instance.Current, NavigationDirection.Next);
- KeyboardDevice.Instance?.SetFocusedElement(nextFocus, NavigationMethod.Tab, KeyModifiers.None);
- e.Handled = true;
+ if (FocusManager.Instance?.Current is IInputElement focus)
+ {
+ var nextFocus = KeyboardNavigationHandler.GetNext(focus, NavigationDirection.Next);
+ KeyboardDevice.Instance?.SetFocusedElement(nextFocus, NavigationMethod.Tab, KeyModifiers.None);
+ e.Handled = true;
+ }
break;
case Key.Enter:
Date = _syncDate;
@@ -332,13 +335,13 @@ namespace Avalonia.Controls
_suppressUpdateSelection = true;
- _monthSelector.MaximumValue = 12;
+ _monthSelector!.MaximumValue = 12;
_monthSelector.MinimumValue = 1;
_monthSelector.ItemFormat = MonthFormat;
- _daySelector.ItemFormat = DayFormat;
+ _daySelector!.ItemFormat = DayFormat;
- _yearSelector.MaximumValue = MaxYear.Year;
+ _yearSelector!.MaximumValue = MaxYear.Year;
_yearSelector.MinimumValue = MinYear.Year;
_yearSelector.ItemFormat = YearFormat;
@@ -375,7 +378,7 @@ namespace Avalonia.Controls
private void SetGrid()
{
var fmt = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
- var columns = new List<(Panel, int)>
+ var columns = new List<(Panel?, int)>
{
(_monthHost, MonthVisible ? fmt.IndexOf("m", StringComparison.OrdinalIgnoreCase) : -1),
(_yearHost, YearVisible ? fmt.IndexOf("y", StringComparison.OrdinalIgnoreCase) : -1),
@@ -383,7 +386,7 @@ namespace Avalonia.Controls
};
columns.Sort((x, y) => x.Item2 - y.Item2);
- _pickerContainer.ColumnDefinitions.Clear();
+ _pickerContainer!.ColumnDefinitions.Clear();
var columnIndex = 0;
@@ -416,18 +419,18 @@ namespace Avalonia.Controls
var isSpacer1Visible = columnIndex > 1;
var isSpacer2Visible = columnIndex > 2;
// ternary conditional operator is used to make sure grid cells will be validated
- Grid.SetColumn(_spacer1, isSpacer1Visible ? 1 : 0);
- Grid.SetColumn(_spacer2, isSpacer2Visible ? 3 : 0);
+ Grid.SetColumn(_spacer1!, isSpacer1Visible ? 1 : 0);
+ Grid.SetColumn(_spacer2!, isSpacer2Visible ? 3 : 0);
- _spacer1.IsVisible = isSpacer1Visible;
- _spacer2.IsVisible = isSpacer2Visible;
+ _spacer1!.IsVisible = isSpacer1Visible;
+ _spacer2!.IsVisible = isSpacer2Visible;
}
private void SetInitialFocus()
{
- int monthCol = MonthVisible ? Grid.GetColumn(_monthHost) : int.MaxValue;
- int dayCol = DayVisible ? Grid.GetColumn(_dayHost) : int.MaxValue;
- int yearCol = YearVisible ? Grid.GetColumn(_yearHost) : int.MaxValue;
+ int monthCol = MonthVisible ? Grid.GetColumn(_monthHost!) : int.MaxValue;
+ int dayCol = DayVisible ? Grid.GetColumn(_dayHost!) : int.MaxValue;
+ int yearCol = YearVisible ? Grid.GetColumn(_yearHost!) : int.MaxValue;
if (monthCol < dayCol && monthCol < yearCol)
{
@@ -443,39 +446,39 @@ namespace Avalonia.Controls
}
}
- private void OnDismissButtonClicked(object sender, RoutedEventArgs e)
+ private void OnDismissButtonClicked(object? sender, RoutedEventArgs e)
{
OnDismiss();
}
- private void OnAcceptButtonClicked(object sender, RoutedEventArgs e)
+ private void OnAcceptButtonClicked(object? sender, RoutedEventArgs e)
{
Date = _syncDate;
OnConfirmed();
}
- private void OnSelectorButtonClick(object sender, RoutedEventArgs e)
+ private void OnSelectorButtonClick(object? sender, RoutedEventArgs e)
{
if (sender == _monthUpButton)
- _monthSelector.ScrollUp();
+ _monthSelector!.ScrollUp();
else if (sender == _monthDownButton)
- _monthSelector.ScrollDown();
+ _monthSelector!.ScrollDown();
else if (sender == _yearUpButton)
- _yearSelector.ScrollUp();
+ _yearSelector!.ScrollUp();
else if (sender == _yearDownButton)
- _yearSelector.ScrollDown();
+ _yearSelector!.ScrollDown();
else if (sender == _dayUpButton)
- _daySelector.ScrollUp();
+ _daySelector!.ScrollUp();
else if (sender == _dayDownButton)
- _daySelector.ScrollDown();
+ _daySelector!.ScrollDown();
}
- private void OnYearChanged(object sender, EventArgs e)
+ private void OnYearChanged(object? sender, EventArgs e)
{
if (_suppressUpdateSelection)
return;
- int maxDays = _calendar.GetDaysInMonth(_yearSelector.SelectedValue, _syncDate.Month);
+ int maxDays = _calendar.GetDaysInMonth(_yearSelector!.SelectedValue, _syncDate.Month);
var newDate = new DateTimeOffset(_yearSelector.SelectedValue, _syncDate.Month,
_syncDate.Day > maxDays ? maxDays : _syncDate.Day, 0, 0, 0, _syncDate.Offset);
@@ -487,7 +490,7 @@ namespace Avalonia.Controls
_suppressUpdateSelection = true;
- _daySelector.FormatDate = newDate.Date;
+ _daySelector!.FormatDate = newDate.Date;
if (_daySelector.MaximumValue != maxDays)
_daySelector.MaximumValue = maxDays;
@@ -497,19 +500,19 @@ namespace Avalonia.Controls
_suppressUpdateSelection = false;
}
- private void OnDayChanged(object sender, EventArgs e)
+ private void OnDayChanged(object? sender, EventArgs e)
{
if (_suppressUpdateSelection)
return;
- _syncDate = new DateTimeOffset(_syncDate.Year, _syncDate.Month, _daySelector.SelectedValue, 0, 0, 0, _syncDate.Offset);
+ _syncDate = new DateTimeOffset(_syncDate.Year, _syncDate.Month, _daySelector!.SelectedValue, 0, 0, 0, _syncDate.Offset);
}
- private void OnMonthChanged(object sender, EventArgs e)
+ private void OnMonthChanged(object? sender, EventArgs e)
{
if (_suppressUpdateSelection)
return;
- int maxDays = _calendar.GetDaysInMonth(_syncDate.Year, _monthSelector.SelectedValue);
+ int maxDays = _calendar.GetDaysInMonth(_syncDate.Year, _monthSelector!.SelectedValue);
var newDate = new DateTimeOffset(_syncDate.Year, _monthSelector.SelectedValue,
_syncDate.Day > maxDays ? maxDays : _syncDate.Day, 0, 0, 0, _syncDate.Offset);
@@ -521,7 +524,7 @@ namespace Avalonia.Controls
_suppressUpdateSelection = true;
- _daySelector.FormatDate = newDate.Date;
+ _daySelector!.FormatDate = newDate.Date;
_syncDate = newDate;
if (_daySelector.MaximumValue != maxDays)
@@ -535,7 +538,7 @@ namespace Avalonia.Controls
internal double GetOffsetForPopup()
{
var acceptDismissButtonHeight = _acceptButton != null ? _acceptButton.Bounds.Height : 41;
- return -(MaxHeight - acceptDismissButtonHeight) / 2 - (_monthSelector.ItemHeight / 2);
+ return -(MaxHeight - acceptDismissButtonHeight) / 2 - (_monthSelector!.ItemHeight / 2);
}
}
}
diff --git a/src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs b/src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
index e16e609a15..10b7f9bdf9 100644
--- a/src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
+++ b/src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
@@ -58,7 +58,7 @@ namespace Avalonia.Controls.Primitives
private Vector _offset;
private bool _hasInit;
private bool _suppressUpdateOffset;
- private ListBoxItem _pressedItem;
+ private ListBoxItem? _pressedItem;
public DateTimePickerPanel()
{
@@ -271,9 +271,9 @@ namespace Avalonia.Controls.Primitives
public Size Viewport => new Size(0, ItemHeight);
- public event EventHandler ScrollInvalidated;
+ public event EventHandler? ScrollInvalidated;
- public event EventHandler SelectionChanged;
+ public event EventHandler? SelectionChanged;
protected override Size MeasureOverride(Size availableSize)
{
@@ -523,40 +523,44 @@ namespace Avalonia.Controls.Primitives
return newValue;
}
- private void OnItemPointerDown(object sender, PointerPressedEventArgs e)
+ private void OnItemPointerDown(object? sender, PointerPressedEventArgs e)
{
- if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
+ if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed &&
+ e.Source is IVisual source)
{
- _pressedItem = GetItemFromSource((IVisual)e.Source);
+ _pressedItem = GetItemFromSource(source);
e.Handled = true;
}
}
- private void OnItemPointerUp(object sender, PointerReleasedEventArgs e)
+ private void OnItemPointerUp(object? sender, PointerReleasedEventArgs e)
{
if (e.GetCurrentPoint(this).Properties.PointerUpdateKind == PointerUpdateKind.LeftButtonReleased &&
- _pressedItem != null)
+ _pressedItem != null &&
+ e.Source is IVisual source &&
+ GetItemFromSource(source) is ListBoxItem item &&
+ item.Tag is int tag)
{
- SelectedValue = (int)GetItemFromSource((IVisual)e.Source).Tag;
+ SelectedValue = tag;
_pressedItem = null;
e.Handled = true;
}
}
//Helper to get ListBoxItem from pointerevent source
- private ListBoxItem GetItemFromSource(IVisual src)
+ private ListBoxItem? GetItemFromSource(IVisual src)
{
var item = src;
while (item != null && !(item is ListBoxItem))
{
item = item.VisualParent;
}
- return (ListBoxItem)item;
+ return (ListBoxItem?)item;
}
public bool BringIntoView(IControl target, Rect targetRect) { return false; }
- public IControl GetControlInDirection(NavigationDirection direction, IControl from) { return null; }
+ public IControl? GetControlInDirection(NavigationDirection direction, IControl from) { return null; }
public void RaiseScrollInvalidated(EventArgs e)
{
diff --git a/src/Avalonia.Controls/DateTimePickers/PickerPresenterBase.cs b/src/Avalonia.Controls/DateTimePickers/PickerPresenterBase.cs
index 639b187ad8..629b1a1766 100644
--- a/src/Avalonia.Controls/DateTimePickers/PickerPresenterBase.cs
+++ b/src/Avalonia.Controls/DateTimePickers/PickerPresenterBase.cs
@@ -16,10 +16,10 @@ namespace Avalonia.Controls.Primitives
protected virtual void OnDismiss()
{
- Dismissed.Invoke(this, EventArgs.Empty);
+ Dismissed?.Invoke(this, EventArgs.Empty);
}
- public event EventHandler Confirmed;
- public event EventHandler Dismissed;
+ public event EventHandler? Confirmed;
+ public event EventHandler? Dismissed;
}
}
diff --git a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
index 6b3f66912f..a0a27bd4ed 100644
--- a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
+++ b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
@@ -49,18 +49,18 @@ namespace Avalonia.Controls
defaultBindingMode: BindingMode.TwoWay);
// Template Items
- private TimePickerPresenter _presenter;
- private Button _flyoutButton;
- private Border _firstPickerHost;
- private Border _secondPickerHost;
- private Border _thirdPickerHost;
- private TextBlock _hourText;
- private TextBlock _minuteText;
- private TextBlock _periodText;
- private Rectangle _firstSplitter;
- private Rectangle _secondSplitter;
- private Grid _contentGrid;
- private Popup _popup;
+ private TimePickerPresenter? _presenter;
+ private Button? _flyoutButton;
+ private Border? _firstPickerHost;
+ private Border? _secondPickerHost;
+ private Border? _thirdPickerHost;
+ private TextBlock? _hourText;
+ private TextBlock? _minuteText;
+ private TextBlock? _periodText;
+ private Rectangle? _firstSplitter;
+ private Rectangle? _secondSplitter;
+ private Grid? _contentGrid;
+ private Popup? _popup;
private TimeSpan? _selectedTime;
private int _minuteIncrement = 1;
@@ -142,7 +142,7 @@ namespace Avalonia.Controls
///
/// Raised when the property changes
///
- public event EventHandler SelectedTimeChanged;
+ public event EventHandler? SelectedTimeChanged;
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
@@ -200,15 +200,15 @@ namespace Avalonia.Controls
var columnsD = use24HourClock ? "*, Auto, *" : "*, Auto, *, Auto, *";
_contentGrid.ColumnDefinitions = new ColumnDefinitions(columnsD);
- _thirdPickerHost.IsVisible = !use24HourClock;
- _secondSplitter.IsVisible = !use24HourClock;
+ _thirdPickerHost!.IsVisible = !use24HourClock;
+ _secondSplitter!.IsVisible = !use24HourClock;
- Grid.SetColumn(_firstPickerHost, 0);
- Grid.SetColumn(_secondPickerHost, 2);
+ Grid.SetColumn(_firstPickerHost!, 0);
+ Grid.SetColumn(_secondPickerHost!, 2);
Grid.SetColumn(_thirdPickerHost, use24HourClock ? 0 : 4);
- Grid.SetColumn(_firstSplitter, 1);
+ Grid.SetColumn(_firstSplitter!, 1);
Grid.SetColumn(_secondSplitter, use24HourClock ? 0 : 3);
}
@@ -220,7 +220,7 @@ namespace Avalonia.Controls
var time = SelectedTime;
if (time.HasValue)
{
- var newTime = SelectedTime.Value;
+ var newTime = SelectedTime!.Value;
if (ClockIdentifier == "12HourClock")
{
@@ -252,30 +252,30 @@ namespace Avalonia.Controls
SelectedTimeChanged?.Invoke(this, new TimePickerSelectedValueChangedEventArgs(oldTime, newTime));
}
- private void OnFlyoutButtonClicked(object sender, Interactivity.RoutedEventArgs e)
+ private void OnFlyoutButtonClicked(object? sender, Interactivity.RoutedEventArgs e)
{
- _presenter.Time = SelectedTime ?? DateTime.Now.TimeOfDay;
+ _presenter!.Time = SelectedTime ?? DateTime.Now.TimeOfDay;
- _popup.IsOpen = true;
+ _popup!.IsOpen = true;
var deltaY = _presenter.GetOffsetForPopup();
// The extra 5 px I think is related to default popup placement behavior
- _popup.Host.ConfigurePosition(_popup.PlacementTarget, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
+ _popup.Host!.ConfigurePosition(_popup.PlacementTarget!, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
Primitives.PopupPositioning.PopupAnchor.Bottom, Primitives.PopupPositioning.PopupGravity.Bottom,
Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY);
}
- private void OnDismissPicker(object sender, EventArgs e)
+ private void OnDismissPicker(object? sender, EventArgs e)
{
- _popup.Close();
+ _popup!.Close();
Focus();
}
- private void OnConfirmed(object sender, EventArgs e)
+ private void OnConfirmed(object? sender, EventArgs e)
{
- _popup.Close();
- SelectedTime = _presenter.Time;
+ _popup!.Close();
+ SelectedTime = _presenter!.Time;
}
}
}
diff --git a/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs b/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
index 920eeeb406..55bc1af3a7 100644
--- a/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
+++ b/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
@@ -40,20 +40,20 @@ namespace Avalonia.Controls
}
// TemplateItems
- private Grid _pickerContainer;
- private Button _acceptButton;
- private Button _dismissButton;
- private Rectangle _spacer2;
- private Panel _periodHost;
- private DateTimePickerPanel _hourSelector;
- private DateTimePickerPanel _minuteSelector;
- private DateTimePickerPanel _periodSelector;
- private Button _hourUpButton;
- private Button _minuteUpButton;
- private Button _periodUpButton;
- private Button _hourDownButton;
- private Button _minuteDownButton;
- private Button _periodDownButton;
+ private Grid? _pickerContainer;
+ private Button? _acceptButton;
+ private Button? _dismissButton;
+ private Rectangle? _spacer2;
+ private Panel? _periodHost;
+ private DateTimePickerPanel? _hourSelector;
+ private DateTimePickerPanel? _minuteSelector;
+ private DateTimePickerPanel? _periodSelector;
+ private Button? _hourUpButton;
+ private Button? _minuteUpButton;
+ private Button? _periodUpButton;
+ private Button? _hourDownButton;
+ private Button? _minuteDownButton;
+ private Button? _periodDownButton;
// Backing Fields
private TimeSpan _time;
@@ -156,9 +156,12 @@ namespace Avalonia.Controls
e.Handled = true;
break;
case Key.Tab:
- var nextFocus = KeyboardNavigationHandler.GetNext(FocusManager.Instance.Current, NavigationDirection.Next);
- KeyboardDevice.Instance?.SetFocusedElement(nextFocus, NavigationMethod.Tab, KeyModifiers.None);
- e.Handled = true;
+ if (FocusManager.Instance?.Current is IInputElement focus)
+ {
+ var nextFocus = KeyboardNavigationHandler.GetNext(focus, NavigationDirection.Next);
+ KeyboardDevice.Instance?.SetFocusedElement(nextFocus, NavigationMethod.Tab, KeyModifiers.None);
+ e.Handled = true;
+ }
break;
case Key.Enter:
OnConfirmed();
@@ -170,9 +173,9 @@ namespace Avalonia.Controls
protected override void OnConfirmed()
{
- var hr = _hourSelector.SelectedValue;
- var min = _minuteSelector.SelectedValue;
- var per = _periodSelector.SelectedValue;
+ var hr = _hourSelector!.SelectedValue;
+ var min = _minuteSelector!.SelectedValue;
+ var per = _periodSelector!.SelectedValue;
if (ClockIdentifier == "12HourClock")
{
@@ -190,20 +193,20 @@ namespace Avalonia.Controls
return;
bool clock12 = ClockIdentifier == "12HourClock";
- _hourSelector.MaximumValue = clock12 ? 12 : 23;
+ _hourSelector!.MaximumValue = clock12 ? 12 : 23;
_hourSelector.MinimumValue = clock12 ? 1 : 0;
_hourSelector.ItemFormat = "%h";
var hr = Time.Hours;
_hourSelector.SelectedValue = !clock12 ? hr :
hr > 12 ? hr - 12 : hr == 0 ? 12 : hr;
- _minuteSelector.MaximumValue = 59;
+ _minuteSelector!.MaximumValue = 59;
_minuteSelector.MinimumValue = 0;
_minuteSelector.Increment = MinuteIncrement;
_minuteSelector.SelectedValue = Time.Minutes;
_minuteSelector.ItemFormat = "mm";
- _periodSelector.MaximumValue = 1;
+ _periodSelector!.MaximumValue = 1;
_periodSelector.MinimumValue = 0;
_periodSelector.SelectedValue = hr >= 12 ? 1 : 0;
@@ -216,45 +219,45 @@ namespace Avalonia.Controls
bool use24HourClock = ClockIdentifier == "24HourClock";
var columnsD = use24HourClock ? "*, Auto, *" : "*, Auto, *, Auto, *";
- _pickerContainer.ColumnDefinitions = new ColumnDefinitions(columnsD);
+ _pickerContainer!.ColumnDefinitions = new ColumnDefinitions(columnsD);
- _spacer2.IsVisible = !use24HourClock;
- _periodHost.IsVisible = !use24HourClock;
+ _spacer2!.IsVisible = !use24HourClock;
+ _periodHost!.IsVisible = !use24HourClock;
Grid.SetColumn(_spacer2, use24HourClock ? 0 : 3);
Grid.SetColumn(_periodHost, use24HourClock ? 0 : 4);
}
- private void OnDismissButtonClicked(object sender, RoutedEventArgs e)
+ private void OnDismissButtonClicked(object? sender, RoutedEventArgs e)
{
OnDismiss();
}
- private void OnAcceptButtonClicked(object sender, RoutedEventArgs e)
+ private void OnAcceptButtonClicked(object? sender, RoutedEventArgs e)
{
OnConfirmed();
}
- private void OnSelectorButtonClick(object sender, RoutedEventArgs e)
+ private void OnSelectorButtonClick(object? sender, RoutedEventArgs e)
{
if (sender == _hourUpButton)
- _hourSelector.ScrollUp();
+ _hourSelector!.ScrollUp();
else if (sender == _hourDownButton)
- _hourSelector.ScrollDown();
+ _hourSelector!.ScrollDown();
else if (sender == _minuteUpButton)
- _minuteSelector.ScrollUp();
+ _minuteSelector!.ScrollUp();
else if (sender == _minuteDownButton)
- _minuteSelector.ScrollDown();
+ _minuteSelector!.ScrollDown();
else if (sender == _periodUpButton)
- _periodSelector.ScrollUp();
+ _periodSelector!.ScrollUp();
else if (sender == _periodDownButton)
- _periodSelector.ScrollDown();
+ _periodSelector!.ScrollDown();
}
internal double GetOffsetForPopup()
{
var acceptDismissButtonHeight = _acceptButton != null ? _acceptButton.Bounds.Height : 41;
- return -(MaxHeight - acceptDismissButtonHeight) / 2 - (_hourSelector.ItemHeight / 2);
+ return -(MaxHeight - acceptDismissButtonHeight) / 2 - (_hourSelector!.ItemHeight / 2);
}
}
}
diff --git a/src/Avalonia.Controls/Decorator.cs b/src/Avalonia.Controls/Decorator.cs
index 8959f0e306..bd866ee8d8 100644
--- a/src/Avalonia.Controls/Decorator.cs
+++ b/src/Avalonia.Controls/Decorator.cs
@@ -11,8 +11,8 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty ChildProperty =
- AvaloniaProperty.Register(nameof(Child));
+ public static readonly StyledProperty ChildProperty =
+ AvaloniaProperty.Register(nameof(Child));
///
/// Defines the property.
@@ -33,7 +33,7 @@ namespace Avalonia.Controls
/// Gets or sets the decorated control.
///
[Content]
- public IControl Child
+ public IControl? Child
{
get { return GetValue(ChildProperty); }
set { SetValue(ChildProperty, value); }
@@ -66,8 +66,8 @@ namespace Avalonia.Controls
/// The event args.
private void ChildChanged(AvaloniaPropertyChangedEventArgs e)
{
- var oldChild = (Control)e.OldValue;
- var newChild = (Control)e.NewValue;
+ var oldChild = (Control?)e.OldValue;
+ var newChild = (Control?)e.NewValue;
if (oldChild != null)
{
diff --git a/src/Avalonia.Controls/DefinitionBase.cs b/src/Avalonia.Controls/DefinitionBase.cs
index 37b8691ce9..eb09ff397a 100644
--- a/src/Avalonia.Controls/DefinitionBase.cs
+++ b/src/Avalonia.Controls/DefinitionBase.cs
@@ -39,7 +39,7 @@ namespace Avalonia.Controls
string sharedSizeGroupId = SharedSizeGroup;
if (sharedSizeGroupId != null)
{
- SharedSizeScope privateSharedSizeScope = PrivateSharedSizeScope;
+ SharedSizeScope? privateSharedSizeScope = PrivateSharedSizeScope;
if (privateSharedSizeScope != null)
{
_sharedState = privateSharedSizeScope.EnsureSharedState(sharedSizeGroupId);
@@ -104,7 +104,7 @@ namespace Avalonia.Controls
///
internal static void OnIsSharedSizeScopePropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e)
{
- if ((bool)e.NewValue)
+ if ((bool)e.NewValue!)
{
SharedSizeScope sharedStatesCollection = new SharedSizeScope();
d.SetValue(PrivateSharedSizeScopeProperty, sharedStatesCollection);
@@ -131,8 +131,8 @@ namespace Avalonia.Controls
}
else
{
- GridUnitType oldUnitType = ((GridLength)e.OldValue).GridUnitType;
- GridUnitType newUnitType = ((GridLength)e.NewValue).GridUnitType;
+ GridUnitType oldUnitType = ((GridLength)e.OldValue!).GridUnitType;
+ GridUnitType newUnitType = ((GridLength)e.NewValue!).GridUnitType;
if (oldUnitType != newUnitType)
{
@@ -300,7 +300,7 @@ namespace Avalonia.Controls
///
internal abstract double UserMaxSizeValueCache { get; }
- internal Grid Parent { get; set; }
+ internal Grid? Parent { get; set; }
///
/// SetFlags is used to set or unset one or multiple
@@ -326,7 +326,7 @@ namespace Avalonia.Controls
if (definition.Parent != null)
{
- string sharedSizeGroupId = (string)e.NewValue;
+ string sharedSizeGroupId = (string)e.NewValue!;
if (definition._sharedState != null)
{
@@ -338,7 +338,7 @@ namespace Avalonia.Controls
if ((definition._sharedState == null) && (sharedSizeGroupId != null))
{
- SharedSizeScope privateSharedSizeScope = definition.PrivateSharedSizeScope;
+ SharedSizeScope? privateSharedSizeScope = definition.PrivateSharedSizeScope;
if (privateSharedSizeScope != null)
{
// if definition is not registered and both: shared size group id AND private shared scope
@@ -402,7 +402,7 @@ namespace Avalonia.Controls
if (definition.Parent != null)
{
- SharedSizeScope privateSharedSizeScope = (SharedSizeScope)e.NewValue;
+ SharedSizeScope privateSharedSizeScope = (SharedSizeScope)e.NewValue!;
if (definition._sharedState != null)
{
@@ -429,9 +429,9 @@ namespace Avalonia.Controls
///
/// Private getter of shared state collection dynamic property.
///
- private SharedSizeScope PrivateSharedSizeScope
+ private SharedSizeScope? PrivateSharedSizeScope
{
- get { return (SharedSizeScope)GetValue(PrivateSharedSizeScopeProperty); }
+ get { return (SharedSizeScope?)GetValue(PrivateSharedSizeScopeProperty); }
}
///
@@ -462,7 +462,7 @@ namespace Avalonia.Controls
private double _sizeCache; // cache used for various purposes (sorting, caching, etc) during calculations
private double _offset; // offset of the DefinitionBase from left / top corner (assuming LTR case)
- private SharedSizeState _sharedState; // reference to shared state object this instance is registered with
+ private SharedSizeState? _sharedState; // reference to shared state object this instance is registered with
[System.Flags]
private enum Flags : byte
@@ -488,7 +488,7 @@ namespace Avalonia.Controls
// check that sharedSizeGroup is not default
Debug.Assert(sharedSizeGroup != null);
- SharedSizeState sharedState = _registry[sharedSizeGroup] as SharedSizeState;
+ SharedSizeState? sharedState = _registry[sharedSizeGroup] as SharedSizeState;
if (sharedState == null)
{
sharedState = new SharedSizeState(this, sharedSizeGroup);
@@ -567,7 +567,7 @@ namespace Avalonia.Controls
{
for (int i = 0, count = _registry.Count; i < count; ++i)
{
- Grid parentGrid = (Grid)(_registry[i].Parent);
+ Grid parentGrid = (Grid)(_registry[i].Parent!);
parentGrid.Invalidate();
}
_broadcastInvalidation = false;
@@ -645,7 +645,7 @@ namespace Avalonia.Controls
/// OnLayoutUpdated handler. Validates that all participating definitions
/// have updated min size value. Forces another layout update cycle if needed.
///
- private void OnLayoutUpdated(object sender, EventArgs e)
+ private void OnLayoutUpdated(object? sender, EventArgs e)
{
double sharedMinSize = 0;
@@ -707,14 +707,14 @@ namespace Avalonia.Controls
if(!measureIsValid)
{
- definitionBase.Parent.InvalidateMeasure();
+ definitionBase.Parent!.InvalidateMeasure();
}
else if (!MathUtilities.AreClose(sharedMinSize, definitionBase.SizeCache))
{
// if measure is valid then also need to check arrange.
// Note: definitionBase.SizeCache is volatile but at this point
// it contains up-to-date final size
- definitionBase.Parent.InvalidateArrange();
+ definitionBase.Parent!.InvalidateArrange();
}
// now we can restore the invariant, and clear the layout flag
@@ -724,7 +724,7 @@ namespace Avalonia.Controls
_minSize = sharedMinSize;
- _layoutUpdatedHost.LayoutUpdated -= _layoutUpdated;
+ _layoutUpdatedHost!.LayoutUpdated -= _layoutUpdated;
_layoutUpdatedHost = null;
_broadcastInvalidation = true;
@@ -743,7 +743,7 @@ namespace Avalonia.Controls
private readonly EventHandler _layoutUpdated;
// Control for which layout updated event handler is registered
- private Control _layoutUpdatedHost;
+ private Control? _layoutUpdatedHost;
// "true" when broadcasting of invalidation is needed
private bool _broadcastInvalidation;
@@ -762,8 +762,8 @@ namespace Avalonia.Controls
/// Private shared size scope property holds a collection of shared state objects for the a given shared size scope.
///
///
- internal static readonly AttachedProperty PrivateSharedSizeScopeProperty =
- AvaloniaProperty.RegisterAttached(
+ internal static readonly AttachedProperty PrivateSharedSizeScopeProperty =
+ AvaloniaProperty.RegisterAttached(
"PrivateSharedSizeScope",
defaultValue: null,
inherits: true);
diff --git a/src/Avalonia.Controls/DefinitionList.cs b/src/Avalonia.Controls/DefinitionList.cs
index ad0e2513c4..c850647bf4 100644
--- a/src/Avalonia.Controls/DefinitionList.cs
+++ b/src/Avalonia.Controls/DefinitionList.cs
@@ -2,8 +2,6 @@ using System.Collections;
using System.Collections.Specialized;
using Avalonia.Collections;
-#nullable enable
-
namespace Avalonia.Controls
{
public abstract class DefinitionList : AvaloniaList where T : DefinitionBase
@@ -36,7 +34,7 @@ namespace Avalonia.Controls
}
}
- internal void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ internal void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
var idx = 0;
@@ -62,7 +60,7 @@ namespace Avalonia.Controls
for (var i = 0; i < count; i++)
{
- var definition = (DefinitionBase) items[i];
+ var definition = (DefinitionBase) items[i]!;
if (wasRemoved)
{
diff --git a/src/Avalonia.Controls/Diagnostics/IPopupHostProvider.cs b/src/Avalonia.Controls/Diagnostics/IPopupHostProvider.cs
index 11d3b1792a..45cd1d727e 100644
--- a/src/Avalonia.Controls/Diagnostics/IPopupHostProvider.cs
+++ b/src/Avalonia.Controls/Diagnostics/IPopupHostProvider.cs
@@ -1,8 +1,6 @@
using System;
using Avalonia.Controls.Primitives;
-#nullable enable
-
namespace Avalonia.Controls.Diagnostics
{
///
diff --git a/src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs b/src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs
index 4acf2a217f..9fddb91231 100644
--- a/src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs
+++ b/src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs
@@ -1,6 +1,4 @@
-#nullable enable
-
-namespace Avalonia.Controls.Diagnostics
+namespace Avalonia.Controls.Diagnostics
{
///
/// Helper class to provide diagnostics information for .
diff --git a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
index e2afbd3bdc..08d559a5c1 100644
--- a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
+++ b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
@@ -12,7 +12,7 @@ namespace Avalonia.Controls.Embedding.Offscreen
private double _scaling = 1;
private Size _clientSize;
- public IInputRoot InputRoot { get; private set; }
+ public IInputRoot? InputRoot { get; private set; }
public bool IsDisposed { get; private set; }
public virtual void Dispose()
@@ -47,12 +47,12 @@ namespace Avalonia.Controls.Embedding.Offscreen
}
}
- public Action Input { get; set; }
- public Action Paint { get; set; }
- public Action Resized { get; set; }
- public Action ScalingChanged { get; set; }
+ public Action? Input { get; set; }
+ public Action? Paint { get; set; }
+ public Action? Resized { get; set; }
+ public Action? ScalingChanged { get; set; }
- public Action TransparencyLevelChanged { get; set; }
+ public Action? TransparencyLevelChanged { get; set; }
///
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 1, 1);
@@ -63,18 +63,18 @@ namespace Avalonia.Controls.Embedding.Offscreen
public virtual PixelPoint PointToScreen(Point point) => PixelPoint.FromPoint(point, 1);
- public virtual void SetCursor(ICursorImpl cursor)
+ public virtual void SetCursor(ICursorImpl? cursor)
{
}
- public Action Closed { get; set; }
- public Action LostFocus { get; set; }
+ public Action? Closed { get; set; }
+ public Action? LostFocus { get; set; }
public abstract IMouseDevice MouseDevice { get; }
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { }
public WindowTransparencyLevel TransparencyLevel { get; private set; }
- public IPopupImpl CreatePopup() => null;
+ public IPopupImpl? CreatePopup() => null;
}
}
diff --git a/src/Avalonia.Controls/Expander.cs b/src/Avalonia.Controls/Expander.cs
index b9c79e5749..020b162864 100644
--- a/src/Avalonia.Controls/Expander.cs
+++ b/src/Avalonia.Controls/Expander.cs
@@ -1,11 +1,8 @@
using System.Threading;
-
using Avalonia.Animation;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
-#nullable enable
-
namespace Avalonia.Controls
{
///
diff --git a/src/Avalonia.Controls/ExperimentalAcrylicBorder.cs b/src/Avalonia.Controls/ExperimentalAcrylicBorder.cs
index 57861163d6..30bdb4c60e 100644
--- a/src/Avalonia.Controls/ExperimentalAcrylicBorder.cs
+++ b/src/Avalonia.Controls/ExperimentalAcrylicBorder.cs
@@ -17,7 +17,7 @@ namespace Avalonia.Controls
private readonly BorderRenderHelper _borderRenderHelper = new BorderRenderHelper();
- private IDisposable _subscription;
+ private IDisposable? _subscription;
static ExperimentalAcrylicBorder()
{
@@ -46,11 +46,14 @@ namespace Avalonia.Controls
{
base.OnAttachedToVisualTree(e);
- var tl = (e.Root as TopLevel);
+ var tl = (TopLevel)e.Root;
_subscription = tl.GetObservable(TopLevel.ActualTransparencyLevelProperty)
.Subscribe(x =>
{
+ if (tl.PlatformImpl is null)
+ return;
+
switch (x)
{
case WindowTransparencyLevel.Transparent:
diff --git a/src/Avalonia.Controls/Flyouts/Flyout.cs b/src/Avalonia.Controls/Flyouts/Flyout.cs
index 974f1418b2..df3fe28a29 100644
--- a/src/Avalonia.Controls/Flyouts/Flyout.cs
+++ b/src/Avalonia.Controls/Flyouts/Flyout.cs
@@ -1,8 +1,6 @@
using Avalonia.Controls.Primitives;
using Avalonia.Metadata;
-#nullable enable
-
namespace Avalonia.Controls
{
public class Flyout : FlyoutBase
diff --git a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs
index a08b82f512..d024f86b32 100644
--- a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs
+++ b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs
@@ -8,8 +8,6 @@ using Avalonia.Input.Raw;
using Avalonia.Layout;
using Avalonia.Logging;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
public abstract class FlyoutBase : AvaloniaObject, IPopupHostProvider
@@ -267,7 +265,7 @@ namespace Avalonia.Controls.Primitives
return true;
}
- private void PlacementTarget_DetachedFromVisualTree(object sender, VisualTreeAttachmentEventArgs e)
+ private void PlacementTarget_DetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
_ = HideCore(false);
}
@@ -335,7 +333,7 @@ namespace Avalonia.Controls.Primitives
protected virtual void OnOpened()
{
- Opened?.Invoke(this, null);
+ Opened?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnClosing(CancelEventArgs args)
@@ -345,7 +343,7 @@ namespace Avalonia.Controls.Primitives
protected virtual void OnClosed()
{
- Closed?.Invoke(this, null);
+ Closed?.Invoke(this, EventArgs.Empty);
}
///
@@ -368,14 +366,14 @@ namespace Avalonia.Controls.Primitives
return popup;
}
- private void OnPopupOpened(object sender, EventArgs e)
+ private void OnPopupOpened(object? sender, EventArgs e)
{
IsOpen = true;
_popupHostChangedHandler?.Invoke(Popup!.Host);
}
- private void OnPopupClosing(object sender, CancelEventArgs e)
+ private void OnPopupClosing(object? sender, CancelEventArgs e)
{
if (IsOpen)
{
@@ -383,7 +381,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void OnPopupClosed(object sender, EventArgs e)
+ private void OnPopupClosed(object? sender, EventArgs e)
{
HideCore(false);
@@ -391,7 +389,7 @@ namespace Avalonia.Controls.Primitives
}
// This method is handling both popup logical tree and target logical tree.
- private void OnPlacementTargetOrPopupKeyUp(object sender, KeyEventArgs e)
+ private void OnPlacementTargetOrPopupKeyUp(object? sender, KeyEventArgs e)
{
if (!e.Handled
&& IsOpen
@@ -530,10 +528,10 @@ namespace Avalonia.Controls.Primitives
}
}
- private static void OnControlContextRequested(object sender, ContextRequestedEventArgs e)
+ private static void OnControlContextRequested(object? sender, ContextRequestedEventArgs e)
{
- var control = (Control)sender;
if (!e.Handled
+ && sender is Control control
&& control.ContextFlyout is FlyoutBase flyout)
{
if (control.ContextMenu != null)
diff --git a/src/Avalonia.Controls/Flyouts/MenuFlyout.cs b/src/Avalonia.Controls/Flyouts/MenuFlyout.cs
index 5b2e323f4f..97fda68051 100644
--- a/src/Avalonia.Controls/Flyouts/MenuFlyout.cs
+++ b/src/Avalonia.Controls/Flyouts/MenuFlyout.cs
@@ -4,8 +4,6 @@ using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Metadata;
-#nullable enable
-
namespace Avalonia.Controls
{
public class MenuFlyout : FlyoutBase
@@ -18,7 +16,7 @@ namespace Avalonia.Controls
///
/// Defines the property
///
- public static readonly DirectProperty ItemsProperty =
+ public static readonly DirectProperty ItemsProperty =
ItemsControl.ItemsProperty.AddOwner(x => x.Items,
(x, v) => x.Items = v);
@@ -35,7 +33,7 @@ namespace Avalonia.Controls
/// Gets or sets the items of the MenuFlyout
///
[Content]
- public IEnumerable Items
+ public IEnumerable? Items
{
get => _items;
set => SetAndRaise(ItemsProperty, ref _items, value);
@@ -51,7 +49,7 @@ namespace Avalonia.Controls
}
private Classes? _classes;
- private IEnumerable _items;
+ private IEnumerable? _items;
private IDataTemplate? _itemTemplate;
protected override Control CreatePresenter()
diff --git a/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
index 6220a20a82..dd4c6561c2 100644
--- a/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
@@ -17,27 +17,27 @@ namespace Avalonia.Controls.Generators
///
/// Gets or sets the data template used to display the items in the control.
///
- IDataTemplate ItemTemplate { get; set; }
+ IDataTemplate? ItemTemplate { get; set; }
///
/// Gets the ContainerType, or null if its an untyped ContainerGenerator.
///
- Type ContainerType { get; }
+ Type? ContainerType { get; }
///
/// Signaled whenever new containers are materialized.
///
- event EventHandler Materialized;
+ event EventHandler? Materialized;
///
/// Event raised whenever containers are dematerialized.
///
- event EventHandler Dematerialized;
+ event EventHandler? Dematerialized;
///
/// Event raised whenever containers are recycled.
///
- event EventHandler Recycled;
+ event EventHandler? Recycled;
///
/// Creates a container control for an item.
@@ -90,7 +90,7 @@ namespace Avalonia.Controls.Generators
///
/// The index.
/// The container, or null if no container created.
- IControl ContainerFromIndex(int index);
+ IControl? ContainerFromIndex(int index);
///
/// Gets the index of the specified container control.
diff --git a/src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs
index 335e0df5f7..f15987fe79 100644
--- a/src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs
@@ -8,7 +8,7 @@ namespace Avalonia.Controls.Generators
///
/// Gets the container index for the tree.
///
- TreeContainerIndex Index { get; }
+ TreeContainerIndex? Index { get; }
///
/// Updates the index based on the parent .
diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
index f16834f6e1..d02eaffeb2 100644
--- a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
@@ -20,27 +20,25 @@ namespace Avalonia.Controls.Generators
/// The owner control.
public ItemContainerGenerator(IControl owner)
{
- Contract.Requires(owner != null);
-
- Owner = owner;
+ Owner = owner ?? throw new ArgumentNullException(nameof(owner));
}
///
public IEnumerable Containers => _containers.Values;
///
- public event EventHandler Materialized;
+ public event EventHandler? Materialized;
///
- public event EventHandler Dematerialized;
+ public event EventHandler? Dematerialized;
///
- public event EventHandler Recycled;
+ public event EventHandler? Recycled;
///
/// Gets or sets the data template used to display the items in the control.
///
- public IDataTemplate ItemTemplate { get; set; }
+ public IDataTemplate? ItemTemplate { get; set; }
///
/// Gets the owner control.
@@ -48,12 +46,12 @@ namespace Avalonia.Controls.Generators
public IControl Owner { get; }
///
- public virtual Type ContainerType => null;
+ public virtual Type? ContainerType => null;
///
public ItemContainerInfo Materialize(int index, object item)
{
- var container = new ItemContainerInfo(CreateContainer(item), item, index);
+ var container = new ItemContainerInfo(CreateContainer(item)!, item, index);
_containers.Add(container.Index, container);
Materialized?.Invoke(this, new ItemContainerEventArgs(container));
@@ -104,9 +102,7 @@ namespace Avalonia.Controls.Generators
{
for (var i = startingIndex; i < startingIndex + count; ++i)
{
- ItemContainerInfo found;
-
- if (_containers.TryGetValue(i, out found))
+ if (_containers.TryGetValue(i, out var found))
{
result.Add(found);
}
@@ -154,9 +150,9 @@ namespace Avalonia.Controls.Generators
}
///
- public IControl ContainerFromIndex(int index)
+ public IControl? ContainerFromIndex(int index)
{
- ItemContainerInfo result;
+ ItemContainerInfo? result;
_containers.TryGetValue(index, out result);
return result?.ContainerControl;
}
@@ -180,7 +176,7 @@ namespace Avalonia.Controls.Generators
///
/// The item.
/// The created container control.
- protected virtual IControl CreateContainer(object item)
+ protected virtual IControl? CreateContainer(object item)
{
var result = item as IControl;
diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
index d1fbb25cb1..635f3a7d37 100644
--- a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
+++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
@@ -19,13 +19,10 @@ namespace Avalonia.Controls.Generators
public ItemContainerGenerator(
IControl owner,
AvaloniaProperty contentProperty,
- AvaloniaProperty contentTemplateProperty)
+ AvaloniaProperty? contentTemplateProperty)
: base(owner)
{
- Contract.Requires(owner != null);
- Contract.Requires(contentProperty != null);
-
- ContentProperty = contentProperty;
+ ContentProperty = contentProperty ?? throw new ArgumentNullException(nameof(contentProperty));
ContentTemplateProperty = contentTemplateProperty;
}
@@ -40,10 +37,10 @@ namespace Avalonia.Controls.Generators
///
/// Gets the container's ContentTemplate property.
///
- protected AvaloniaProperty ContentTemplateProperty { get; }
+ protected AvaloniaProperty? ContentTemplateProperty { get; }
///
- protected override IControl CreateContainer(object item)
+ protected override IControl? CreateContainer(object item)
{
var container = item as T;
diff --git a/src/Avalonia.Controls/Generators/MenuItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/MenuItemContainerGenerator.cs
index d3cf70e0f8..bfcb474515 100644
--- a/src/Avalonia.Controls/Generators/MenuItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/MenuItemContainerGenerator.cs
@@ -12,7 +12,7 @@
}
///
- protected override IControl CreateContainer(object item)
+ protected override IControl? CreateContainer(object item)
{
var separator = item as Separator;
return separator != null ? separator : base.CreateContainer(item);
diff --git a/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs
index 840a1f66f1..c6b0bda9af 100644
--- a/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs
@@ -20,7 +20,7 @@ namespace Avalonia.Controls.Generators
protected override IControl CreateContainer(object item)
{
- var tabItem = (TabItem)base.CreateContainer(item);
+ var tabItem = (TabItem)base.CreateContainer(item)!;
tabItem.Bind(TabItem.TabStripPlacementProperty, new OwnerBinding(
tabItem,
@@ -28,7 +28,7 @@ namespace Avalonia.Controls.Generators
if (tabItem.HeaderTemplate == null)
{
- tabItem.Bind(TabItem.HeaderTemplateProperty, new OwnerBinding(
+ tabItem.Bind(TabItem.HeaderTemplateProperty, new OwnerBinding(
tabItem,
TabControl.ItemTemplateProperty));
}
@@ -50,7 +50,7 @@ namespace Avalonia.Controls.Generators
if (!(tabItem.Content is IControl))
{
- tabItem.Bind(TabItem.ContentTemplateProperty, new OwnerBinding(
+ tabItem.Bind(TabItem.ContentTemplateProperty, new OwnerBinding(
tabItem,
TabControl.ContentTemplateProperty));
}
@@ -62,8 +62,8 @@ namespace Avalonia.Controls.Generators
{
private readonly TabItem _item;
private readonly StyledProperty _ownerProperty;
- private IDisposable _ownerSubscription;
- private IDisposable _propertySubscription;
+ private IDisposable? _ownerSubscription;
+ private IDisposable? _propertySubscription;
public OwnerBinding(TabItem item, StyledProperty ownerProperty)
{
@@ -82,7 +82,7 @@ namespace Avalonia.Controls.Generators
_ownerSubscription = null;
}
- private void OwnerChanged(ILogical c)
+ private void OwnerChanged(ILogical? c)
{
_propertySubscription?.Dispose();
_propertySubscription = null;
diff --git a/src/Avalonia.Controls/Generators/TreeContainerIndex.cs b/src/Avalonia.Controls/Generators/TreeContainerIndex.cs
index f0da370f73..da13416700 100644
--- a/src/Avalonia.Controls/Generators/TreeContainerIndex.cs
+++ b/src/Avalonia.Controls/Generators/TreeContainerIndex.cs
@@ -21,12 +21,12 @@ namespace Avalonia.Controls.Generators
///
/// Signaled whenever new containers are materialized.
///
- public event EventHandler Materialized;
+ public event EventHandler? Materialized;
///
/// Event raised whenever containers are dematerialized.
///
- public event EventHandler Dematerialized;
+ public event EventHandler? Dematerialized;
///
/// Gets the currently materialized containers.
@@ -92,7 +92,7 @@ namespace Avalonia.Controls.Generators
///
/// The item.
/// The container, or null of not found.
- public IControl ContainerFromItem(object item)
+ public IControl? ContainerFromItem(object item)
{
if (item != null)
{
@@ -108,7 +108,7 @@ namespace Avalonia.Controls.Generators
///
/// The container.
/// The item, or null of not found.
- public object ItemFromContainer(IControl container)
+ public object? ItemFromContainer(IControl? container)
{
if (container != null)
{
diff --git a/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
index 9e65ef5f81..536a5fdd06 100644
--- a/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Controls.Generators
public class TreeItemContainerGenerator : ItemContainerGenerator, ITreeItemContainerGenerator
where T : class, IControl, new()
{
- private TreeView _treeView;
+ private TreeView? _treeView;
///
/// Initializes a new instance of the class.
@@ -32,20 +32,15 @@ namespace Avalonia.Controls.Generators
AvaloniaProperty isExpandedProperty)
: base(owner, contentProperty, contentTemplateProperty)
{
- Contract.Requires(owner != null);
- Contract.Requires(contentProperty != null);
- Contract.Requires(itemsProperty != null);
- Contract.Requires(isExpandedProperty != null);
-
- ItemsProperty = itemsProperty;
- IsExpandedProperty = isExpandedProperty;
+ ItemsProperty = itemsProperty ?? throw new ArgumentNullException(nameof(itemsProperty));
+ IsExpandedProperty = isExpandedProperty ?? throw new ArgumentNullException(nameof(isExpandedProperty));
UpdateIndex();
}
///
/// Gets the container index for the tree.
///
- public TreeContainerIndex Index { get; private set; }
+ public TreeContainerIndex? Index { get; private set; }
///
/// Gets the item container's Items property.
@@ -58,7 +53,7 @@ namespace Avalonia.Controls.Generators
protected AvaloniaProperty IsExpandedProperty { get; }
///
- protected override IControl CreateContainer(object item)
+ protected override IControl? CreateContainer(object? item)
{
var container = item as T;
@@ -141,12 +136,12 @@ namespace Avalonia.Controls.Generators
{
private readonly IDataTemplate _inner;
public WrapperTreeDataTemplate(IDataTemplate inner) => _inner = inner;
- public IControl Build(object param) => _inner.Build(param);
- public bool Match(object data) => _inner.Match(data);
- public InstancedBinding ItemsSelector(object item) => null;
+ public IControl? Build(object? param) => _inner.Build(param);
+ public bool Match(object? data) => _inner.Match(data);
+ public InstancedBinding? ItemsSelector(object item) => null;
}
- private ITreeDataTemplate GetTreeDataTemplate(object item, IDataTemplate primary)
+ private ITreeDataTemplate GetTreeDataTemplate(object item, IDataTemplate? primary)
{
var template = Owner.FindDataTemplate(item, primary) ?? FuncDataTemplate.Default;
var treeTemplate = template as ITreeDataTemplate ?? new WrapperTreeDataTemplate(template);
diff --git a/src/Avalonia.Controls/Grid.cs b/src/Avalonia.Controls/Grid.cs
index 74401c450a..8d246d35f4 100644
--- a/src/Avalonia.Controls/Grid.cs
+++ b/src/Avalonia.Controls/Grid.cs
@@ -8,6 +8,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Avalonia.Layout;
using Avalonia.Media;
@@ -48,7 +49,7 @@ namespace Avalonia.Controls
/// Column property value.
public static void SetColumn(Control element, int value)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(ColumnProperty, value);
}
@@ -59,7 +60,7 @@ namespace Avalonia.Controls
/// Column property value.
public static int GetColumn(Control element)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(ColumnProperty);
}
@@ -70,7 +71,7 @@ namespace Avalonia.Controls
/// Row property value.
public static void SetRow(Control element, int value)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(RowProperty, value);
}
@@ -81,7 +82,7 @@ namespace Avalonia.Controls
/// Row property value.
public static int GetRow(Control element)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(RowProperty);
}
@@ -92,7 +93,7 @@ namespace Avalonia.Controls
/// ColumnSpan property value.
public static void SetColumnSpan(Control element, int value)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(ColumnSpanProperty, value);
}
@@ -103,7 +104,7 @@ namespace Avalonia.Controls
/// ColumnSpan property value.
public static int GetColumnSpan(Control element)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(ColumnSpanProperty);
}
@@ -114,7 +115,7 @@ namespace Avalonia.Controls
/// RowSpan property value.
public static void SetRowSpan(Control element, int value)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(RowSpanProperty, value);
}
@@ -125,7 +126,7 @@ namespace Avalonia.Controls
/// RowSpan property value.
public static int GetRowSpan(Control element)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(RowSpanProperty);
}
@@ -136,7 +137,7 @@ namespace Avalonia.Controls
/// IsSharedSizeScope property value.
public static void SetIsSharedSizeScope(Control element, bool value)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(IsSharedSizeScopeProperty, value);
}
@@ -147,7 +148,7 @@ namespace Avalonia.Controls
/// IsSharedSizeScope property value.
public static bool GetIsSharedSizeScope(Control element)
{
- Contract.Requires(element != null);
+ _ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(IsSharedSizeScopeProperty);
}
@@ -573,7 +574,7 @@ namespace Avalonia.Controls
///
///
///
- protected override void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
+ protected override void ChildrenChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
CellsStructureDirty = true;
base.ChildrenChanged(sender, e);
@@ -598,7 +599,7 @@ namespace Avalonia.Controls
{
double value = 0.0;
- Contract.Requires(_data != null);
+ Debug.Assert(_data != null);
// actual value calculations require structure to be up-to-date
if (!ColumnDefinitionsDirty)
@@ -620,7 +621,7 @@ namespace Avalonia.Controls
{
double value = 0.0;
- Contract.Requires(_data != null);
+ Debug.Assert(_data != null);
// actual value calculations require structure to be up-to-date
if (!RowDefinitionsDirty)
@@ -994,7 +995,7 @@ namespace Avalonia.Controls
}
var children = this.Children;
- Hashtable spanStore = null;
+ Hashtable? spanStore = null;
bool ignoreDesiredSizeV = forceInfinityV;
int i = cellsHead;
@@ -1048,7 +1049,7 @@ namespace Avalonia.Controls
foreach (DictionaryEntry e in spanStore)
{
SpanKey key = (SpanKey)e.Key;
- double requestedSize = (double)e.Value;
+ double requestedSize = (double)e.Value!;
EnsureMinSizeInDefinitionRange(
key.U ? DefinitionsU : DefinitionsV,
@@ -1069,7 +1070,7 @@ namespace Avalonia.Controls
/// true if this is a column span. false if this is a row span.
/// Value to store. If an entry already exists the biggest value is stored.
private static void RegisterSpan(
- ref Hashtable store,
+ ref Hashtable? store,
int start,
int count,
bool u,
@@ -1081,7 +1082,7 @@ namespace Avalonia.Controls
}
SpanKey key = new SpanKey(start, count, u);
- object o = store[key];
+ object? o = store[key];
if (o == null
|| value > (double)o)
@@ -1605,12 +1606,12 @@ namespace Avalonia.Controls
while (minCount > 0 && tempDefinitions[minCount - 1].MeasureSize < 0.0)
{
--minCount;
- tempDefinitions[minCount] = null;
+ tempDefinitions[minCount] = null!;
}
while (maxCount > 0 && tempDefinitions[defCount + maxCount - 1].MeasureSize < 0.0)
{
--maxCount;
- tempDefinitions[defCount + maxCount] = null;
+ tempDefinitions[defCount + maxCount] = null!;
}
}
@@ -2321,7 +2322,7 @@ namespace Avalonia.Controls
/// by adding / removing GridLinesRenderer visual.
/// Returns a reference to GridLinesRenderer visual or null.
///
- private GridLinesRenderer EnsureGridLinesRenderer()
+ private GridLinesRenderer? EnsureGridLinesRenderer()
{
//
// synchronize the state
@@ -2369,16 +2370,16 @@ namespace Avalonia.Controls
grid.InvalidateVisual();
}
- grid.SetFlags((bool)e.NewValue, Flags.ShowGridLinesPropertyValue);
+ grid.SetFlags((bool)e.NewValue!, Flags.ShowGridLinesPropertyValue);
}
private static void OnCellAttachedPropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e)
{
- Visual child = d as Visual;
+ Visual? child = d as Visual;
if (child != null)
{
- Grid grid = child.GetVisualParent();
+ Grid? grid = child.GetVisualParent();
if (grid != null
&& grid.ExtData != null
&& grid.ListenToNotifications)
@@ -2395,7 +2396,7 @@ namespace Avalonia.Controls
/// true if one or both of x and y are null, in which case result holds
/// the relative sort order.
///
- private static bool CompareNullRefs(object x, object y, out int result)
+ private static bool CompareNullRefs([NotNullWhen(false)] object? x, [NotNullWhen(false)] object? y, out int result)
{
result = 2;
@@ -2426,7 +2427,7 @@ namespace Avalonia.Controls
///
private IReadOnlyList DefinitionsU
{
- get { return (ExtData.DefinitionsU); }
+ get { return (ExtData.DefinitionsU!); }
}
///
@@ -2434,7 +2435,7 @@ namespace Avalonia.Controls
///
private IReadOnlyList DefinitionsV
{
- get { return (ExtData.DefinitionsV); }
+ get { return (ExtData.DefinitionsV!); }
}
///
@@ -2450,7 +2451,7 @@ namespace Avalonia.Controls
if (extData.TempDefinitions == null
|| extData.TempDefinitions.Length < requiredLength)
{
- WeakReference tempDefinitionsWeakRef = (WeakReference)Thread.GetData(s_tempDefinitionsDataSlot);
+ WeakReference? tempDefinitionsWeakRef = (WeakReference?)Thread.GetData(s_tempDefinitionsDataSlot);
if (tempDefinitionsWeakRef == null)
{
extData.TempDefinitions = new DefinitionBase[requiredLength];
@@ -2458,7 +2459,7 @@ namespace Avalonia.Controls
}
else
{
- extData.TempDefinitions = (DefinitionBase[])tempDefinitionsWeakRef.Target;
+ extData.TempDefinitions = (DefinitionBase[]?)tempDefinitionsWeakRef.Target;
if (extData.TempDefinitions == null
|| extData.TempDefinitions.Length < requiredLength)
{
@@ -2515,7 +2516,7 @@ namespace Avalonia.Controls
///
private CellCache[] PrivateCells
{
- get { return (ExtData.CellCachesCollection); }
+ get { return (ExtData.CellCachesCollection!); }
}
///
@@ -2586,7 +2587,7 @@ namespace Avalonia.Controls
///
private ExtendedData ExtData
{
- get { return (_data); }
+ get { return (_data!); }
}
///
@@ -2608,17 +2609,17 @@ namespace Avalonia.Controls
}
// Extended data instantiated on demand, for non-trivial case handling only
- private ExtendedData _data;
+ private ExtendedData? _data;
// Grid validity / property caches dirtiness flags
private Flags _flags;
- private GridLinesRenderer _gridLinesRenderer;
+ private GridLinesRenderer? _gridLinesRenderer;
// Keeps track of definition indices.
- int[] _definitionIndices;
+ int[]? _definitionIndices;
// Stores unrounded values and rounding errors during layout rounding.
- double[] _roundingErrors;
+ double[]? _roundingErrors;
// 5 is an arbitrary constant chosen to end the measure loop
private const int c_layoutLoopMaxCount = 5;
@@ -2635,16 +2636,16 @@ namespace Avalonia.Controls
///
private class ExtendedData
{
- internal ColumnDefinitions ColumnDefinitions; // collection of column definitions (logical tree support)
- internal RowDefinitions RowDefinitions; // collection of row definitions (logical tree support)
- internal IReadOnlyList DefinitionsU; // collection of column definitions used during calc
- internal IReadOnlyList DefinitionsV; // collection of row definitions used during calc
- internal CellCache[] CellCachesCollection; // backing store for logical children
+ internal ColumnDefinitions? ColumnDefinitions; // collection of column definitions (logical tree support)
+ internal RowDefinitions? RowDefinitions; // collection of row definitions (logical tree support)
+ internal IReadOnlyList? DefinitionsU; // collection of column definitions used during calc
+ internal IReadOnlyList? DefinitionsV; // collection of row definitions used during calc
+ internal CellCache[]? CellCachesCollection; // backing store for logical children
internal int CellGroup1; // index of the first cell in first cell group
internal int CellGroup2; // index of the first cell in second cell group
internal int CellGroup3; // index of the first cell in third cell group
internal int CellGroup4; // index of the first cell in forth cell group
- internal DefinitionBase[] TempDefinitions; // temporary array used during layout for various purposes
+ internal DefinitionBase[]? TempDefinitions; // temporary array used during layout for various purposes
// TempDefinitions.Length == Max(definitionsU.Length, definitionsV.Length)
}
@@ -2831,9 +2832,9 @@ namespace Avalonia.Controls
///
///
///
- public override bool Equals(object obj)
+ public override bool Equals(object? obj)
{
- SpanKey sk = obj as SpanKey;
+ SpanKey? sk = obj as SpanKey;
return (sk != null
&& sk._start == _start
&& sk._count == _count
@@ -2866,10 +2867,10 @@ namespace Avalonia.Controls
///
private class SpanPreferredDistributionOrderComparer : IComparer
{
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
- DefinitionBase definitionX = x as DefinitionBase;
- DefinitionBase definitionY = y as DefinitionBase;
+ DefinitionBase? definitionX = x as DefinitionBase;
+ DefinitionBase? definitionY = y as DefinitionBase;
int result;
@@ -2908,10 +2909,10 @@ namespace Avalonia.Controls
///
private class SpanMaxDistributionOrderComparer : IComparer
{
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
- DefinitionBase definitionX = x as DefinitionBase;
- DefinitionBase definitionY = y as DefinitionBase;
+ DefinitionBase? definitionX = x as DefinitionBase;
+ DefinitionBase? definitionY = y as DefinitionBase;
int result;
@@ -2954,17 +2955,16 @@ namespace Avalonia.Controls
internal StarDistributionOrderIndexComparer(IReadOnlyList definitions)
{
- Contract.Requires(definitions != null);
- this.definitions = definitions;
+ this.definitions = definitions ?? throw new ArgumentNullException(nameof(definitions));
}
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
int? indexX = x as int?;
int? indexY = y as int?;
- DefinitionBase definitionX = null;
- DefinitionBase definitionY = null;
+ DefinitionBase? definitionX = null;
+ DefinitionBase? definitionY = null;
if (indexX != null)
{
@@ -2995,17 +2995,16 @@ namespace Avalonia.Controls
internal DistributionOrderIndexComparer(IReadOnlyList definitions)
{
- Contract.Requires(definitions != null);
- this.definitions = definitions;
+ this.definitions = definitions ?? throw new ArgumentNullException(nameof(definitions));
}
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
int? indexX = x as int?;
int? indexY = y as int?;
- DefinitionBase definitionX = null;
- DefinitionBase definitionY = null;
+ DefinitionBase? definitionX = null;
+ DefinitionBase? definitionY = null;
if (indexX != null)
{
@@ -3038,11 +3037,10 @@ namespace Avalonia.Controls
internal RoundingErrorIndexComparer(double[] errors)
{
- Contract.Requires(errors != null);
- this.errors = errors;
+ this.errors = errors ?? throw new ArgumentNullException(nameof(errors));
}
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
int? indexX = x as int?;
int? indexY = y as int?;
@@ -3067,10 +3065,10 @@ namespace Avalonia.Controls
///
private class MinRatioComparer : IComparer
{
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
- DefinitionBase definitionX = x as DefinitionBase;
- DefinitionBase definitionY = y as DefinitionBase;
+ DefinitionBase? definitionX = x as DefinitionBase;
+ DefinitionBase? definitionY = y as DefinitionBase;
int result;
@@ -3090,10 +3088,10 @@ namespace Avalonia.Controls
///
private class MaxRatioComparer : IComparer
{
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
- DefinitionBase definitionX = x as DefinitionBase;
- DefinitionBase definitionY = y as DefinitionBase;
+ DefinitionBase? definitionX = x as DefinitionBase;
+ DefinitionBase? definitionY = y as DefinitionBase;
int result;
@@ -3112,10 +3110,10 @@ namespace Avalonia.Controls
///
private class StarWeightComparer : IComparer
{
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
- DefinitionBase definitionX = x as DefinitionBase;
- DefinitionBase definitionY = y as DefinitionBase;
+ DefinitionBase? definitionX = x as DefinitionBase;
+ DefinitionBase? definitionY = y as DefinitionBase;
int result;
@@ -3137,17 +3135,16 @@ namespace Avalonia.Controls
internal MinRatioIndexComparer(IReadOnlyList definitions)
{
- Contract.Requires(definitions != null);
- this.definitions = definitions;
+ this.definitions = definitions ?? throw new ArgumentNullException(nameof(definitions));
}
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
int? indexX = x as int?;
int? indexY = y as int?;
- DefinitionBase definitionX = null;
- DefinitionBase definitionY = null;
+ DefinitionBase? definitionX = null;
+ DefinitionBase? definitionY = null;
if (indexX != null)
{
@@ -3178,17 +3175,16 @@ namespace Avalonia.Controls
internal MaxRatioIndexComparer(IReadOnlyList definitions)
{
- Contract.Requires(definitions != null);
- this.definitions = definitions;
+ this.definitions = definitions ?? throw new ArgumentNullException(nameof(definitions));
}
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
int? indexX = x as int?;
int? indexY = y as int?;
- DefinitionBase definitionX = null;
- DefinitionBase definitionY = null;
+ DefinitionBase? definitionX = null;
+ DefinitionBase? definitionY = null;
if (indexX != null)
{
@@ -3219,17 +3215,16 @@ namespace Avalonia.Controls
internal StarWeightIndexComparer(IReadOnlyList definitions)
{
- Contract.Requires(definitions != null);
- this.definitions = definitions;
+ this.definitions = definitions ?? throw new ArgumentNullException(nameof(definitions));
}
- public int Compare(object x, object y)
+ public int Compare(object? x, object? y)
{
int? indexX = x as int?;
int? indexY = y as int?;
- DefinitionBase definitionX = null;
- DefinitionBase definitionY = null;
+ DefinitionBase? definitionX = null;
+ DefinitionBase? definitionY = null;
if (indexX != null)
{
diff --git a/src/Avalonia.Controls/GridLength.cs b/src/Avalonia.Controls/GridLength.cs
index ee6a146d61..d7022b80ce 100644
--- a/src/Avalonia.Controls/GridLength.cs
+++ b/src/Avalonia.Controls/GridLength.cs
@@ -135,7 +135,7 @@ namespace Avalonia.Controls
///
/// The object with which to test equality.
/// True if the objects are equal, otherwise false.
- public override bool Equals(object o)
+ public override bool Equals(object? o)
{
if (o == null)
{
diff --git a/src/Avalonia.Controls/GridSplitter.cs b/src/Avalonia.Controls/GridSplitter.cs
index 26c8464576..216e43e1f0 100644
--- a/src/Avalonia.Controls/GridSplitter.cs
+++ b/src/Avalonia.Controls/GridSplitter.cs
@@ -59,7 +59,7 @@ namespace Avalonia.Controls
private static readonly Cursor s_columnSplitterCursor = new Cursor(StandardCursorType.SizeWestEast);
private static readonly Cursor s_rowSplitterCursor = new Cursor(StandardCursorType.SizeNorthSouth);
- private ResizeData _resizeData;
+ private ResizeData? _resizeData;
///
/// Indicates whether the Splitter resizes the Columns, Rows, or Both.
@@ -197,9 +197,9 @@ namespace Avalonia.Controls
///
private void RemovePreviewAdorner()
{
- if (_resizeData.Adorner != null)
+ if (_resizeData?.Adorner != null)
{
- AdornerLayer layer = AdornerLayer.GetAdornerLayer(this);
+ AdornerLayer layer = AdornerLayer.GetAdornerLayer(this)!;
layer.Children.Remove(_resizeData.Adorner);
}
}
@@ -242,7 +242,7 @@ namespace Avalonia.Controls
///
private bool SetupDefinitionsToResize()
{
- int gridSpan = GetValue(_resizeData.ResizeDirection == GridResizeDirection.Columns ?
+ int gridSpan = GetValue(_resizeData!.ResizeDirection == GridResizeDirection.Columns ?
Grid.ColumnSpanProperty :
Grid.RowSpanProperty);
@@ -276,8 +276,8 @@ namespace Avalonia.Controls
// Get count of rows/columns in the resize direction.
int count = _resizeData.ResizeDirection == GridResizeDirection.Columns ?
- _resizeData.Grid.ColumnDefinitions.Count :
- _resizeData.Grid.RowDefinitions.Count;
+ _resizeData.Grid!.ColumnDefinitions.Count :
+ _resizeData.Grid!.RowDefinitions.Count;
if (index1 >= 0 && index2 < count)
{
@@ -322,10 +322,10 @@ namespace Avalonia.Controls
///
private void SetupPreviewAdorner()
{
- if (_resizeData.ShowsPreview)
+ if (_resizeData!.ShowsPreview)
{
// Get the adorner layer and add an adorner to it.
- var adornerLayer = AdornerLayer.GetAdornerLayer(_resizeData.Grid);
+ var adornerLayer = AdornerLayer.GetAdornerLayer(_resizeData.Grid!);
var previewContent = PreviewContent;
@@ -335,7 +335,7 @@ namespace Avalonia.Controls
return;
}
- IControl builtPreviewContent = previewContent?.Build();
+ IControl? builtPreviewContent = previewContent?.Build();
_resizeData.Adorner = new PreviewAdorner(builtPreviewContent);
@@ -409,13 +409,13 @@ namespace Avalonia.Controls
// Set the Translation of the Adorner to the distance from the thumb.
if (_resizeData.ResizeDirection == GridResizeDirection.Columns)
{
- _resizeData.Adorner.OffsetX = Math.Min(
+ _resizeData.Adorner!.OffsetX = Math.Min(
Math.Max(horizontalChange, _resizeData.MinChange),
_resizeData.MaxChange);
}
else
{
- _resizeData.Adorner.OffsetY = Math.Min(
+ _resizeData.Adorner!.OffsetY = Math.Min(
Math.Max(verticalChange, _resizeData.MinChange),
_resizeData.MaxChange);
}
@@ -437,7 +437,7 @@ namespace Avalonia.Controls
if (_resizeData.ShowsPreview)
{
// Update the grid.
- MoveSplitter(_resizeData.Adorner.OffsetX, _resizeData.Adorner.OffsetY);
+ MoveSplitter(_resizeData.Adorner!.OffsetX, _resizeData.Adorner.OffsetY);
RemovePreviewAdorner();
}
@@ -481,14 +481,14 @@ namespace Avalonia.Controls
private void CancelResize()
{
// Restore original column/row lengths.
- if (_resizeData.ShowsPreview)
+ if (_resizeData!.ShowsPreview)
{
RemovePreviewAdorner();
}
else // Reset the columns/rows lengths to the saved values.
{
- SetDefinitionLength(_resizeData.Definition1, _resizeData.OriginalDefinition1Length);
- SetDefinitionLength(_resizeData.Definition2, _resizeData.OriginalDefinition2Length);
+ SetDefinitionLength(_resizeData.Definition1!, _resizeData.OriginalDefinition1Length);
+ SetDefinitionLength(_resizeData.Definition2!, _resizeData.OriginalDefinition2Length);
}
_resizeData = null;
@@ -536,12 +536,12 @@ namespace Avalonia.Controls
///
private void GetDeltaConstraints(out double minDelta, out double maxDelta)
{
- double definition1Len = GetActualLength(_resizeData.Definition1);
- double definition1Min = _resizeData.Definition1.UserMinSizeValueCache;
+ double definition1Len = GetActualLength(_resizeData!.Definition1!);
+ double definition1Min = _resizeData.Definition1!.UserMinSizeValueCache;
double definition1Max = _resizeData.Definition1.UserMaxSizeValueCache;
- double definition2Len = GetActualLength(_resizeData.Definition2);
- double definition2Min = _resizeData.Definition2.UserMinSizeValueCache;
+ double definition2Len = GetActualLength(_resizeData.Definition2!);
+ double definition2Min = _resizeData.Definition2!.UserMinSizeValueCache;
double definition2Max = _resizeData.Definition2.UserMaxSizeValueCache;
// Set MinWidths to be greater than width of splitter.
@@ -565,11 +565,11 @@ namespace Avalonia.Controls
private void SetLengths(double definition1Pixels, double definition2Pixels)
{
// For the case where both definition1 and 2 are stars, update all star values to match their current pixel values.
- if (_resizeData.SplitBehavior == SplitBehavior.Split)
+ if (_resizeData!.SplitBehavior == SplitBehavior.Split)
{
var definitions = _resizeData.ResizeDirection == GridResizeDirection.Columns ?
- (IAvaloniaReadOnlyList)_resizeData.Grid.ColumnDefinitions :
- (IAvaloniaReadOnlyList)_resizeData.Grid.RowDefinitions;
+ (IAvaloniaReadOnlyList)_resizeData.Grid!.ColumnDefinitions :
+ (IAvaloniaReadOnlyList)_resizeData.Grid!.RowDefinitions;
var definitionsCount = definitions.Count;
@@ -595,11 +595,11 @@ namespace Avalonia.Controls
}
else if (_resizeData.SplitBehavior == SplitBehavior.Resize1)
{
- SetDefinitionLength(_resizeData.Definition1, new GridLength(definition1Pixels));
+ SetDefinitionLength(_resizeData.Definition1!, new GridLength(definition1Pixels));
}
else
{
- SetDefinitionLength(_resizeData.Definition2, new GridLength(definition2Pixels));
+ SetDefinitionLength(_resizeData.Definition2!, new GridLength(definition2Pixels));
}
}
@@ -623,8 +623,8 @@ namespace Avalonia.Controls
delta = LayoutHelper.RoundLayoutValue(delta, LayoutHelper.GetLayoutScale(this));
}
- DefinitionBase definition1 = _resizeData.Definition1;
- DefinitionBase definition2 = _resizeData.Definition2;
+ DefinitionBase? definition1 = _resizeData.Definition1;
+ DefinitionBase? definition2 = _resizeData.Definition2;
if (definition1 != null && definition2 != null)
{
@@ -691,7 +691,7 @@ namespace Avalonia.Controls
private readonly TranslateTransform _translation;
private readonly Decorator _decorator;
- public PreviewAdorner(IControl previewControl)
+ public PreviewAdorner(IControl? previewControl)
{
// Add a decorator to perform translations.
_translation = new TranslateTransform();
@@ -762,22 +762,22 @@ namespace Avalonia.Controls
private class ResizeData
{
public bool ShowsPreview;
- public PreviewAdorner Adorner;
+ public PreviewAdorner? Adorner;
// The constraints to keep the Preview within valid ranges.
public double MinChange;
public double MaxChange;
// The grid to Resize.
- public Grid Grid;
+ public Grid? Grid;
// Cache of Resize Direction and Behavior.
public GridResizeDirection ResizeDirection;
public GridResizeBehavior ResizeBehavior;
// The columns/rows to resize.
- public DefinitionBase Definition1;
- public DefinitionBase Definition2;
+ public DefinitionBase? Definition1;
+ public DefinitionBase? Definition2;
// Are the columns/rows star lengths.
public SplitBehavior SplitBehavior;
diff --git a/src/Avalonia.Controls/HotkeyManager.cs b/src/Avalonia.Controls/HotkeyManager.cs
index e89bb177dd..d83b996aa0 100644
--- a/src/Avalonia.Controls/HotkeyManager.cs
+++ b/src/Avalonia.Controls/HotkeyManager.cs
@@ -7,29 +7,29 @@ namespace Avalonia.Controls
{
public class HotKeyManager
{
- public static readonly AttachedProperty HotKeyProperty
- = AvaloniaProperty.RegisterAttached("HotKey", typeof(HotKeyManager));
+ public static readonly AttachedProperty HotKeyProperty
+ = AvaloniaProperty.RegisterAttached("HotKey", typeof(HotKeyManager));
class HotkeyCommandWrapper : ICommand
{
- public HotkeyCommandWrapper(ICommandSource control)
+ public HotkeyCommandWrapper(ICommandSource? control)
{
CommandSource = control;
}
- public readonly ICommandSource CommandSource;
+ public readonly ICommandSource? CommandSource;
- private ICommand GetCommand() => CommandSource.Command;
+ private ICommand? GetCommand() => CommandSource?.Command;
- public bool CanExecute(object parameter) =>
- CommandSource.Command?.CanExecute(CommandSource.CommandParameter) == true
+ public bool CanExecute(object? parameter) =>
+ CommandSource?.Command?.CanExecute(CommandSource.CommandParameter) == true
&& CommandSource.IsEffectivelyEnabled;
- public void Execute(object parameter) =>
- GetCommand()?.Execute(CommandSource.CommandParameter);
+ public void Execute(object? parameter) =>
+ GetCommand()?.Execute(CommandSource?.CommandParameter);
#pragma warning disable 67 // Event not used
- public event EventHandler CanExecuteChanged;
+ public event EventHandler? CanExecuteChanged;
#pragma warning restore 67
}
@@ -37,12 +37,12 @@ namespace Avalonia.Controls
class Manager
{
private readonly IControl _control;
- private TopLevel _root;
- private IDisposable _parentSub;
- private IDisposable _hotkeySub;
- private KeyGesture _hotkey;
+ private TopLevel? _root;
+ private IDisposable? _parentSub;
+ private IDisposable? _hotkeySub;
+ private KeyGesture? _hotkey;
private readonly HotkeyCommandWrapper _wrapper;
- private KeyBinding _binding;
+ private KeyBinding? _binding;
public Manager(IControl control)
{
@@ -56,14 +56,14 @@ namespace Avalonia.Controls
_parentSub = AncestorFinder.Create(_control).Subscribe(OnParentChanged);
}
- private void OnParentChanged(TopLevel control)
+ private void OnParentChanged(TopLevel? control)
{
Unregister();
_root = control;
Register();
}
- private void OnHotkeyChanged(KeyGesture hotkey)
+ private void OnHotkeyChanged(KeyGesture? hotkey)
{
if (hotkey == null)
//Subscription will be recreated by static property watcher
@@ -95,8 +95,8 @@ namespace Avalonia.Controls
void Stop()
{
Unregister();
- _parentSub.Dispose();
- _hotkeySub.Dispose();
+ _parentSub?.Dispose();
+ _hotkeySub?.Dispose();
}
}
@@ -118,6 +118,6 @@ namespace Avalonia.Controls
});
}
public static void SetHotKey(AvaloniaObject target, KeyGesture value) => target.SetValue(HotKeyProperty, value);
- public static KeyGesture GetHotKey(AvaloniaObject target) => target.GetValue(HotKeyProperty);
+ public static KeyGesture? GetHotKey(AvaloniaObject target) => target.GetValue(HotKeyProperty);
}
}
diff --git a/src/Avalonia.Controls/IContentControl.cs b/src/Avalonia.Controls/IContentControl.cs
index 889771b355..d28b0afb25 100644
--- a/src/Avalonia.Controls/IContentControl.cs
+++ b/src/Avalonia.Controls/IContentControl.cs
@@ -12,12 +12,12 @@ namespace Avalonia.Controls
///
/// Gets or sets the content to display.
///
- object Content { get; set; }
+ object? Content { get; set; }
///
/// Gets or sets the data template used to display the content of the control.
///
- IDataTemplate ContentTemplate { get; set; }
+ IDataTemplate? ContentTemplate { get; set; }
///
/// Gets or sets the horizontal alignment of the content within the control.
@@ -29,4 +29,4 @@ namespace Avalonia.Controls
///
VerticalAlignment VerticalContentAlignment { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Controls/IControl.cs b/src/Avalonia.Controls/IControl.cs
index 598e6b6f4e..b501bc15a7 100644
--- a/src/Avalonia.Controls/IControl.cs
+++ b/src/Avalonia.Controls/IControl.cs
@@ -3,8 +3,6 @@ using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls
{
///
diff --git a/src/Avalonia.Controls/IHeadered.cs b/src/Avalonia.Controls/IHeadered.cs
index c208e21c97..8c1b5cfb1b 100644
--- a/src/Avalonia.Controls/IHeadered.cs
+++ b/src/Avalonia.Controls/IHeadered.cs
@@ -8,6 +8,6 @@ namespace Avalonia.Controls
///
/// Gets or set the header.
///
- object Header { get; set; }
+ object? Header { get; set; }
}
}
diff --git a/src/Avalonia.Controls/IMenuElement.cs b/src/Avalonia.Controls/IMenuElement.cs
index 426f265084..a3200d2b1b 100644
--- a/src/Avalonia.Controls/IMenuElement.cs
+++ b/src/Avalonia.Controls/IMenuElement.cs
@@ -1,8 +1,6 @@
using System.Collections.Generic;
using Avalonia.Input;
-#nullable enable
-
namespace Avalonia.Controls
{
///
diff --git a/src/Avalonia.Controls/IMenuItem.cs b/src/Avalonia.Controls/IMenuItem.cs
index d92625218a..35e36eb0f4 100644
--- a/src/Avalonia.Controls/IMenuItem.cs
+++ b/src/Avalonia.Controls/IMenuItem.cs
@@ -1,6 +1,4 @@
-#nullable enable
-
-namespace Avalonia.Controls
+namespace Avalonia.Controls
{
///
/// Represents a .
diff --git a/src/Avalonia.Controls/IScrollAnchorProvider.cs b/src/Avalonia.Controls/IScrollAnchorProvider.cs
index 7ba02e99ea..b3ce7ef9e8 100644
--- a/src/Avalonia.Controls/IScrollAnchorProvider.cs
+++ b/src/Avalonia.Controls/IScrollAnchorProvider.cs
@@ -1,6 +1,4 @@
-#nullable enable
-
-namespace Avalonia.Controls
+namespace Avalonia.Controls
{
///
/// Specifies a contract for a scrolling control that supports scroll anchoring.
diff --git a/src/Avalonia.Controls/IVirtualizingPanel.cs b/src/Avalonia.Controls/IVirtualizingPanel.cs
index 8c4dc80934..604a62dcb9 100644
--- a/src/Avalonia.Controls/IVirtualizingPanel.cs
+++ b/src/Avalonia.Controls/IVirtualizingPanel.cs
@@ -16,7 +16,7 @@ namespace Avalonia.Controls
/// Note that this property may remain null if the panel is added to a control that does
/// not act as a virtualizing controller.
///
- IVirtualizingController Controller { get; set; }
+ IVirtualizingController? Controller { get; set; }
///
/// Gets a value indicating whether the panel is full.
diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs
index 1ff49326b6..ed8f9efb2e 100644
--- a/src/Avalonia.Controls/ItemsControl.cs
+++ b/src/Avalonia.Controls/ItemsControl.cs
@@ -32,8 +32,8 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly DirectProperty ItemsProperty =
- AvaloniaProperty.RegisterDirect(nameof(Items), o => o.Items, (o, v) => o.Items = v);
+ public static readonly DirectProperty ItemsProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Items), o => o.Items, (o, v) => o.Items = v);
///
/// Defines the property.
@@ -50,13 +50,13 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty ItemTemplateProperty =
- AvaloniaProperty.Register(nameof(ItemTemplate));
+ public static readonly StyledProperty ItemTemplateProperty =
+ AvaloniaProperty.Register(nameof(ItemTemplate));
- private IEnumerable _items = new AvaloniaList();
+ private IEnumerable? _items = new AvaloniaList();
private int _itemCount;
- private IItemContainerGenerator _itemContainerGenerator;
- private EventHandler _childIndexChanged;
+ private IItemContainerGenerator? _itemContainerGenerator;
+ private EventHandler? _childIndexChanged;
///
/// Initializes static members of the class.
@@ -87,13 +87,10 @@ namespace Avalonia.Controls
{
_itemContainerGenerator = CreateItemContainerGenerator();
- if (_itemContainerGenerator != null)
- {
- _itemContainerGenerator.ItemTemplate = ItemTemplate;
- _itemContainerGenerator.Materialized += (_, e) => OnContainersMaterialized(e);
- _itemContainerGenerator.Dematerialized += (_, e) => OnContainersDematerialized(e);
- _itemContainerGenerator.Recycled += (_, e) => OnContainersRecycled(e);
- }
+ _itemContainerGenerator.ItemTemplate = ItemTemplate;
+ _itemContainerGenerator.Materialized += (_, e) => OnContainersMaterialized(e);
+ _itemContainerGenerator.Dematerialized += (_, e) => OnContainersDematerialized(e);
+ _itemContainerGenerator.Recycled += (_, e) => OnContainersRecycled(e);
}
return _itemContainerGenerator;
@@ -104,7 +101,7 @@ namespace Avalonia.Controls
/// Gets or sets the items to display.
///
[Content]
- public IEnumerable Items
+ public IEnumerable? Items
{
get { return _items; }
set { SetAndRaise(ItemsProperty, ref _items, value); }
@@ -131,7 +128,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the data template used to display the items in the control.
///
- public IDataTemplate ItemTemplate
+ public IDataTemplate? ItemTemplate
{
get { return GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
@@ -140,13 +137,15 @@ namespace Avalonia.Controls
///
/// Gets the items presenter control.
///
- public IItemsPresenter Presenter
+ public IItemsPresenter? Presenter
{
get;
protected set;
}
- event EventHandler IChildIndexProvider.ChildIndexChanged
+ private protected bool WrapFocus { get; set; }
+
+ event EventHandler? IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
@@ -161,7 +160,7 @@ namespace Avalonia.Controls
}
Presenter = presenter;
- ItemContainerGenerator.Clear();
+ ItemContainerGenerator?.Clear();
if (Presenter is IChildIndexProvider innerProvider)
{
@@ -189,11 +188,11 @@ namespace Avalonia.Controls
/// The collection.
/// The index.
/// The item at the given index or null if the index is out of bounds.
- protected static object ElementAt(IEnumerable items, int index)
+ protected static object? ElementAt(IEnumerable? items, int index)
{
if (index != -1 && index < items.Count())
{
- return items.ElementAt(index) ?? null;
+ return items!.ElementAt(index) ?? null;
}
else
{
@@ -207,7 +206,7 @@ namespace Avalonia.Controls
/// The collection.
/// The item.
/// The index of the item or -1 if the item was not found.
- protected static int IndexOf(IEnumerable items, object item)
+ protected static int IndexOf(IEnumerable? items, object item)
{
if (items != null && item != null)
{
@@ -240,14 +239,8 @@ namespace Avalonia.Controls
/// Creates the for the control.
///
///
- /// An or null.
+ /// An .
///
- ///
- /// Certain controls such as don't actually create item
- /// containers; however they want it to be ItemsControls so that they have an Items
- /// property etc. In this case, a derived class can override this method to return null
- /// in order to disable the creation of item containers.
- ///
protected virtual IItemContainerGenerator CreateItemContainerGenerator()
{
return new ItemContainerGenerator(this);
@@ -282,7 +275,7 @@ namespace Avalonia.Controls
{
// If the item is its own container, then it will be removed from the logical tree
// when it is removed from the Items collection.
- if (container?.ContainerControl != container?.Item)
+ if (container.ContainerControl != container.Item)
{
LogicalChildren.Remove(container.ContainerControl);
}
@@ -311,20 +304,20 @@ namespace Avalonia.Controls
var container = Presenter?.Panel as INavigableContainer;
if (container == null ||
- focus.Current == null ||
+ focus?.Current == null ||
direction == null ||
direction.Value.IsTab())
{
return;
}
- IVisual current = focus.Current;
+ IVisual? current = focus.Current;
while (current != null)
{
if (current.VisualParent == container && current is IInputElement inputElement)
{
- IInputElement next = GetNextControl(container, direction.Value, inputElement, false);
+ var next = GetNextControl(container, direction.Value, inputElement, WrapFocus);
if (next != null)
{
@@ -406,7 +399,7 @@ namespace Avalonia.Controls
/// Given a collection of items, adds those that are controls to the logical children.
///
/// The items.
- private void AddControlItemsToLogicalChildren(IEnumerable items)
+ private void AddControlItemsToLogicalChildren(IEnumerable? items)
{
var toAdd = new List();
@@ -430,7 +423,7 @@ namespace Avalonia.Controls
/// Given a collection of items, removes those that are controls to from logical children.
///
/// The items.
- private void RemoveControlItemsFromLogicalChildren(IEnumerable items)
+ private void RemoveControlItemsFromLogicalChildren(IEnumerable? items)
{
var toRemove = new List();
@@ -454,7 +447,7 @@ namespace Avalonia.Controls
/// Subscribes to an collection.
///
/// The items collection.
- private void SubscribeToItems(IEnumerable items)
+ private void SubscribeToItems(IEnumerable? items)
{
if (items is INotifyCollectionChanged incc)
{
@@ -470,7 +463,7 @@ namespace Avalonia.Controls
{
if (_itemContainerGenerator != null)
{
- _itemContainerGenerator.ItemTemplate = (IDataTemplate)e.NewValue;
+ _itemContainerGenerator.ItemTemplate = (IDataTemplate?)e.NewValue;
// TODO: Rebuild the item containers.
}
}
@@ -497,13 +490,13 @@ namespace Avalonia.Controls
PseudoClasses.Set(":singleitem", itemCount == 1);
}
- protected static IInputElement GetNextControl(
+ protected static IInputElement? GetNextControl(
INavigableContainer container,
NavigationDirection direction,
- IInputElement from,
+ IInputElement? from,
bool wrap)
{
- IInputElement result;
+ IInputElement? result;
var c = from;
do
@@ -525,7 +518,7 @@ namespace Avalonia.Controls
return null;
}
- private void PresenterChildIndexChanged(object sender, ChildIndexChangedEventArgs e)
+ private void PresenterChildIndexChanged(object? sender, ChildIndexChangedEventArgs e)
{
_childIndexChanged?.Invoke(this, e);
}
diff --git a/src/Avalonia.Controls/ItemsSourceView.cs b/src/Avalonia.Controls/ItemsSourceView.cs
index c2d20495ef..945035ab5e 100644
--- a/src/Avalonia.Controls/ItemsSourceView.cs
+++ b/src/Avalonia.Controls/ItemsSourceView.cs
@@ -7,12 +7,9 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Avalonia.Controls.Utils;
-#nullable enable
-
namespace Avalonia.Controls
{
///
@@ -196,7 +193,7 @@ namespace Avalonia.Controls
_collectionChanged?.Invoke(this, args);
}
- private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
OnItemsSourceChanged(e);
}
@@ -239,8 +236,7 @@ namespace Avalonia.Controls
///
/// The index.
/// The item.
- [return: MaybeNull]
- public new T GetAt(int index) => (T)Inner[index];
+ public new T GetAt(int index) => (T)Inner[index]!;
public IEnumerator GetEnumerator() => Inner.Cast().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => Inner.GetEnumerator();
diff --git a/src/Avalonia.Controls/Label.cs b/src/Avalonia.Controls/Label.cs
index 9d5eda464f..5c8a6e0a5b 100644
--- a/src/Avalonia.Controls/Label.cs
+++ b/src/Avalonia.Controls/Label.cs
@@ -18,19 +18,19 @@ namespace Avalonia.Controls
///
/// Defines the Direct property
///
- public static readonly DirectProperty
public class LayoutTransformControl : Decorator
{
- public static readonly StyledProperty LayoutTransformProperty =
- AvaloniaProperty.Register(nameof(LayoutTransform));
+ public static readonly StyledProperty LayoutTransformProperty =
+ AvaloniaProperty.Register(nameof(LayoutTransform));
public static readonly StyledProperty UseRenderTransformProperty =
AvaloniaProperty.Register(nameof(UseRenderTransform));
@@ -37,7 +37,7 @@ namespace Avalonia.Controls
///
/// Gets or sets a graphics transformation that should apply to this element when layout is performed.
///
- public ITransform LayoutTransform
+ public ITransform? LayoutTransform
{
get { return GetValue(LayoutTransformProperty); }
set { SetValue(LayoutTransformProperty, value); }
@@ -52,7 +52,7 @@ namespace Avalonia.Controls
set { SetValue(UseRenderTransformProperty, value); }
}
- public IControl TransformRoot => Child;
+ public IControl? TransformRoot => Child;
///
/// Provides the behavior for the "Arrange" pass of layout.
@@ -146,7 +146,7 @@ namespace Avalonia.Controls
return transformedDesiredSize;
}
- IDisposable _renderTransformChangedEvent;
+ IDisposable? _renderTransformChangedEvent;
private void OnUseRenderTransformPropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
@@ -158,7 +158,7 @@ namespace Avalonia.Controls
// workaround.
var target = e.Sender as LayoutTransformControl;
- var shouldUseRenderTransform = (bool)e.NewValue;
+ var shouldUseRenderTransform = (bool)e.NewValue!;
if (target != null)
{
if (shouldUseRenderTransform)
@@ -217,7 +217,7 @@ namespace Avalonia.Controls
/// Transformation matrix corresponding to _matrixTransform.
///
private Matrix _transformation;
- private IDisposable _transformChangedEvent = null;
+ private IDisposable? _transformChangedEvent = null;
///
/// Returns true if Size a is smaller than Size b in either dimension.
diff --git a/src/Avalonia.Controls/ListBox.cs b/src/Avalonia.Controls/ListBox.cs
index 43b4908482..9b7ae0d324 100644
--- a/src/Avalonia.Controls/ListBox.cs
+++ b/src/Avalonia.Controls/ListBox.cs
@@ -23,13 +23,13 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly DirectProperty ScrollProperty =
- AvaloniaProperty.RegisterDirect(nameof(Scroll), o => o.Scroll);
+ public static readonly DirectProperty ScrollProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Scroll), o => o.Scroll);
///
/// Defines the property.
///
- public static readonly new DirectProperty SelectedItemsProperty =
+ public static readonly new DirectProperty SelectedItemsProperty =
SelectingItemsControl.SelectedItemsProperty;
///
@@ -50,7 +50,7 @@ namespace Avalonia.Controls
public static readonly StyledProperty VirtualizationModeProperty =
ItemsPresenter.VirtualizationModeProperty.AddOwner();
- private IScrollable _scroll;
+ private IScrollable? _scroll;
///
/// Initializes static members of the class.
@@ -64,14 +64,14 @@ namespace Avalonia.Controls
///
/// Gets the scroll information for the .
///
- public IScrollable Scroll
+ public IScrollable? Scroll
{
get { return _scroll; }
private set { SetAndRaise(ScrollProperty, ref _scroll, value); }
}
///
- public new IList SelectedItems
+ public new IList? SelectedItems
{
get => base.SelectedItems;
set => base.SelectedItems = value;
diff --git a/src/Avalonia.Controls/MaskedTextBox.cs b/src/Avalonia.Controls/MaskedTextBox.cs
index f59cef8223..ad64c61ebe 100644
--- a/src/Avalonia.Controls/MaskedTextBox.cs
+++ b/src/Avalonia.Controls/MaskedTextBox.cs
@@ -8,8 +8,6 @@ using Avalonia.Input.Platform;
using Avalonia.Interactivity;
using Avalonia.Styling;
-#nullable enable
-
namespace Avalonia.Controls
{
public class MaskedTextBox : TextBox, IStyleable
@@ -241,7 +239,7 @@ namespace Avalonia.Controls
switch (e.Key)
{
case Key.Delete:
- if (CaretIndex < Text.Length)
+ if (CaretIndex < Text?.Length)
{
if (MaskProvider.RemoveAt(CaretIndex))
{
@@ -286,7 +284,7 @@ namespace Avalonia.Controls
{
void UpdateMaskProvider()
{
- MaskProvider = new MaskedTextProvider(Mask, Culture, true, PromptChar, PasswordChar, AsciiOnly) { ResetOnSpace = ResetOnSpace, ResetOnPrompt = ResetOnPrompt };
+ MaskProvider = new MaskedTextProvider(Mask!, Culture, true, PromptChar, PasswordChar, AsciiOnly) { ResetOnSpace = ResetOnSpace, ResetOnPrompt = ResetOnPrompt };
if (Text != null)
{
MaskProvider.Set(Text);
@@ -383,11 +381,11 @@ namespace Avalonia.Controls
}
}
- if (CaretIndex < Text.Length)
+ if (CaretIndex < Text?.Length)
{
CaretIndex = GetNextCharacterPosition(CaretIndex);
- if (MaskProvider.InsertAt(e.Text, CaretIndex))
+ if (MaskProvider.InsertAt(e.Text!, CaretIndex))
{
CaretIndex++;
}
diff --git a/src/Avalonia.Controls/Menu.cs b/src/Avalonia.Controls/Menu.cs
index 706be376a9..cc89677f82 100644
--- a/src/Avalonia.Controls/Menu.cs
+++ b/src/Avalonia.Controls/Menu.cs
@@ -5,8 +5,6 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
-#nullable enable
-
namespace Avalonia.Controls
{
///
diff --git a/src/Avalonia.Controls/MenuBase.cs b/src/Avalonia.Controls/MenuBase.cs
index 0434928280..bdcff5cd09 100644
--- a/src/Avalonia.Controls/MenuBase.cs
+++ b/src/Avalonia.Controls/MenuBase.cs
@@ -8,8 +8,6 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
-#nullable enable
-
namespace Avalonia.Controls
{
///
@@ -83,12 +81,13 @@ namespace Avalonia.Controls
{
var index = SelectedIndex;
return (index != -1) ?
- (IMenuItem)ItemContainerGenerator.ContainerFromIndex(index) :
+ (IMenuItem?)ItemContainerGenerator.ContainerFromIndex(index) :
null;
}
set
{
- SelectedIndex = ItemContainerGenerator.IndexFromContainer(value);
+ SelectedIndex = value is not null ?
+ ItemContainerGenerator.IndexFromContainer(value) : -1;
}
}
@@ -111,7 +110,7 @@ namespace Avalonia.Controls
///
/// Occurs when a is opened.
///
- public event EventHandler MenuOpened
+ public event EventHandler? MenuOpened
{
add { AddHandler(MenuOpenedEvent, value); }
remove { RemoveHandler(MenuOpenedEvent, value); }
@@ -120,7 +119,7 @@ namespace Avalonia.Controls
///
/// Occurs when a is closed.
///
- public event EventHandler MenuClosed
+ public event EventHandler? MenuClosed
{
add { AddHandler(MenuClosedEvent, value); }
remove { RemoveHandler(MenuClosedEvent, value); }
diff --git a/src/Avalonia.Controls/MenuItem.cs b/src/Avalonia.Controls/MenuItem.cs
index b843992f04..185b834052 100644
--- a/src/Avalonia.Controls/MenuItem.cs
+++ b/src/Avalonia.Controls/MenuItem.cs
@@ -14,8 +14,6 @@ using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls
{
///
@@ -42,20 +40,20 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty CommandParameterProperty =
+ public static readonly StyledProperty CommandParameterProperty =
Button.CommandParameterProperty.AddOwner();
///
/// Defines the property.
///
- public static readonly StyledProperty IconProperty =
- AvaloniaProperty.Register(nameof(Icon));
+ public static readonly StyledProperty IconProperty =
+ AvaloniaProperty.Register(nameof(Icon));
///
/// Defines the property.
///
- public static readonly StyledProperty InputGestureProperty =
- AvaloniaProperty.Register(nameof(InputGesture));
+ public static readonly StyledProperty InputGestureProperty =
+ AvaloniaProperty.Register(nameof(InputGesture));
///
/// Defines the property.
@@ -164,7 +162,7 @@ namespace Avalonia.Controls
///
/// Occurs when a without a submenu is clicked.
///
- public event EventHandler Click
+ public event EventHandler? Click
{
add { AddHandler(ClickEvent, value); }
remove { RemoveHandler(ClickEvent, value); }
@@ -176,7 +174,7 @@ namespace Avalonia.Controls
///
/// A bubbling version of the event for menu items.
///
- public event EventHandler PointerEnterItem
+ public event EventHandler? PointerEnterItem
{
add { AddHandler(PointerEnterItemEvent, value); }
remove { RemoveHandler(PointerEnterItemEvent, value); }
@@ -188,7 +186,7 @@ namespace Avalonia.Controls
///
/// A bubbling version of the event for menu items.
///
- public event EventHandler PointerLeaveItem
+ public event EventHandler? PointerLeaveItem
{
add { AddHandler(PointerLeaveItemEvent, value); }
remove { RemoveHandler(PointerLeaveItemEvent, value); }
@@ -197,7 +195,7 @@ namespace Avalonia.Controls
///
/// Occurs when a 's submenu is opened.
///
- public event EventHandler SubmenuOpened
+ public event EventHandler? SubmenuOpened
{
add { AddHandler(SubmenuOpenedEvent, value); }
remove { RemoveHandler(SubmenuOpenedEvent, value); }
@@ -225,7 +223,7 @@ namespace Avalonia.Controls
/// Gets or sets the parameter to pass to the property of a
/// .
///
- public object CommandParameter
+ public object? CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
@@ -234,7 +232,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the icon that appears in a .
///
- public object Icon
+ public object? Icon
{
get { return GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
@@ -247,7 +245,7 @@ namespace Avalonia.Controls
/// Setting this property does not cause the input gesture to be handled by the menu item,
/// it simply displays the gesture text in the menu.
///
- public KeyGesture InputGesture
+ public KeyGesture? InputGesture
{
get { return GetValue(InputGestureProperty); }
set { SetValue(InputGestureProperty, value); }
@@ -310,12 +308,12 @@ namespace Avalonia.Controls
{
var index = SelectedIndex;
return (index != -1) ?
- (IMenuItem)ItemContainerGenerator.ContainerFromIndex(index) :
+ (IMenuItem?)ItemContainerGenerator.ContainerFromIndex(index) :
null;
}
set
{
- SelectedIndex = ItemContainerGenerator.IndexFromContainer(value);
+ SelectedIndex = value is not null ? ItemContainerGenerator.IndexFromContainer(value) : -1;
}
}
@@ -390,7 +388,7 @@ namespace Avalonia.Controls
parent = parent.Parent;
}
- _isEmbeddedInMenu = parent.FindLogicalAncestorOfType(true) != null;
+ _isEmbeddedInMenu = parent?.FindLogicalAncestorOfType(true) != null;
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
@@ -561,7 +559,7 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- private void CanExecuteChanged(object sender, EventArgs e)
+ private void CanExecuteChanged(object? sender, EventArgs e)
{
TryUpdateCanExecute();
}
@@ -655,7 +653,7 @@ namespace Avalonia.Controls
if (value)
{
- foreach (var item in Items.OfType())
+ foreach (var item in Items!.OfType())
{
item.TryUpdateCanExecute();
}
@@ -677,13 +675,13 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- private void PopupOpened(object sender, EventArgs e)
+ private void PopupOpened(object? sender, EventArgs e)
{
var selected = SelectedIndex;
if (selected != -1)
{
- var container = ItemContainerGenerator.ContainerFromIndex(selected);
+ var container = ItemContainerGenerator?.ContainerFromIndex(selected);
container?.Focus();
}
}
@@ -693,7 +691,7 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- private void PopupClosed(object sender, EventArgs e)
+ private void PopupClosed(object? sender, EventArgs e)
{
SelectedItem = null;
}
diff --git a/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs b/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs
index 2c3dac8482..4cc6a20082 100644
--- a/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs
+++ b/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs
@@ -19,7 +19,7 @@ namespace Avalonia.Controls
///
/// The window to which the handler belongs.
///
- private IInputRoot _owner;
+ private IInputRoot? _owner;
///
/// Gets or sets the window's main menu.
@@ -27,7 +27,7 @@ namespace Avalonia.Controls
///
/// This property is ignored as a menu item cannot have a main menu.
///
- public IMainMenu MainMenu { get; set; }
+ public IMainMenu? MainMenu { get; set; }
///
/// Sets the owner of the access key handler.
@@ -38,7 +38,7 @@ namespace Avalonia.Controls
///
public void SetOwner(IInputRoot owner)
{
- Contract.Requires(owner != null);
+ _ = owner ?? throw new ArgumentNullException(nameof(owner));
if (_owner != null)
{
@@ -84,7 +84,7 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- protected virtual void OnTextInput(object sender, TextInputEventArgs e)
+ protected virtual void OnTextInput(object? sender, TextInputEventArgs e)
{
if (!string.IsNullOrWhiteSpace(e.Text))
{
diff --git a/src/Avalonia.Controls/Mixins/SelectableMixin.cs b/src/Avalonia.Controls/Mixins/SelectableMixin.cs
index c9e2b684cb..fa964c0056 100644
--- a/src/Avalonia.Controls/Mixins/SelectableMixin.cs
+++ b/src/Avalonia.Controls/Mixins/SelectableMixin.cs
@@ -40,7 +40,7 @@ namespace Avalonia.Controls.Mixins
public static void Attach(AvaloniaProperty isSelected)
where TControl : class, IControl
{
- Contract.Requires(isSelected != null);
+ _ = isSelected ?? throw new ArgumentNullException(nameof(isSelected));
isSelected.Changed.Subscribe(x =>
{
diff --git a/src/Avalonia.Controls/NativeControlHost.cs b/src/Avalonia.Controls/NativeControlHost.cs
index e18b7a5ba2..191b60f303 100644
--- a/src/Avalonia.Controls/NativeControlHost.cs
+++ b/src/Avalonia.Controls/NativeControlHost.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using Avalonia.Controls.Platform;
using Avalonia.Platform;
using Avalonia.Threading;
@@ -9,10 +10,10 @@ namespace Avalonia.Controls
{
public class NativeControlHost : Control
{
- private TopLevel _currentRoot;
- private INativeControlHostImpl _currentHost;
- private INativeControlHostControlTopLevelAttachment _attachment;
- private IPlatformHandle _nativeControlHandle;
+ private TopLevel? _currentRoot;
+ private INativeControlHostImpl? _currentHost;
+ private INativeControlHostControlTopLevelAttachment? _attachment;
+ private IPlatformHandle? _nativeControlHandle;
private bool _queuedForDestruction;
private bool _queuedForMoveResize;
private readonly List _propertyChangedSubscriptions = new List();
@@ -35,7 +36,7 @@ namespace Avalonia.Controls
UpdateHost();
}
- private void PropertyChangedHandler(object sender, AvaloniaPropertyChangedEventArgs e)
+ private void PropertyChangedHandler(object? sender, AvaloniaPropertyChangedEventArgs e)
{
if (e.IsEffectiveValueChange && (e.Property == BoundsProperty || e.Property == IsVisibleProperty))
EnqueueForMoveResize();
@@ -58,9 +59,8 @@ namespace Avalonia.Controls
{
_queuedForMoveResize = false;
_currentHost = (_currentRoot?.PlatformImpl as ITopLevelImplWithNativeControlHost)?.NativeControlHost;
- var needsAttachment = _currentHost != null;
- if (needsAttachment)
+ if (_currentHost != null)
{
// If there is an existing attachment, ensure that we are attached to the proper host or destroy the attachment
if (_attachment != null && _attachment.AttachedTo != _currentHost)
@@ -119,6 +119,8 @@ namespace Avalonia.Controls
private Rect? GetAbsoluteBounds()
{
+ Debug.Assert(_currentRoot is not null);
+
var bounds = Bounds;
var position = this.TranslatePoint(default, _currentRoot);
if (position == null)
@@ -140,9 +142,8 @@ namespace Avalonia.Controls
return false;
var bounds = GetAbsoluteBounds();
- var needsShow = IsEffectivelyVisible && bounds.HasValue;
- if (needsShow)
+ if (IsEffectivelyVisible && bounds.HasValue)
{
if (bounds.Value.IsEmpty)
return false;
diff --git a/src/Avalonia.Controls/NativeMenu.Export.cs b/src/Avalonia.Controls/NativeMenu.Export.cs
index 6bfe5ebc82..fe650ab41e 100644
--- a/src/Avalonia.Controls/NativeMenu.Export.cs
+++ b/src/Avalonia.Controls/NativeMenu.Export.cs
@@ -18,7 +18,7 @@ namespace Avalonia.Controls
class NativeMenuInfo
{
public bool ChangingIsExported { get; set; }
- public ITopLevelNativeMenuExporter Exporter { get; }
+ public ITopLevelNativeMenuExporter? Exporter { get; }
public NativeMenuInfo(TopLevel target)
{
diff --git a/src/Avalonia.Controls/NativeMenu.cs b/src/Avalonia.Controls/NativeMenu.cs
index 58ee99722f..5ff4148e5a 100644
--- a/src/Avalonia.Controls/NativeMenu.cs
+++ b/src/Avalonia.Controls/NativeMenu.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Controls
{
private readonly AvaloniaList _items =
new AvaloniaList { ResetBehavior = ResetBehavior.Remove };
- private NativeMenuItem _parent;
+ private NativeMenuItem? _parent;
[Content]
public IList Items => _items;
@@ -23,7 +23,7 @@ namespace Avalonia.Controls
/// Use this event to add, remove or modify menu items before a menu is
/// shown or a hotkey is pressed.
///
- public event EventHandler NeedsUpdate;
+ public event EventHandler? NeedsUpdate;
///
/// Raised before the menu is opened.
@@ -31,7 +31,7 @@ namespace Avalonia.Controls
///
/// Do not update the menu in this event; use .
///
- public event EventHandler Opening;
+ public event EventHandler? Opening;
///
/// Raised after the menu is closed.
@@ -39,7 +39,7 @@ namespace Avalonia.Controls
///
/// Do not update the menu in this event; use .
///
- public event EventHandler Closed;
+ public event EventHandler? Closed;
public NativeMenu()
{
@@ -68,7 +68,7 @@ namespace Avalonia.Controls
throw new InvalidOperationException("NativeMenuItem already has a parent");
}
- private void ItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void ItemsChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null)
foreach (NativeMenuItemBase i in e.OldItems)
@@ -78,10 +78,10 @@ namespace Avalonia.Controls
i.Parent = this;
}
- public static readonly DirectProperty ParentProperty =
- AvaloniaProperty.RegisterDirect("Parent", o => o.Parent, (o, v) => o.Parent = v);
+ public static readonly DirectProperty ParentProperty =
+ AvaloniaProperty.RegisterDirect("Parent", o => o.Parent, (o, v) => o.Parent = v);
- public NativeMenuItem Parent
+ public NativeMenuItem? Parent
{
get => _parent;
set => SetAndRaise(ParentProperty, ref _parent, value);
diff --git a/src/Avalonia.Controls/NativeMenuBar.cs b/src/Avalonia.Controls/NativeMenuBar.cs
index 5d2e1087a7..ae473f8500 100644
--- a/src/Avalonia.Controls/NativeMenuBar.cs
+++ b/src/Avalonia.Controls/NativeMenuBar.cs
@@ -27,9 +27,9 @@ namespace Avalonia.Controls
menuItem.SetValue(EnableMenuItemClickForwardingProperty, enable);
}
- private static void OnMenuItemClick(object sender, RoutedEventArgs e)
+ private static void OnMenuItemClick(object? sender, RoutedEventArgs e)
{
- (((MenuItem)sender).DataContext as INativeMenuItemExporterEventsImplBridge)?.RaiseClicked();
+ (((MenuItem)sender!).DataContext as INativeMenuItemExporterEventsImplBridge)?.RaiseClicked();
}
}
}
diff --git a/src/Avalonia.Controls/NativeMenuItem.cs b/src/Avalonia.Controls/NativeMenuItem.cs
index 4d048f0fb0..265e7119eb 100644
--- a/src/Avalonia.Controls/NativeMenuItem.cs
+++ b/src/Avalonia.Controls/NativeMenuItem.cs
@@ -9,23 +9,23 @@ namespace Avalonia.Controls
{
public class NativeMenuItem : NativeMenuItemBase, INativeMenuItemExporterEventsImplBridge
{
- private string _header;
- private KeyGesture _gesture;
+ private string? _header;
+ private KeyGesture? _gesture;
private bool _isEnabled = true;
- private ICommand _command;
+ private ICommand? _command;
private bool _isChecked = false;
private NativeMenuItemToggleType _toggleType;
- private IBitmap _icon;
+ private IBitmap? _icon;
private readonly CanExecuteChangedSubscriber _canExecuteChangedSubscriber;
- private NativeMenu _menu;
+ private NativeMenu? _menu;
static NativeMenuItem()
{
MenuProperty.Changed.Subscribe(args =>
{
var item = (NativeMenuItem)args.Sender;
- var value = args.NewValue.GetValueOrDefault();
+ var value = args.NewValue.GetValueOrDefault()!;
if (value.Parent != null && value.Parent != item)
throw new InvalidOperationException("NativeMenu already has a parent");
value.Parent = item;
@@ -59,44 +59,44 @@ namespace Avalonia.Controls
Header = header;
}
- public static readonly DirectProperty MenuProperty =
- AvaloniaProperty.RegisterDirect(nameof(Menu), o => o.Menu, (o, v) => o.Menu = v);
+ public static readonly DirectProperty MenuProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Menu), o => o.Menu, (o, v) => o.Menu = v);
[Content]
- public NativeMenu Menu
+ public NativeMenu? Menu
{
get => _menu;
set
{
- if (value.Parent != null && value.Parent != this)
+ if (value != null && value.Parent != null && value.Parent != this)
throw new InvalidOperationException("NativeMenu already has a parent");
SetAndRaise(MenuProperty, ref _menu, value);
}
}
- public static readonly DirectProperty IconProperty =
- AvaloniaProperty.RegisterDirect(nameof(Icon), o => o.Icon, (o, v) => o.Icon = v);
+ public static readonly DirectProperty IconProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Icon), o => o.Icon, (o, v) => o.Icon = v);
- public IBitmap Icon
+ public IBitmap? Icon
{
get => _icon;
set => SetAndRaise(IconProperty, ref _icon, value);
}
- public static readonly DirectProperty HeaderProperty =
- AvaloniaProperty.RegisterDirect(nameof(Header), o => o.Header, (o, v) => o.Header = v);
+ public static readonly DirectProperty HeaderProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Header), o => o.Header, (o, v) => o.Header = v);
- public string Header
+ public string? Header
{
get => _header;
set => SetAndRaise(HeaderProperty, ref _header, value);
}
- public static readonly DirectProperty GestureProperty =
- AvaloniaProperty.RegisterDirect(nameof(Gesture), o => o.Gesture, (o, v) => o.Gesture = v);
+ public static readonly DirectProperty GestureProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Gesture), o => o.Gesture, (o, v) => o.Gesture = v);
- public KeyGesture Gesture
+ public KeyGesture? Gesture
{
get => _gesture;
set => SetAndRaise(GestureProperty, ref _gesture, value);
@@ -126,7 +126,7 @@ namespace Avalonia.Controls
set => SetAndRaise(ToggleTypeProperty, ref _toggleType, value);
}
- public static readonly DirectProperty CommandProperty =
+ public static readonly DirectProperty CommandProperty =
Button.CommandProperty.AddOwner(
menuItem => menuItem.Command,
(menuItem, command) => menuItem.Command = command,
@@ -135,7 +135,7 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty CommandParameterProperty =
+ public static readonly StyledProperty CommandParameterProperty =
Button.CommandParameterProperty.AddOwner();
public static readonly DirectProperty IsEnabledProperty =
@@ -154,7 +154,7 @@ namespace Avalonia.Controls
public bool HasClickHandlers => Click != null;
- public ICommand Command
+ public ICommand? Command
{
get => _command;
set
@@ -175,7 +175,7 @@ namespace Avalonia.Controls
/// Gets or sets the parameter to pass to the property of a
/// .
///
- public object CommandParameter
+ public object? CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
@@ -184,7 +184,7 @@ namespace Avalonia.Controls
///
/// Occurs when a is clicked.
///
- public event EventHandler Click;
+ public event EventHandler? Click;
[Obsolete("Use Click event.")]
public event EventHandler Clicked
diff --git a/src/Avalonia.Controls/NativeMenuItemBase.cs b/src/Avalonia.Controls/NativeMenuItemBase.cs
index 47eb86cdc3..a5e3308e3b 100644
--- a/src/Avalonia.Controls/NativeMenuItemBase.cs
+++ b/src/Avalonia.Controls/NativeMenuItemBase.cs
@@ -4,17 +4,17 @@ namespace Avalonia.Controls
{
public class NativeMenuItemBase : AvaloniaObject
{
- private NativeMenu _parent;
+ private NativeMenu? _parent;
internal NativeMenuItemBase()
{
}
- public static readonly DirectProperty ParentProperty =
- AvaloniaProperty.RegisterDirect("Parent", o => o.Parent, (o, v) => o.Parent = v);
+ public static readonly DirectProperty ParentProperty =
+ AvaloniaProperty.RegisterDirect("Parent", o => o.Parent, (o, v) => o.Parent = v);
- public NativeMenu Parent
+ public NativeMenu? Parent
{
get => _parent;
set => SetAndRaise(ParentProperty, ref _parent, value);
diff --git a/src/Avalonia.Controls/Notifications/INotification.cs b/src/Avalonia.Controls/Notifications/INotification.cs
index dc69a12887..fa08233097 100644
--- a/src/Avalonia.Controls/Notifications/INotification.cs
+++ b/src/Avalonia.Controls/Notifications/INotification.cs
@@ -10,12 +10,12 @@ namespace Avalonia.Controls.Notifications
///
/// Gets the Title of the notification.
///
- string Title { get; }
+ string? Title { get; }
///
/// Gets the notification message.
///
- string Message { get; }
+ string? Message { get; }
///
/// Gets the of the notification.
@@ -31,11 +31,11 @@ namespace Avalonia.Controls.Notifications
///
/// Gets an Action to be run when the notification is clicked.
///
- Action OnClick { get; }
+ Action? OnClick { get; }
///
/// Gets an Action to be run when the notification is closed.
///
- Action OnClose { get; }
+ Action? OnClose { get; }
}
}
diff --git a/src/Avalonia.Controls/Notifications/Notification.cs b/src/Avalonia.Controls/Notifications/Notification.cs
index 9bb514971b..376df175f3 100644
--- a/src/Avalonia.Controls/Notifications/Notification.cs
+++ b/src/Avalonia.Controls/Notifications/Notification.cs
@@ -21,12 +21,12 @@ namespace Avalonia.Controls.Notifications
/// Use for notifications that will remain open.
/// An Action to call when the notification is clicked.
/// An Action to call when the notification is closed.
- public Notification(string title,
- string message,
+ public Notification(string? title,
+ string? message,
NotificationType type = NotificationType.Information,
TimeSpan? expiration = null,
- Action onClick = null,
- Action onClose = null)
+ Action? onClick = null,
+ Action? onClose = null)
{
Title = title;
Message = message;
@@ -37,10 +37,10 @@ namespace Avalonia.Controls.Notifications
}
///
- public string Title { get; private set; }
+ public string? Title { get; private set; }
///
- public string Message { get; private set; }
+ public string? Message { get; private set; }
///
public NotificationType Type { get; private set; }
@@ -49,9 +49,9 @@ namespace Avalonia.Controls.Notifications
public TimeSpan Expiration { get; private set; }
///
- public Action OnClick { get; private set; }
+ public Action? OnClick { get; private set; }
///
- public Action OnClose { get; private set; }
+ public Action? OnClose { get; private set; }
}
}
diff --git a/src/Avalonia.Controls/Notifications/NotificationCard.cs b/src/Avalonia.Controls/Notifications/NotificationCard.cs
index ad883c8076..a103adf185 100644
--- a/src/Avalonia.Controls/Notifications/NotificationCard.cs
+++ b/src/Avalonia.Controls/Notifications/NotificationCard.cs
@@ -37,8 +37,11 @@ namespace Avalonia.Controls.Notifications
RaiseEvent(new RoutedEventArgs(NotificationClosedEvent));
});
+ // Disabling nullable checking because of https://github.com/dotnet/reactive/issues/1525
+#pragma warning disable CS8620
this.GetObservable(ContentProperty)
.OfType()
+#pragma warning restore CS8620
.Subscribe(x =>
{
switch (x.Type)
@@ -102,7 +105,7 @@ namespace Avalonia.Controls.Notifications
///
/// Raised when the has closed.
///
- public event EventHandler NotificationClosed
+ public event EventHandler? NotificationClosed
{
add { AddHandler(NotificationClosedEvent, value); }
remove { RemoveHandler(NotificationClosedEvent, value); }
@@ -110,13 +113,13 @@ namespace Avalonia.Controls.Notifications
public static bool GetCloseOnClick(Button obj)
{
- Contract.Requires(obj != null);
+ _ = obj ?? throw new ArgumentNullException(nameof(obj));
return (bool)obj.GetValue(CloseOnClickProperty);
}
public static void SetCloseOnClick(Button obj, bool value)
{
- Contract.Requires(obj != null);
+ _ = obj ?? throw new ArgumentNullException(nameof(obj));
obj.SetValue(CloseOnClickProperty, value);
}
@@ -129,7 +132,7 @@ namespace Avalonia.Controls.Notifications
private static void OnCloseOnClickPropertyChanged(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e)
{
var button = (Button)d;
- var value = (bool)e.NewValue;
+ var value = (bool)e.NewValue!;
if (value)
{
button.Click += Button_Click;
@@ -143,10 +146,10 @@ namespace Avalonia.Controls.Notifications
///
/// Called when a button inside the Notification is clicked.
///
- private static void Button_Click(object sender, RoutedEventArgs e)
+ private static void Button_Click(object? sender, RoutedEventArgs e)
{
var btn = sender as ILogical;
- var notification = btn.GetLogicalAncestors().OfType().FirstOrDefault();
+ var notification = btn?.GetLogicalAncestors().OfType().FirstOrDefault();
notification?.Close();
}
diff --git a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
index 8f5c6faf40..9499995da3 100644
--- a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
+++ b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
@@ -17,7 +17,7 @@ namespace Avalonia.Controls.Notifications
[PseudoClasses(":topleft", ":topright", ":bottomleft", ":bottomright")]
public class WindowNotificationManager : TemplatedControl, IManagedNotificationManager, ICustomSimpleHitTest
{
- private IList _items;
+ private IList? _items;
///
/// Defines the property.
@@ -107,7 +107,7 @@ namespace Avalonia.Controls.Notifications
{
notification.OnClose?.Invoke();
- _items.Remove(sender);
+ _items?.Remove(sender);
};
}
@@ -121,9 +121,9 @@ namespace Avalonia.Controls.Notifications
(sender as NotificationCard)?.Close();
};
- _items.Add(notificationControl);
+ _items?.Add(notificationControl);
- if (_items.OfType().Count(i => !i.IsClosing) > MaxItems)
+ if (_items?.OfType().Count(i => !i.IsClosing) > MaxItems)
{
_items.OfType().First(i => !i.IsClosing).Close();
}
diff --git a/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs b/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
index eba381e5fa..f67377b310 100644
--- a/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
+++ b/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
@@ -46,15 +46,15 @@ namespace Avalonia.Controls
/// Defines the property.
///
[Obsolete]
- public static readonly DirectProperty CultureInfoProperty =
- AvaloniaProperty.RegisterDirect(nameof(CultureInfo), o => o.CultureInfo,
+ public static readonly DirectProperty CultureInfoProperty =
+ AvaloniaProperty.RegisterDirect(nameof(CultureInfo), o => o.CultureInfo,
(o, v) => o.CultureInfo = v, CultureInfo.CurrentCulture);
///
/// Defines the property.
///
- public static readonly DirectProperty NumberFormatProperty =
- AvaloniaProperty.RegisterDirect(nameof(NumberFormat), o => o.NumberFormat,
+ public static readonly DirectProperty NumberFormatProperty =
+ AvaloniaProperty.RegisterDirect(nameof(NumberFormat), o => o.NumberFormat,
(o, v) => o.NumberFormat = v, NumberFormatInfo.CurrentInfo);
///
@@ -97,8 +97,8 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly DirectProperty TextProperty =
- AvaloniaProperty.RegisterDirect(nameof(Text), o => o.Text, (o, v) => o.Text = v,
+ public static readonly DirectProperty TextProperty =
+ AvaloniaProperty.RegisterDirect(nameof(Text), o => o.Text, (o, v) => o.Text = v,
defaultBindingMode: BindingMode.TwoWay, enableDataValidation: true);
///
@@ -111,8 +111,8 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty WatermarkProperty =
- AvaloniaProperty.Register(nameof(Watermark));
+ public static readonly StyledProperty WatermarkProperty =
+ AvaloniaProperty.Register(nameof(Watermark));
///
/// Defines the property.
@@ -126,27 +126,27 @@ namespace Avalonia.Controls
public static readonly StyledProperty VerticalContentAlignmentProperty =
ContentControl.VerticalContentAlignmentProperty.AddOwner();
- private IDisposable _textBoxTextChangedSubscription;
+ private IDisposable? _textBoxTextChangedSubscription;
private decimal _value;
- private string _text;
+ private string? _text;
private bool _internalValueSet;
private bool _clipValueToMinMax;
private bool _isSyncingTextAndValueProperties;
private bool _isTextChangedFromUI;
- private CultureInfo _cultureInfo;
+ private CultureInfo? _cultureInfo;
private NumberStyles _parsingNumberStyle = NumberStyles.Any;
- private NumberFormatInfo _numberFormat;
+ private NumberFormatInfo? _numberFormat;
///
/// Gets the Spinner template part.
///
- private Spinner Spinner { get; set; }
+ private Spinner? Spinner { get; set; }
///
/// Gets the TextBox template part.
///
- private TextBox TextBox { get; set; }
+ private TextBox? TextBox { get; set; }
///
/// Gets or sets the ability to perform increment/decrement operations via the keyboard, button spinners, or mouse wheel.
@@ -188,7 +188,7 @@ namespace Avalonia.Controls
/// Gets or sets the current CultureInfo.
///
[Obsolete("CultureInfo is obsolete, please use NumberFormat instead.")]
- public CultureInfo CultureInfo
+ public CultureInfo? CultureInfo
{
get { return _cultureInfo; }
set
@@ -202,7 +202,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the current NumberFormatInfo
///
- public NumberFormatInfo NumberFormat
+ public NumberFormatInfo? NumberFormat
{
get { return _numberFormat; }
set { SetAndRaise(NumberFormatProperty, ref _numberFormat, value); }
@@ -265,7 +265,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the formatted string representation of the value.
///
- public string Text
+ public string? Text
{
get { return _text; }
set { SetAndRaise(TextProperty, ref _text, value); }
@@ -287,7 +287,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the object to use as a watermark if the is null.
///
- public string Watermark
+ public string? Watermark
{
get { return GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
@@ -414,7 +414,7 @@ namespace Avalonia.Controls
///
/// The old value.
/// The new value.
- protected virtual void OnCultureInfoChanged(CultureInfo oldValue, CultureInfo newValue)
+ protected virtual void OnCultureInfoChanged(CultureInfo? oldValue, CultureInfo? newValue)
{
if (IsInitialized)
{
@@ -427,7 +427,7 @@ namespace Avalonia.Controls
///
/// The old value.
/// The new value.
- protected virtual void OnNumberFormatChanged(NumberFormatInfo oldValue, NumberFormatInfo newValue)
+ protected virtual void OnNumberFormatChanged(NumberFormatInfo? oldValue, NumberFormatInfo? newValue)
{
if (IsInitialized)
{
@@ -440,7 +440,7 @@ namespace Avalonia.Controls
///
/// The old value.
/// The new value.
- protected virtual void OnFormatStringChanged(string oldValue, string newValue)
+ protected virtual void OnFormatStringChanged(string? oldValue, string? newValue)
{
if (IsInitialized)
{
@@ -510,7 +510,7 @@ namespace Avalonia.Controls
///
/// The old value.
/// The new value.
- protected virtual void OnTextChanged(string oldValue, string newValue)
+ protected virtual void OnTextChanged(string? oldValue, string? newValue)
{
if (IsInitialized)
{
@@ -706,8 +706,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (CultureInfo)e.OldValue;
- var newValue = (CultureInfo)e.NewValue;
+ var oldValue = (CultureInfo?)e.OldValue;
+ var newValue = (CultureInfo?)e.NewValue;
upDown.OnCultureInfoChanged(oldValue, newValue);
}
}
@@ -720,8 +720,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (NumberFormatInfo)e.OldValue;
- var newValue = (NumberFormatInfo)e.NewValue;
+ var oldValue = (NumberFormatInfo?)e.OldValue;
+ var newValue = (NumberFormatInfo?)e.NewValue;
upDown.OnNumberFormatChanged(oldValue, newValue);
}
}
@@ -734,8 +734,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (decimal)e.OldValue;
- var newValue = (decimal)e.NewValue;
+ var oldValue = (decimal)e.OldValue!;
+ var newValue = (decimal)e.NewValue!;
upDown.OnIncrementChanged(oldValue, newValue);
}
}
@@ -748,8 +748,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (string)e.OldValue;
- var newValue = (string)e.NewValue;
+ var oldValue = (string?)e.OldValue;
+ var newValue = (string?)e.NewValue;
upDown.OnFormatStringChanged(oldValue, newValue);
}
}
@@ -762,8 +762,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (bool)e.OldValue;
- var newValue = (bool)e.NewValue;
+ var oldValue = (bool)e.OldValue!;
+ var newValue = (bool)e.NewValue!;
upDown.OnIsReadOnlyChanged(oldValue, newValue);
}
}
@@ -776,8 +776,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (decimal)e.OldValue;
- var newValue = (decimal)e.NewValue;
+ var oldValue = (decimal)e.OldValue!;
+ var newValue = (decimal)e.NewValue!;
upDown.OnMaximumChanged(oldValue, newValue);
}
}
@@ -790,8 +790,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (decimal)e.OldValue;
- var newValue = (decimal)e.NewValue;
+ var oldValue = (decimal)e.OldValue!;
+ var newValue = (decimal)e.NewValue!;
upDown.OnMinimumChanged(oldValue, newValue);
}
}
@@ -804,8 +804,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (string)e.OldValue;
- var newValue = (string)e.NewValue;
+ var oldValue = (string?)e.OldValue;
+ var newValue = (string?)e.NewValue;
upDown.OnTextChanged(oldValue, newValue);
}
}
@@ -818,8 +818,8 @@ namespace Avalonia.Controls
{
if (e.Sender is NumericUpDown upDown)
{
- var oldValue = (decimal)e.OldValue;
- var newValue = (decimal)e.NewValue;
+ var oldValue = (decimal)e.OldValue!;
+ var newValue = (decimal)e.NewValue!;
upDown.OnValueChanged(oldValue, newValue);
}
}
@@ -883,7 +883,7 @@ namespace Avalonia.Controls
}
}
- private void OnSpinnerSpin(object sender, SpinEventArgs e)
+ private void OnSpinnerSpin(object? sender, SpinEventArgs e)
{
if (AllowSpin && !IsReadOnly)
{
@@ -914,9 +914,9 @@ namespace Avalonia.Controls
}
}
- public event EventHandler Spinned;
+ public event EventHandler? Spinned;
- private void TextBoxOnPointerPressed(object sender, PointerPressedEventArgs e)
+ private void TextBoxOnPointerPressed(object? sender, PointerPressedEventArgs e)
{
if (e.Pointer.Captured != Spinner)
{
@@ -933,7 +933,7 @@ namespace Avalonia.Controls
///
/// Raised when the changes.
///
- public event EventHandler ValueChanged
+ public event EventHandler? ValueChanged
{
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
@@ -949,7 +949,7 @@ namespace Avalonia.Controls
///
/// If value should be updated from text.
/// The text.
- private bool SyncTextAndValueProperties(bool updateValueFromText, string text)
+ private bool SyncTextAndValueProperties(bool updateValueFromText, string? text)
{
return SyncTextAndValueProperties(updateValueFromText, text, false);
}
@@ -960,7 +960,7 @@ namespace Avalonia.Controls
/// If value should be updated from text.
/// The text.
/// Force text update.
- private bool SyncTextAndValueProperties(bool updateValueFromText, string text, bool forceTextUpdate)
+ private bool SyncTextAndValueProperties(bool updateValueFromText, string? text, bool forceTextUpdate)
{
if (_isSyncingTextAndValueProperties)
return true;
@@ -1092,7 +1092,7 @@ namespace Avalonia.Controls
///
/// Text to parse.
/// The culture info.
- private static decimal ParsePercent(string text, IFormatProvider cultureInfo)
+ private static decimal ParsePercent(string text, IFormatProvider? cultureInfo)
{
var info = NumberFormatInfo.GetInstance(cultureInfo);
text = text.Replace(info.PercentSymbol, null);
diff --git a/src/Avalonia.Controls/Panel.cs b/src/Avalonia.Controls/Panel.cs
index b182f9d261..482a7fab84 100644
--- a/src/Avalonia.Controls/Panel.cs
+++ b/src/Avalonia.Controls/Panel.cs
@@ -21,7 +21,7 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty BackgroundProperty =
+ public static readonly StyledProperty BackgroundProperty =
Border.BackgroundProperty.AddOwner();
///
@@ -32,7 +32,7 @@ namespace Avalonia.Controls
AffectsRender(BackgroundProperty);
}
- private EventHandler _childIndexChanged;
+ private EventHandler? _childIndexChanged;
///
/// Initializes a new instance of the class.
@@ -51,13 +51,13 @@ namespace Avalonia.Controls
///
/// Gets or Sets Panel background brush.
///
- public IBrush Background
+ public IBrush? Background
{
get { return GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
}
- event EventHandler IChildIndexProvider.ChildIndexChanged
+ event EventHandler? IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
@@ -110,34 +110,34 @@ namespace Avalonia.Controls
///
/// The event sender.
/// The event args.
- protected virtual void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
+ protected virtual void ChildrenChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
List controls;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
- controls = e.NewItems.OfType().ToList();
+ controls = e.NewItems!.OfType().ToList();
LogicalChildren.InsertRange(e.NewStartingIndex, controls);
- VisualChildren.InsertRange(e.NewStartingIndex, e.NewItems.OfType());
+ VisualChildren.InsertRange(e.NewStartingIndex, e.NewItems!.OfType());
break;
case NotifyCollectionChangedAction.Move:
- LogicalChildren.MoveRange(e.OldStartingIndex, e.OldItems.Count, e.NewStartingIndex);
+ LogicalChildren.MoveRange(e.OldStartingIndex, e.OldItems!.Count, e.NewStartingIndex);
VisualChildren.MoveRange(e.OldStartingIndex, e.OldItems.Count, e.NewStartingIndex);
break;
case NotifyCollectionChangedAction.Remove:
- controls = e.OldItems.OfType().ToList();
+ controls = e.OldItems!.OfType().ToList();
LogicalChildren.RemoveAll(controls);
- VisualChildren.RemoveAll(e.OldItems.OfType());
+ VisualChildren.RemoveAll(e.OldItems!.OfType());
break;
case NotifyCollectionChangedAction.Replace:
- for (var i = 0; i < e.OldItems.Count; ++i)
+ for (var i = 0; i < e.OldItems!.Count; ++i)
{
var index = i + e.OldStartingIndex;
- var child = (IControl)e.NewItems[i];
+ var child = (IControl)e.NewItems![i]!;
LogicalChildren[index] = child;
VisualChildren[index] = child;
}
diff --git a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
index 18348571bf..23ecdb2e7b 100644
--- a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
+++ b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
@@ -4,12 +4,11 @@ using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
+using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Threading;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Platform
{
///
@@ -68,8 +67,8 @@ namespace Avalonia.Controls.Platform
window.Deactivated += WindowDeactivated;
}
- if (_root is TopLevel tl)
- tl.PlatformImpl.LostFocus += TopLevelLostPlatformFocus;
+ if (_root is TopLevel tl && tl.PlatformImpl is ITopLevelImpl pimpl)
+ pimpl.LostFocus += TopLevelLostPlatformFocus;
_inputManagerSubscription = InputManager?.Process.Subscribe(RawInput);
}
@@ -118,7 +117,7 @@ namespace Avalonia.Controls.Platform
protected static TimeSpan MenuShowDelay { get; } = TimeSpan.FromMilliseconds(400);
- protected internal virtual void GotFocus(object sender, GotFocusEventArgs e)
+ protected internal virtual void GotFocus(object? sender, GotFocusEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
@@ -128,7 +127,7 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void LostFocus(object sender, RoutedEventArgs e)
+ protected internal virtual void LostFocus(object? sender, RoutedEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
@@ -138,7 +137,7 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void KeyDown(object sender, KeyEventArgs e)
+ protected internal virtual void KeyDown(object? sender, KeyEventArgs e)
{
KeyDown(GetMenuItem(e.Source as IControl), e);
}
@@ -267,7 +266,7 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void AccessKeyPressed(object sender, RoutedEventArgs e)
+ protected internal virtual void AccessKeyPressed(object? sender, RoutedEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
@@ -288,7 +287,7 @@ namespace Avalonia.Controls.Platform
e.Handled = true;
}
- protected internal virtual void PointerEnter(object sender, PointerEventArgs e)
+ protected internal virtual void PointerEnter(object? sender, PointerEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
@@ -333,7 +332,7 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void PointerLeave(object sender, PointerEventArgs e)
+ protected internal virtual void PointerLeave(object? sender, PointerEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
@@ -368,12 +367,12 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void PointerPressed(object sender, PointerPressedEventArgs e)
+ protected internal virtual void PointerPressed(object? sender, PointerPressedEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
- var visual = (IVisual)sender;
- if (e.GetCurrentPoint(visual).Properties.IsLeftButtonPressed && item?.HasSubMenu == true)
+ if (sender is IVisual visual &&
+ e.GetCurrentPoint(visual).Properties.IsLeftButtonPressed && item?.HasSubMenu == true)
{
if (item.IsSubMenuOpen)
{
@@ -399,7 +398,7 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void PointerReleased(object sender, PointerReleasedEventArgs e)
+ protected internal virtual void PointerReleased(object? sender, PointerReleasedEventArgs e)
{
var item = GetMenuItem(e.Source as IControl);
@@ -410,7 +409,7 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void MenuOpened(object sender, RoutedEventArgs e)
+ protected internal virtual void MenuOpened(object? sender, RoutedEventArgs e)
{
if (e.Source == Menu)
{
@@ -428,20 +427,18 @@ namespace Avalonia.Controls.Platform
}
}
- protected internal virtual void RootPointerPressed(object sender, PointerPressedEventArgs e)
+ protected internal virtual void RootPointerPressed(object? sender, PointerPressedEventArgs e)
{
if (Menu?.IsOpen == true)
{
- var control = e.Source as ILogical;
-
- if (!Menu.IsLogicalAncestorOf(control))
+ if (e.Source is ILogical control && !Menu.IsLogicalAncestorOf(control))
{
Menu.Close();
}
}
}
- protected internal virtual void WindowDeactivated(object sender, EventArgs e)
+ protected internal virtual void WindowDeactivated(object? sender, EventArgs e)
{
Menu?.Close();
}
diff --git a/src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs b/src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs
index e958b7aa15..2a401ad912 100644
--- a/src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs
+++ b/src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs
@@ -6,7 +6,7 @@ namespace Avalonia.Platform
public class ExportWindowingSubsystemAttribute : Attribute
{
public ExportWindowingSubsystemAttribute(OperatingSystemType requiredRuntimePlatform, int priority, string name, Type initializationType,
- string initializationMethod, Type environmentChecker = null)
+ string initializationMethod, Type? environmentChecker = null)
{
Name = name;
InitializationType = initializationType;
@@ -17,7 +17,7 @@ namespace Avalonia.Platform
}
public string InitializationMethod { get; private set; }
- public Type EnvironmentChecker { get; }
+ public Type? EnvironmentChecker { get; }
public Type InitializationType { get; private set; }
public string Name { get; private set; }
public int Priority { get; private set; }
diff --git a/src/Avalonia.Controls/Platform/INativeControlHostImpl.cs b/src/Avalonia.Controls/Platform/INativeControlHostImpl.cs
index c6b1d09849..df13613848 100644
--- a/src/Avalonia.Controls/Platform/INativeControlHostImpl.cs
+++ b/src/Avalonia.Controls/Platform/INativeControlHostImpl.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using Avalonia.Platform;
using Avalonia.VisualTree;
@@ -19,7 +20,8 @@ namespace Avalonia.Controls.Platform
public interface INativeControlHostControlTopLevelAttachment : IDisposable
{
- INativeControlHostImpl AttachedTo { get; set; }
+ INativeControlHostImpl? AttachedTo { get; set; }
+
bool IsCompatibleWith(INativeControlHostImpl host);
void HideWithSize(Size size);
void ShowInBounds(Rect rect);
@@ -27,6 +29,6 @@ namespace Avalonia.Controls.Platform
public interface ITopLevelImplWithNativeControlHost
{
- INativeControlHostImpl NativeControlHost { get; }
+ INativeControlHostImpl? NativeControlHost { get; }
}
}
diff --git a/src/Avalonia.Controls/Platform/ISystemDialogImpl.cs b/src/Avalonia.Controls/Platform/ISystemDialogImpl.cs
index 7bd13ecdb1..1685a6a38c 100644
--- a/src/Avalonia.Controls/Platform/ISystemDialogImpl.cs
+++ b/src/Avalonia.Controls/Platform/ISystemDialogImpl.cs
@@ -1,7 +1,5 @@
using System.Threading.Tasks;
-#nullable enable
-
namespace Avalonia.Controls.Platform
{
///
diff --git a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs
index f4f4d29168..80434882f7 100644
--- a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs
+++ b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs
@@ -82,27 +82,27 @@ namespace Avalonia.Platform
///
/// Gets or sets a method called when the toplevel receives input.
///
- Action Input { get; set; }
+ Action? Input { get; set; }
///
/// Gets or sets a method called when the toplevel requires painting.
///
- Action Paint { get; set; }
+ Action? Paint { get; set; }
///
/// Gets or sets a method called when the toplevel is resized.
///
- Action Resized { get; set; }
+ Action? Resized { get; set; }
///
/// Gets or sets a method called when the toplevel's scaling changes.
///
- Action ScalingChanged { get; set; }
+ Action? ScalingChanged { get; set; }
///
/// Gets or sets a method called when the toplevel's TransparencyLevel changes.
///
- Action TransparencyLevelChanged { get; set; }
+ Action? TransparencyLevelChanged { get; set; }
///
/// Creates a new renderer for the toplevel.
@@ -138,17 +138,17 @@ namespace Avalonia.Platform
/// Sets the cursor associated with the toplevel.
///
/// The cursor. Use null for default cursor
- void SetCursor(ICursorImpl cursor);
+ void SetCursor(ICursorImpl? cursor);
///
/// Gets or sets a method called when the underlying implementation is destroyed.
///
- Action Closed { get; set; }
+ Action? Closed { get; set; }
///
/// Gets or sets a method called when the input focus is lost.
///
- Action LostFocus { get; set; }
+ Action? LostFocus { get; set; }
///
/// Gets a mouse device associated with toplevel
@@ -156,7 +156,7 @@ namespace Avalonia.Platform
[CanBeNull]
IMouseDevice MouseDevice { get; }
- IPopupImpl CreatePopup();
+ IPopupImpl? CreatePopup();
///
/// Sets the hint of the TopLevel.
diff --git a/src/Avalonia.Controls/Platform/ITopLevelImplWithTextInputMethod.cs b/src/Avalonia.Controls/Platform/ITopLevelImplWithTextInputMethod.cs
index 9c29415a6a..bafb973765 100644
--- a/src/Avalonia.Controls/Platform/ITopLevelImplWithTextInputMethod.cs
+++ b/src/Avalonia.Controls/Platform/ITopLevelImplWithTextInputMethod.cs
@@ -6,6 +6,6 @@ namespace Avalonia.Controls.Platform
{
public interface ITopLevelImplWithTextInputMethod : ITopLevelImpl
{
- public ITextInputMethodImpl TextInputMethod { get; }
+ public ITextInputMethodImpl? TextInputMethod { get; }
}
}
diff --git a/src/Avalonia.Controls/Platform/ITopLevelNativeMenuExporter.cs b/src/Avalonia.Controls/Platform/ITopLevelNativeMenuExporter.cs
index 9b779054f3..9e72a40439 100644
--- a/src/Avalonia.Controls/Platform/ITopLevelNativeMenuExporter.cs
+++ b/src/Avalonia.Controls/Platform/ITopLevelNativeMenuExporter.cs
@@ -1,8 +1,6 @@
using System;
using Avalonia.Platform;
-#nullable enable
-
namespace Avalonia.Controls.Platform
{
public interface INativeMenuExporter
@@ -24,6 +22,6 @@ namespace Avalonia.Controls.Platform
public interface ITopLevelImplWithNativeMenuExporter : ITopLevelImpl
{
- ITopLevelNativeMenuExporter NativeMenuExporter { get; }
+ ITopLevelNativeMenuExporter? NativeMenuExporter { get; }
}
}
diff --git a/src/Avalonia.Controls/Platform/ITrayIconImpl.cs b/src/Avalonia.Controls/Platform/ITrayIconImpl.cs
index 9768d149f0..289b569645 100644
--- a/src/Avalonia.Controls/Platform/ITrayIconImpl.cs
+++ b/src/Avalonia.Controls/Platform/ITrayIconImpl.cs
@@ -1,8 +1,6 @@
using System;
using Avalonia.Controls.Platform;
-#nullable enable
-
namespace Avalonia.Platform
{
public interface ITrayIconImpl : IDisposable
diff --git a/src/Avalonia.Controls/Platform/IWindowBaseImpl.cs b/src/Avalonia.Controls/Platform/IWindowBaseImpl.cs
index 5172569726..ff83e007b4 100644
--- a/src/Avalonia.Controls/Platform/IWindowBaseImpl.cs
+++ b/src/Avalonia.Controls/Platform/IWindowBaseImpl.cs
@@ -29,7 +29,7 @@ namespace Avalonia.Platform
///
/// Gets or sets a method called when the window's position changes.
///
- Action PositionChanged { get; set; }
+ Action? PositionChanged { get; set; }
///
/// Activates the window.
@@ -39,12 +39,12 @@ namespace Avalonia.Platform
///
/// Gets or sets a method called when the window is deactivated (loses focus).
///
- Action Deactivated { get; set; }
+ Action? Deactivated { get; set; }
///
/// Gets or sets a method called when the window is activated (receives focus).
///
- Action Activated { get; set; }
+ Action? Activated { get; set; }
///
/// Gets the platform window handle.
diff --git a/src/Avalonia.Controls/Platform/IWindowImpl.cs b/src/Avalonia.Controls/Platform/IWindowImpl.cs
index 17a90eddfe..d4be4f9f45 100644
--- a/src/Avalonia.Controls/Platform/IWindowImpl.cs
+++ b/src/Avalonia.Controls/Platform/IWindowImpl.cs
@@ -23,7 +23,7 @@ namespace Avalonia.Platform
/// Sets the title of the window.
///
/// The title.
- void SetTitle(string title);
+ void SetTitle(string? title);
///
/// Sets the parent of the window.
@@ -50,7 +50,7 @@ namespace Avalonia.Platform
///
/// Sets the icon of this window.
///
- void SetIcon(IWindowIconImpl icon);
+ void SetIcon(IWindowIconImpl? icon);
///
/// Enables or disables the taskbar icon
diff --git a/src/Avalonia.Controls/Platform/IWindowingPlatform.cs b/src/Avalonia.Controls/Platform/IWindowingPlatform.cs
index 21882b1271..fa26fe8fdd 100644
--- a/src/Avalonia.Controls/Platform/IWindowingPlatform.cs
+++ b/src/Avalonia.Controls/Platform/IWindowingPlatform.cs
@@ -1,5 +1,3 @@
-#nullable enable
-
namespace Avalonia.Platform
{
public interface IWindowingPlatform
diff --git a/src/Avalonia.Controls/Platform/InProcessDragSource.cs b/src/Avalonia.Controls/Platform/InProcessDragSource.cs
index 414c523e0d..209d5f03dc 100644
--- a/src/Avalonia.Controls/Platform/InProcessDragSource.cs
+++ b/src/Avalonia.Controls/Platform/InProcessDragSource.cs
@@ -20,17 +20,17 @@ namespace Avalonia.Platform
private readonly Subject _result = new Subject();
private DragDropEffects _allowedEffects;
- private IDataObject _draggedData;
- private IInputRoot _lastRoot;
+ private IDataObject? _draggedData;
+ private IInputRoot? _lastRoot;
private Point _lastPosition;
private StandardCursorType _lastCursorType;
- private object _originalCursor;
+ private object? _originalCursor;
private RawInputModifiers? _initialInputModifiers;
public InProcessDragSource()
{
- _inputManager = AvaloniaLocator.Current.GetService();
- _dragDrop = AvaloniaLocator.Current.GetService();
+ _inputManager = AvaloniaLocator.Current.GetRequiredService();
+ _dragDrop = AvaloniaLocator.Current.GetRequiredService();
}
public async Task DoDragDrop(PointerEventArgs triggerEvent, IDataObject data, DragDropEffects allowedEffects)
@@ -60,9 +60,9 @@ namespace Avalonia.Platform
{
_lastPosition = pt;
- RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData, _allowedEffects, modifiers);
+ RawDragEvent rawEvent = new RawDragEvent(_dragDrop, type, root, pt, _draggedData!, _allowedEffects, modifiers);
var tl = root.GetSelfAndVisualAncestors().OfType().FirstOrDefault();
- tl.PlatformImpl?.Input(rawEvent);
+ tl?.PlatformImpl?.Input?.Invoke(rawEvent);
var effect = GetPreferredEffect(rawEvent.Effects & _allowedEffects, modifiers);
UpdateCursor(root, effect);
@@ -91,7 +91,7 @@ namespace Avalonia.Platform
return StandardCursorType.No;
}
- private void UpdateCursor(IInputRoot root, DragDropEffects effect)
+ private void UpdateCursor(IInputRoot? root, DragDropEffects effect)
{
if (_lastRoot != root)
{
diff --git a/src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs b/src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs
index 6a95c2e047..4e5908456e 100644
--- a/src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs
+++ b/src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs
@@ -36,7 +36,7 @@ namespace Avalonia.Controls.Platform
private readonly DispatcherPriority _priority;
private readonly TimeSpan _interval;
private readonly Action _tick;
- private Timer _timer;
+ private Timer? _timer;
private GCHandle _handle;
public TimerImpl(DispatcherPriority priority, TimeSpan interval, Action tick)
@@ -48,7 +48,7 @@ namespace Avalonia.Controls.Platform
_handle = GCHandle.Alloc(_timer);
}
- private void OnTimer(object state)
+ private void OnTimer(object? state)
{
if (_timer == null)
return;
@@ -66,7 +66,7 @@ namespace Avalonia.Controls.Platform
public void Dispose()
{
_handle.Free();
- _timer.Dispose();
+ _timer?.Dispose();
_timer = null;
}
}
@@ -84,9 +84,9 @@ namespace Avalonia.Controls.Platform
[ThreadStatic] private static bool TlsCurrentThreadIsLoopThread;
public bool CurrentThreadIsLoopThread => TlsCurrentThreadIsLoopThread;
- public event Action Signaled;
+ public event Action? Signaled;
#pragma warning disable CS0067
- public event Action Tick;
+ public event Action? Tick;
#pragma warning restore CS0067
}
diff --git a/src/Avalonia.Controls/Platform/MountedDriveInfo.cs b/src/Avalonia.Controls/Platform/MountedDriveInfo.cs
index 9448f16c38..f3104e4360 100644
--- a/src/Avalonia.Controls/Platform/MountedDriveInfo.cs
+++ b/src/Avalonia.Controls/Platform/MountedDriveInfo.cs
@@ -7,14 +7,14 @@ namespace Avalonia.Controls.Platform
///
public class MountedVolumeInfo : IEquatable
{
- public string VolumeLabel { get; set; }
- public string VolumePath { get; set; }
+ public string? VolumeLabel { get; set; }
+ public string? VolumePath { get; set; }
public ulong VolumeSizeBytes { get; set; }
- public bool Equals(MountedVolumeInfo other)
+ public bool Equals(MountedVolumeInfo? other)
{
- return this.VolumeSizeBytes.Equals(other.VolumeSizeBytes) &&
- this.VolumePath.Equals(other.VolumePath) &&
+ return this.VolumeSizeBytes.Equals(other?.VolumeSizeBytes) &&
+ Equals(this.VolumePath, other.VolumePath) &&
(this.VolumeLabel ?? string.Empty).Equals(other.VolumeLabel ?? string.Empty);
}
}
diff --git a/src/Avalonia.Controls/Platform/PlatformManager.cs b/src/Avalonia.Controls/Platform/PlatformManager.cs
index 8e9f64b3ad..ee62316922 100644
--- a/src/Avalonia.Controls/Platform/PlatformManager.cs
+++ b/src/Avalonia.Controls/Platform/PlatformManager.cs
@@ -2,8 +2,6 @@ using System;
using System.Reactive.Disposables;
using Avalonia.Platform;
-#nullable enable
-
namespace Avalonia.Controls.Platform
{
public static partial class PlatformManager
diff --git a/src/Avalonia.Controls/Presenters/CarouselPresenter.cs b/src/Avalonia.Controls/Presenters/CarouselPresenter.cs
index 81f43865a7..3d1e7eb5a8 100644
--- a/src/Avalonia.Controls/Presenters/CarouselPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/CarouselPresenter.cs
@@ -35,7 +35,7 @@ namespace Avalonia.Controls.Presenters
Carousel.PageTransitionProperty.AddOwner();
private int _selectedIndex = -1;
- private Task _currentTransition;
+ private Task? _currentTransition;
private int _queuedTransitionIndex = -1;
///
@@ -126,7 +126,7 @@ namespace Avalonia.Controls.Presenters
break;
case NotifyCollectionChangedAction.Replace:
if (e.OldStartingIndex > SelectedIndex ||
- e.OldStartingIndex + e.OldItems.Count - 1 < SelectedIndex)
+ e.OldStartingIndex + e.OldItems!.Count - 1 < SelectedIndex)
{
return;
}
@@ -171,12 +171,12 @@ namespace Avalonia.Controls.Presenters
if (fromIndex != toIndex)
{
var generator = ItemContainerGenerator;
- IControl from = null;
- IControl to = null;
+ IControl? from = null;
+ IControl? to = null;
if (fromIndex != -1)
{
- from = ItemContainerGenerator.ContainerFromIndex(fromIndex);
+ from = generator.ContainerFromIndex(fromIndex);
}
if (toIndex != -1)
@@ -186,7 +186,7 @@ namespace Avalonia.Controls.Presenters
if (PageTransition != null && (from != null || to != null))
{
- await PageTransition.Start((Visual)from, (Visual)to, fromIndex < toIndex, default);
+ await PageTransition.Start((Visual?)from, (Visual?)to, fromIndex < toIndex, default);
}
else if (to != null)
{
@@ -197,7 +197,7 @@ namespace Avalonia.Controls.Presenters
{
if (IsVirtualized)
{
- Panel.Children.Remove(from);
+ Panel!.Children.Remove(from);
generator.Dematerialize(fromIndex, 1);
}
else
@@ -208,15 +208,15 @@ namespace Avalonia.Controls.Presenters
}
}
- private IControl GetOrCreateContainer(int index)
+ private IControl? GetOrCreateContainer(int index)
{
var container = ItemContainerGenerator.ContainerFromIndex(index);
if (container == null && IsVirtualized)
{
- var item = Items.Cast().ElementAt(index);
+ var item = Items!.Cast().ElementAt(index);
var materialized = ItemContainerGenerator.Materialize(index, item);
- Panel.Children.Add(materialized.ContainerControl);
+ Panel!.Children.Add(materialized.ContainerControl);
container = materialized.ContainerControl;
}
@@ -245,8 +245,8 @@ namespace Avalonia.Controls.Presenters
{
if (_currentTransition == null)
{
- int fromIndex = (int)e.OldValue;
- int toIndex = (int)e.NewValue;
+ int fromIndex = (int)e.OldValue!;
+ int toIndex = (int)e.NewValue!;
for (;;)
{
@@ -268,7 +268,7 @@ namespace Avalonia.Controls.Presenters
}
else
{
- _queuedTransitionIndex = (int)e.NewValue;
+ _queuedTransitionIndex = (int)e.NewValue!;
}
}
}
diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs
index 1a46d84558..9886dd913a 100644
--- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs
@@ -20,13 +20,13 @@ namespace Avalonia.Controls.Presenters
///
/// Defines the property.
///
- public static readonly StyledProperty BackgroundProperty =
+ public static readonly StyledProperty BackgroundProperty =
Border.BackgroundProperty.AddOwner();
///
/// Defines the property.
///
- public static readonly StyledProperty BorderBrushProperty =
+ public static readonly StyledProperty BorderBrushProperty =
Border.BorderBrushProperty.AddOwner();
///
@@ -50,21 +50,21 @@ namespace Avalonia.Controls.Presenters
///
/// Defines the property.
///
- public static readonly DirectProperty ChildProperty =
- AvaloniaProperty.RegisterDirect(
+ public static readonly DirectProperty ChildProperty =
+ AvaloniaProperty.RegisterDirect(
nameof(Child),
o => o.Child);
///
/// Defines the property.
///
- public static readonly StyledProperty ContentProperty =
+ public static readonly StyledProperty ContentProperty =
ContentControl.ContentProperty.AddOwner();
///
/// Defines the property.
///
- public static readonly StyledProperty ContentTemplateProperty =
+ public static readonly StyledProperty ContentTemplateProperty =
ContentControl.ContentTemplateProperty.AddOwner();
///
@@ -93,9 +93,9 @@ namespace Avalonia.Controls.Presenters
nameof(RecognizesAccessKey),
cp => cp.RecognizesAccessKey, (cp, value) => cp.RecognizesAccessKey = value);
- private IControl _child;
+ private IControl? _child;
private bool _createdChild;
- private IRecyclingDataTemplate _recyclingDataTemplate;
+ private IRecyclingDataTemplate? _recyclingDataTemplate;
private readonly BorderRenderHelper _borderRenderer = new BorderRenderHelper();
private bool _recognizesAccessKey;
@@ -120,7 +120,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets a brush with which to paint the background.
///
- public IBrush Background
+ public IBrush? Background
{
get { return GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
@@ -129,7 +129,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets a brush with which to paint the border.
///
- public IBrush BorderBrush
+ public IBrush? BorderBrush
{
get { return GetValue(BorderBrushProperty); }
set { SetValue(BorderBrushProperty, value); }
@@ -165,7 +165,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets the control displayed by the presenter.
///
- public IControl Child
+ public IControl? Child
{
get { return _child; }
private set { SetAndRaise(ChildProperty, ref _child, value); }
@@ -175,7 +175,7 @@ namespace Avalonia.Controls.Presenters
/// Gets or sets the content to be displayed by the presenter.
///
[DependsOn(nameof(ContentTemplate))]
- public object Content
+ public object? Content
{
get { return GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
@@ -184,7 +184,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets the data template used to display the content of the control.
///
- public IDataTemplate ContentTemplate
+ public IDataTemplate? ContentTemplate
{
get { return GetValue(ContentTemplateProperty); }
set { SetValue(ContentTemplateProperty, value); }
@@ -229,7 +229,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets the host content control.
///
- internal IContentPresenterHost Host { get; private set; }
+ internal IContentPresenterHost? Host { get; private set; }
///
public sealed override void ApplyTemplate()
@@ -321,7 +321,7 @@ namespace Avalonia.Controls.Presenters
/// Creates the child control.
///
/// The child control or null.
- protected virtual IControl CreateChild()
+ protected virtual IControl? CreateChild()
{
var content = Content;
var oldChild = Child;
diff --git a/src/Avalonia.Controls/Presenters/IContentPresenter.cs b/src/Avalonia.Controls/Presenters/IContentPresenter.cs
index b1e64c2f25..ab4d61e3bd 100644
--- a/src/Avalonia.Controls/Presenters/IContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/IContentPresenter.cs
@@ -11,11 +11,11 @@ namespace Avalonia.Controls.Presenters
///
/// Gets the control displayed by the presenter.
///
- IControl Child { get; }
+ IControl? Child { get; }
///
/// Gets or sets the content to be displayed by the presenter.
///
- object Content { get; set; }
+ object? Content { get; set; }
}
}
diff --git a/src/Avalonia.Controls/Presenters/IItemsPresenter.cs b/src/Avalonia.Controls/Presenters/IItemsPresenter.cs
index 873f0d756f..e7da3d4618 100644
--- a/src/Avalonia.Controls/Presenters/IItemsPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/IItemsPresenter.cs
@@ -5,9 +5,9 @@ namespace Avalonia.Controls.Presenters
{
public interface IItemsPresenter : IPresenter
{
- IEnumerable Items { get; set; }
+ IEnumerable? Items { get; set; }
- IPanel Panel { get; }
+ IPanel? Panel { get; }
void ItemsChanged(NotifyCollectionChangedEventArgs e);
diff --git a/src/Avalonia.Controls/Presenters/ItemContainerSync.cs b/src/Avalonia.Controls/Presenters/ItemContainerSync.cs
index 6e72908e6b..81184f719e 100644
--- a/src/Avalonia.Controls/Presenters/ItemContainerSync.cs
+++ b/src/Avalonia.Controls/Presenters/ItemContainerSync.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Controls.Presenters
{
public static void ItemsChanged(
ItemsPresenterBase owner,
- IEnumerable items,
+ IEnumerable? items,
NotifyCollectionChangedEventArgs e)
{
var generator = owner.ItemContainerGenerator;
@@ -24,7 +24,7 @@ namespace Avalonia.Controls.Presenters
void Add()
{
- if (e.NewStartingIndex + e.NewItems.Count < items.Count())
+ if (e.NewStartingIndex + e.NewItems!.Count < items!.Count())
{
generator.InsertSpace(e.NewStartingIndex, e.NewItems.Count);
}
@@ -34,7 +34,7 @@ namespace Avalonia.Controls.Presenters
void Remove()
{
- RemoveContainers(panel, generator.RemoveRange(e.OldStartingIndex, e.OldItems.Count));
+ RemoveContainers(panel, generator.RemoveRange(e.OldStartingIndex, e.OldItems!.Count));
}
switch (e.Action)
@@ -48,8 +48,8 @@ namespace Avalonia.Controls.Presenters
break;
case NotifyCollectionChangedAction.Replace:
- RemoveContainers(panel, generator.Dematerialize(e.OldStartingIndex, e.OldItems.Count));
- var containers = AddContainers(owner, e.NewStartingIndex, e.NewItems);
+ RemoveContainers(panel, generator.Dematerialize(e.OldStartingIndex, e.OldItems!.Count));
+ var containers = AddContainers(owner, e.NewStartingIndex, e.NewItems!);
var i = e.NewStartingIndex;
@@ -92,7 +92,7 @@ namespace Avalonia.Controls.Presenters
if (i.ContainerControl != null)
{
- if (i.Index < panel.Children.Count)
+ if (i.Index < panel!.Children.Count)
{
// TODO: This will insert at the wrong place when there are null items.
panel.Children.Insert(i.Index, i.ContainerControl);
diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizer.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizer.cs
index be2b1e86f0..343c72f742 100644
--- a/src/Avalonia.Controls/Presenters/ItemVirtualizer.cs
+++ b/src/Avalonia.Controls/Presenters/ItemVirtualizer.cs
@@ -16,7 +16,7 @@ namespace Avalonia.Controls.Presenters
internal abstract class ItemVirtualizer : IVirtualizingController, IDisposable
{
private double _crossAxisOffset;
- private IDisposable _subscriptions;
+ private IDisposable? _subscriptions;
///
/// Initializes a new instance of the class.
@@ -46,12 +46,12 @@ namespace Avalonia.Controls.Presenters
///
/// Gets the which will host the items.
///
- public IVirtualizingPanel VirtualizingPanel => Owner.Panel as IVirtualizingPanel;
+ public IVirtualizingPanel? VirtualizingPanel => Owner.Panel as IVirtualizingPanel;
///
/// Gets the items to display.
///
- public IEnumerable Items { get; private set; }
+ public IEnumerable? Items { get; private set; }
///
/// Gets the number of items in .
@@ -100,11 +100,11 @@ namespace Avalonia.Controls.Presenters
{
get
{
- if (IsLogicalScrollEnabled)
+ if (IsLogicalScrollEnabled && Owner.Panel is Panel panel)
{
return Vertical ?
- new Size(Owner.Panel.DesiredSize.Width, ExtentValue) :
- new Size(ExtentValue, Owner.Panel.DesiredSize.Height);
+ new Size(panel.DesiredSize.Width, ExtentValue) :
+ new Size(ExtentValue, panel.DesiredSize.Height);
}
return default;
@@ -118,11 +118,11 @@ namespace Avalonia.Controls.Presenters
{
get
{
- if (IsLogicalScrollEnabled)
+ if (IsLogicalScrollEnabled && Owner.Panel is Panel panel)
{
return Vertical ?
- new Size(Owner.Panel.Bounds.Width, ViewportValue) :
- new Size(ViewportValue, Owner.Panel.Bounds.Height);
+ new Size(panel.Bounds.Width, ViewportValue) :
+ new Size(ViewportValue, panel.Bounds.Height);
}
return default;
@@ -177,7 +177,7 @@ namespace Avalonia.Controls.Presenters
///
/// The items presenter.
/// An .
- public static ItemVirtualizer Create(ItemsPresenter owner)
+ public static ItemVirtualizer? Create(ItemsPresenter owner)
{
if (owner.Panel == null)
{
@@ -186,7 +186,7 @@ namespace Avalonia.Controls.Presenters
var virtualizingPanel = owner.Panel as IVirtualizingPanel;
var scrollContentPresenter = owner.Parent as IScrollable;
- ItemVirtualizer result = null;
+ ItemVirtualizer? result = null;
if (virtualizingPanel != null && scrollContentPresenter is object)
{
@@ -218,7 +218,7 @@ namespace Avalonia.Controls.Presenters
/// The desired size for the control.
public virtual Size MeasureOverride(Size availableSize)
{
- Owner.Panel.Measure(availableSize);
+ Owner.Panel!.Measure(availableSize);
return Owner.Panel.DesiredSize;
}
@@ -232,12 +232,12 @@ namespace Avalonia.Controls.Presenters
if (VirtualizingPanel != null)
{
VirtualizingPanel.CrossAxisOffset = _crossAxisOffset;
- Owner.Panel.Arrange(new Rect(finalSize));
+ Owner.Panel!.Arrange(new Rect(finalSize));
}
else
{
var origin = Vertical ? new Point(-_crossAxisOffset, 0) : new Point(0, _crossAxisOffset);
- Owner.Panel.Arrange(new Rect(origin, finalSize));
+ Owner.Panel!.Arrange(new Rect(origin, finalSize));
}
return finalSize;
@@ -254,7 +254,7 @@ namespace Avalonia.Controls.Presenters
/// The movement direction.
/// The control from which movement begins.
/// The control.
- public virtual IControl GetControlInDirection(NavigationDirection direction, IControl from)
+ public virtual IControl? GetControlInDirection(NavigationDirection direction, IControl from)
{
return null;
}
@@ -266,10 +266,10 @@ namespace Avalonia.Controls.Presenters
///
/// The items.
/// A description of the change.
- public virtual void ItemsChanged(IEnumerable items, NotifyCollectionChangedEventArgs e)
+ public virtual void ItemsChanged(IEnumerable? items, NotifyCollectionChangedEventArgs e)
{
Items = items;
- ItemCount = items.Count();
+ ItemCount = items?.Count() ?? 0;
}
///
diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs
index 275f4d418e..c1b6842b88 100644
--- a/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs
+++ b/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs
@@ -54,7 +54,7 @@ namespace Avalonia.Controls.Presenters
}
///
- public override void ItemsChanged(IEnumerable items, NotifyCollectionChangedEventArgs e)
+ public override void ItemsChanged(IEnumerable? items, NotifyCollectionChangedEventArgs e)
{
base.ItemsChanged(items, e);
ItemContainerSync.ItemsChanged(Owner, items, e);
@@ -86,7 +86,7 @@ namespace Avalonia.Controls.Presenters
if (i.ContainerControl != null)
{
- if (i.Index < panel.Children.Count)
+ if (i.Index < panel!.Children.Count)
{
// TODO: This will insert at the wrong place when there are null items.
panel.Children.Insert(i.Index, i.ContainerControl);
@@ -102,18 +102,5 @@ namespace Avalonia.Controls.Presenters
return result;
}
-
- private void RemoveContainers(IEnumerable items)
- {
- var panel = Owner.Panel;
-
- foreach (var i in items)
- {
- if (i.ContainerControl != null)
- {
- panel.Children.Remove(i.ContainerControl);
- }
- }
- }
}
}
diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
index 7d50ef7d33..361febf305 100644
--- a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
+++ b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
@@ -108,6 +108,8 @@ namespace Avalonia.Controls.Presenters
}
}
+ public new IVirtualizingPanel VirtualizingPanel => base.VirtualizingPanel!;
+
///
public override Size MeasureOverride(Size availableSize)
{
@@ -151,7 +153,7 @@ namespace Avalonia.Controls.Presenters
}
}
- Owner.Panel.Measure(availableSize);
+ Owner.Panel!.Measure(availableSize);
return Owner.Panel.DesiredSize;
}
@@ -163,7 +165,7 @@ namespace Avalonia.Controls.Presenters
}
///
- public override void ItemsChanged(IEnumerable items, NotifyCollectionChangedEventArgs e)
+ public override void ItemsChanged(IEnumerable? items, NotifyCollectionChangedEventArgs e)
{
base.ItemsChanged(items, e);
@@ -224,18 +226,13 @@ namespace Avalonia.Controls.Presenters
InvalidateScroll();
}
- public override IControl GetControlInDirection(NavigationDirection direction, IControl from)
+ public override IControl? GetControlInDirection(NavigationDirection direction, IControl from)
{
var generator = Owner.ItemContainerGenerator;
var panel = VirtualizingPanel;
var itemIndex = generator.IndexFromContainer(from);
var vertical = VirtualizingPanel.ScrollDirection == Orientation.Vertical;
- if (itemIndex == -1)
- {
- return null;
- }
-
var newItemIndex = -1;
switch (direction)
@@ -248,6 +245,16 @@ namespace Avalonia.Controls.Presenters
newItemIndex = ItemCount - 1;
break;
+ default:
+ if (itemIndex == -1)
+ {
+ return null;
+ }
+ break;
+ }
+
+ switch (direction)
+ {
case NavigationDirection.Up:
if (vertical)
{
@@ -331,7 +338,7 @@ namespace Avalonia.Controls.Presenters
}
}
- var materialized = generator.Materialize(index, Items.ElementAt(index));
+ var materialized = generator.Materialize(index, Items.ElementAt(index)!);
if (step == 1)
{
@@ -382,7 +389,7 @@ namespace Avalonia.Controls.Presenters
foreach (var container in containers)
{
- var item = Items.ElementAt(itemIndex);
+ var item = Items!.ElementAt(itemIndex)!;
if (!object.Equals(container.Item, item))
{
@@ -427,7 +434,7 @@ namespace Avalonia.Controls.Presenters
var oldItemIndex = FirstIndex + first + i;
var newItemIndex = oldItemIndex + delta + ((panel.Children.Count - count) * sign);
- var item = Items.ElementAt(newItemIndex);
+ var item = Items!.ElementAt(newItemIndex)!;
if (!generator.TryRecycle(oldItemIndex, newItemIndex, item))
{
@@ -506,7 +513,7 @@ namespace Avalonia.Controls.Presenters
///
/// The item index.
/// The container that was brought into view.
- private IControl ScrollIntoViewCore(int index)
+ private IControl? ScrollIntoViewCore(int index)
{
var panel = VirtualizingPanel;
var generator = Owner.ItemContainerGenerator;
diff --git a/src/Avalonia.Controls/Presenters/ItemsPresenter.cs b/src/Avalonia.Controls/Presenters/ItemsPresenter.cs
index 80c9e972d5..2c04b03faf 100644
--- a/src/Avalonia.Controls/Presenters/ItemsPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ItemsPresenter.cs
@@ -21,7 +21,7 @@ namespace Avalonia.Controls.Presenters
private bool _canHorizontallyScroll;
private bool _canVerticallyScroll;
- private EventHandler _scrollInvalidated;
+ private EventHandler? _scrollInvalidated;
///
/// Initializes static members of the class.
@@ -96,7 +96,7 @@ namespace Avalonia.Controls.Presenters
Size IScrollable.Viewport => Virtualizer?.Viewport ?? Bounds.Size;
///
- event EventHandler ILogicalScrollable.ScrollInvalidated
+ event EventHandler? ILogicalScrollable.ScrollInvalidated
{
add => _scrollInvalidated += value;
remove => _scrollInvalidated -= value;
@@ -108,7 +108,7 @@ namespace Avalonia.Controls.Presenters
///
Size ILogicalScrollable.PageScrollSize => Virtualizer?.Viewport ?? new Size(16, 16);
- internal ItemVirtualizer Virtualizer { get; private set; }
+ internal ItemVirtualizer? Virtualizer { get; private set; }
///
bool ILogicalScrollable.BringIntoView(IControl target, Rect targetRect)
@@ -117,7 +117,7 @@ namespace Avalonia.Controls.Presenters
}
///
- IControl ILogicalScrollable.GetControlInDirection(NavigationDirection direction, IControl from)
+ IControl? ILogicalScrollable.GetControlInDirection(NavigationDirection direction, IControl from)
{
return Virtualizer?.GetControlInDirection(direction, from);
}
@@ -152,7 +152,7 @@ namespace Avalonia.Controls.Presenters
_scrollInvalidated?.Invoke(this, EventArgs.Empty);
KeyboardNavigation.SetTabNavigation(
- (InputElement)Panel,
+ (InputElement)panel,
KeyboardNavigation.GetTabNavigation(this));
}
diff --git a/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs b/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs
index aeead7bfd0..f938c8d437 100644
--- a/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs
+++ b/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs
@@ -18,7 +18,7 @@ namespace Avalonia.Controls.Presenters
///
/// Defines the property.
///
- public static readonly DirectProperty ItemsProperty =
+ public static readonly DirectProperty ItemsProperty =
ItemsControl.ItemsProperty.AddOwner(o => o.Items, (o, v) => o.Items = v);
///
@@ -30,14 +30,14 @@ namespace Avalonia.Controls.Presenters
///
/// Defines the property.
///
- public static readonly StyledProperty ItemTemplateProperty =
+ public static readonly StyledProperty ItemTemplateProperty =
ItemsControl.ItemTemplateProperty.AddOwner();
- private IEnumerable _items;
- private IDisposable _itemsSubscription;
+ private IEnumerable? _items;
+ private IDisposable? _itemsSubscription;
private bool _createdPanel;
- private IItemContainerGenerator _generator;
- private EventHandler _childIndexChanged;
+ private IItemContainerGenerator? _generator;
+ private EventHandler? _childIndexChanged;
///
/// Initializes static members of the class.
@@ -50,7 +50,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets the items to be displayed.
///
- public IEnumerable Items
+ public IEnumerable? Items
{
get
{
@@ -114,7 +114,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets the data template used to display the items in the control.
///
- public IDataTemplate ItemTemplate
+ public IDataTemplate? ItemTemplate
{
get { return GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
@@ -123,7 +123,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets the panel used to display the items.
///
- public IPanel Panel
+ public IPanel? Panel
{
get;
private set;
@@ -131,7 +131,7 @@ namespace Avalonia.Controls.Presenters
protected bool IsHosted => TemplatedParent is IItemsPresenterHost;
- event EventHandler IChildIndexProvider.ChildIndexChanged
+ event EventHandler? IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
@@ -186,7 +186,7 @@ namespace Avalonia.Controls.Presenters
return result;
}
- private void ContainerActionHandler(object sender, ItemContainerEventArgs e)
+ private void ContainerActionHandler(object? sender, ItemContainerEventArgs e)
{
for (var i = 0; i < e.Containers.Count; i++)
{
@@ -197,14 +197,14 @@ namespace Avalonia.Controls.Presenters
///
protected override Size MeasureOverride(Size availableSize)
{
- Panel.Measure(availableSize);
+ Panel!.Measure(availableSize);
return Panel.DesiredSize;
}
///
protected override Size ArrangeOverride(Size finalSize)
{
- Panel.Arrange(new Rect(finalSize));
+ Panel!.Arrange(new Rect(finalSize));
return finalSize;
}
@@ -258,7 +258,7 @@ namespace Avalonia.Controls.Presenters
///
/// The sender.
/// The event args.
- private void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void ItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (_createdPanel)
{
diff --git a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
index a62ba306ab..97fb4c3f43 100644
--- a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
@@ -7,8 +7,6 @@ using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Presenters
{
///
@@ -60,6 +58,12 @@ namespace Avalonia.Controls.Presenters
o => o.Viewport,
(o, v) => o.Viewport = v);
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty IsScrollChainingEnabledProperty =
+ ScrollViewer.IsScrollChainingEnabledProperty.AddOwner();
+
private bool _canHorizontallyScroll;
private bool _canVerticallyScroll;
private bool _arranging;
@@ -138,6 +142,20 @@ namespace Avalonia.Controls.Presenters
private set { SetAndRaise(ViewportProperty, ref _viewport, value); }
}
+ ///
+ /// Gets or sets if scroll chaining is enabled. The default value is true.
+ ///
+ ///
+ /// After a user hits a scroll limit on an element that has been nested within another scrollable element,
+ /// you can specify whether that parent element should continue the scrolling operation begun in its child element.
+ /// This is called scroll chaining.
+ ///
+ public bool IsScrollChainingEnabled
+ {
+ get => GetValue(IsScrollChainingEnabledProperty);
+ set => SetValue(IsScrollChainingEnabledProperty, value);
+ }
+
///
IControl? IScrollAnchorProvider.CurrentAnchor
{
@@ -268,8 +286,8 @@ namespace Avalonia.Controls.Presenters
private Size ArrangeWithAnchoring(Size finalSize)
{
var size = new Size(
- CanHorizontallyScroll ? Math.Max(Child.DesiredSize.Width, finalSize.Width) : finalSize.Width,
- CanVerticallyScroll ? Math.Max(Child.DesiredSize.Height, finalSize.Height) : finalSize.Height);
+ CanHorizontallyScroll ? Math.Max(Child!.DesiredSize.Width, finalSize.Width) : finalSize.Width,
+ CanVerticallyScroll ? Math.Max(Child!.DesiredSize.Height, finalSize.Height) : finalSize.Height);
Vector TrackAnchor()
{
@@ -277,7 +295,7 @@ namespace Avalonia.Controls.Presenters
// arrange then that change wasn't just due to scrolling (as scrolling doesn't adjust
// relative positions within Child).
if (_anchorElement != null &&
- TranslateBounds(_anchorElement, Child, out var updatedBounds) &&
+ TranslateBounds(_anchorElement, Child!, out var updatedBounds) &&
updatedBounds.Position != _anchorElementBounds.Position)
{
var offset = updatedBounds.Position - _anchorElementBounds.Position;
@@ -337,13 +355,13 @@ namespace Avalonia.Controls.Presenters
}
Viewport = finalSize;
- Extent = Child.Bounds.Size.Inflate(Child.Margin);
+ Extent = Child!.Bounds.Size.Inflate(Child.Margin);
_isAnchorElementDirty = true;
return finalSize;
}
- private void OnScrollGesture(object sender, ScrollGestureEventArgs e)
+ private void OnScrollGesture(object? sender, ScrollGestureEventArgs e)
{
if (Extent.Height > Viewport.Height || Extent.Width > Viewport.Width)
{
@@ -405,12 +423,15 @@ namespace Avalonia.Controls.Presenters
_activeLogicalGestureScrolls[e.Id] = delta;
}
- Offset = new Vector(x, y);
- e.Handled = true;
+ Vector newOffset = new Vector(x, y);
+ bool offsetChanged = newOffset != Offset;
+ Offset = newOffset;
+
+ e.Handled = !IsScrollChainingEnabled || offsetChanged;
}
}
- private void OnScrollGestureEnded(object sender, ScrollGestureEndedEventArgs e)
+ private void OnScrollGestureEnded(object? sender, ScrollGestureEndedEventArgs e)
=> _activeLogicalGestureScrolls?.Remove(e.Id);
///
@@ -440,8 +461,11 @@ namespace Avalonia.Controls.Presenters
x = Math.Min(x, Extent.Width - Viewport.Width);
}
- Offset = new Vector(x, y);
- e.Handled = true;
+ Vector newOffset = new Vector(x, y);
+ bool offsetChanged = newOffset != Offset;
+ Offset = newOffset;
+
+ e.Handled = !IsScrollChainingEnabled || offsetChanged;
}
}
@@ -455,9 +479,10 @@ namespace Avalonia.Controls.Presenters
base.OnPropertyChanged(change);
}
- private void BringIntoViewRequested(object sender, RequestBringIntoViewEventArgs e)
+ private void BringIntoViewRequested(object? sender, RequestBringIntoViewEventArgs e)
{
- e.Handled = BringDescendantIntoView(e.TargetObject, e.TargetRect);
+ if (e.TargetObject is not null)
+ e.Handled = BringDescendantIntoView(e.TargetObject, e.TargetRect);
}
private void ChildChanged(AvaloniaPropertyChangedEventArgs e)
@@ -496,9 +521,9 @@ namespace Avalonia.Controls.Presenters
}
}
- private void ScrollInvalidated(object sender, EventArgs e)
+ private void ScrollInvalidated(object? sender, EventArgs e)
{
- UpdateFromScrollable((ILogicalScrollable)sender);
+ UpdateFromScrollable((ILogicalScrollable)sender!);
}
private void UpdateFromScrollable(ILogicalScrollable scrollable)
@@ -555,7 +580,7 @@ namespace Avalonia.Controls.Presenters
// We have a candidate, calculate its bounds relative to Child. Because these
// bounds aren't relative to the ScrollContentPresenter itself, if they change
// then we know it wasn't just due to scrolling.
- var unscrolledBounds = TranslateBounds(bestCandidate, Child);
+ var unscrolledBounds = TranslateBounds(bestCandidate, Child!);
_anchorElement = bestCandidate;
_anchorElementBounds = unscrolledBounds;
}
@@ -563,7 +588,7 @@ namespace Avalonia.Controls.Presenters
private bool GetViewportBounds(IControl element, out Rect bounds)
{
- if (TranslateBounds(element, Child, out var childBounds))
+ if (TranslateBounds(element, Child!, out var childBounds))
{
// We want the bounds relative to the new Offset, regardless of whether the child
// control has actually been arranged to this offset yet, so translate first to the
diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs
index ff63e5644f..8629af5243 100644
--- a/src/Avalonia.Controls/Presenters/TextPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs
@@ -1,9 +1,10 @@
using System;
-using System.Reactive.Linq;
-using Avalonia.Input.TextInput;
+using System.Collections.Generic;
using Avalonia.Media;
+using Avalonia.Media.TextFormatting;
using Avalonia.Metadata;
using Avalonia.Threading;
+using Avalonia.Utilities;
using Avalonia.VisualTree;
using Avalonia.Layout;
using Avalonia.Media.Immutable;
@@ -23,14 +24,14 @@ namespace Avalonia.Controls.Presenters
public static readonly StyledProperty PasswordCharProperty =
AvaloniaProperty.Register(nameof(PasswordChar));
- public static readonly StyledProperty SelectionBrushProperty =
- AvaloniaProperty.Register(nameof(SelectionBrushProperty));
+ public static readonly StyledProperty SelectionBrushProperty =
+ AvaloniaProperty.Register(nameof(SelectionBrushProperty));
- public static readonly StyledProperty SelectionForegroundBrushProperty =
- AvaloniaProperty.Register(nameof(SelectionForegroundBrushProperty));
+ public static readonly StyledProperty SelectionForegroundBrushProperty =
+ AvaloniaProperty.Register(nameof(SelectionForegroundBrushProperty));
- public static readonly StyledProperty CaretBrushProperty =
- AvaloniaProperty.Register(nameof(CaretBrushProperty));
+ public static readonly StyledProperty CaretBrushProperty =
+ AvaloniaProperty.Register(nameof(CaretBrushProperty));
public static readonly DirectProperty SelectionStartProperty =
TextBox.SelectionStartProperty.AddOwner(
@@ -45,8 +46,8 @@ namespace Avalonia.Controls.Presenters
///
/// Defines the property.
///
- public static readonly DirectProperty TextProperty =
- AvaloniaProperty.RegisterDirect(
+ public static readonly DirectProperty TextProperty =
+ AvaloniaProperty.RegisterDirect(
nameof(Text),
o => o.Text,
(o, v) => o.Text = v);
@@ -66,7 +67,7 @@ namespace Avalonia.Controls.Presenters
///
/// Defines the property.
///
- public static readonly StyledProperty BackgroundProperty =
+ public static readonly StyledProperty BackgroundProperty =
Border.BackgroundProperty.AddOwner();
private readonly DispatcherTimer _caretTimer;
@@ -74,29 +75,17 @@ namespace Avalonia.Controls.Presenters
private int _selectionStart;
private int _selectionEnd;
private bool _caretBlink;
- private string _text;
- private FormattedText _formattedText;
+ private string? _text;
+ private TextLayout? _textLayout;
private Size _constraint;
+ private CharacterHit _lastCharacterHit;
+ private Rect _caretBounds;
+ private Point _navigationPosition;
+
static TextPresenter()
{
- AffectsRender(SelectionBrushProperty, TextBlock.ForegroundProperty,
- SelectionForegroundBrushProperty, CaretBrushProperty,
- SelectionStartProperty, SelectionEndProperty);
-
- AffectsMeasure(TextProperty, PasswordCharProperty, RevealPasswordProperty,
- TextAlignmentProperty, TextWrappingProperty, TextBlock.FontSizeProperty,
- TextBlock.FontStyleProperty, TextBlock.FontWeightProperty, TextBlock.FontFamilyProperty);
-
- Observable.Merge(TextProperty.Changed, TextBlock.ForegroundProperty.Changed,
- TextAlignmentProperty.Changed, TextWrappingProperty.Changed,
- TextBlock.FontSizeProperty.Changed, TextBlock.FontStyleProperty.Changed,
- TextBlock.FontWeightProperty.Changed, TextBlock.FontFamilyProperty.Changed,
- SelectionStartProperty.Changed, SelectionEndProperty.Changed,
- SelectionForegroundBrushProperty.Changed, PasswordCharProperty.Changed, RevealPasswordProperty.Changed
- ).AddClassHandler((x, _) => x.InvalidateFormattedText());
-
- CaretIndexProperty.Changed.AddClassHandler((x, e) => x.CaretIndexChanged((int)e.NewValue));
+ AffectsRender(CaretBrushProperty, SelectionBrushProperty);
}
public TextPresenter()
@@ -106,10 +95,12 @@ namespace Avalonia.Controls.Presenters
_caretTimer.Tick += CaretTimerTick;
}
+ public event EventHandler? CaretBoundsChanged;
+
///
/// Gets or sets a brush used to paint the control's background.
///
- public IBrush Background
+ public IBrush? Background
{
get => GetValue(BackgroundProperty);
set => SetValue(BackgroundProperty, value);
@@ -119,7 +110,7 @@ namespace Avalonia.Controls.Presenters
/// Gets or sets the text.
///
[Content]
- public string Text
+ public string? Text
{
get => _text;
set => SetAndRaise(TextProperty, ref _text, value);
@@ -164,7 +155,7 @@ namespace Avalonia.Controls.Presenters
///
/// Gets or sets a brush used to paint the text.
///
- public IBrush Foreground
+ public IBrush? Foreground
{
get => TextBlock.GetForeground(this);
set => TextBlock.SetForeground(this, value);
@@ -189,13 +180,22 @@ namespace Avalonia.Controls.Presenters
}
///
- /// Gets the used to render the text.
+ /// Gets the used to render the text.
///
- public FormattedText FormattedText
+ public TextLayout TextLayout
{
get
{
- return _formattedText ?? (_formattedText = CreateFormattedText());
+ if (_textLayout != null)
+ {
+ return _textLayout;
+ }
+
+ _textLayout = CreateTextLayout();
+
+ UpdateCaret(_lastCharacterHit);
+
+ return _textLayout;
}
}
@@ -205,11 +205,12 @@ namespace Avalonia.Controls.Presenters
{
return _caretIndex;
}
-
set
{
- value = CoerceCaretIndex(value);
- SetAndRaise(CaretIndexProperty, ref _caretIndex, value);
+ if (value != _caretIndex)
+ {
+ MoveCaretToTextPosition(value);
+ }
}
}
@@ -225,19 +226,19 @@ namespace Avalonia.Controls.Presenters
set => SetValue(RevealPasswordProperty, value);
}
- public IBrush SelectionBrush
+ public IBrush? SelectionBrush
{
get => GetValue(SelectionBrushProperty);
set => SetValue(SelectionBrushProperty, value);
}
- public IBrush SelectionForegroundBrush
+ public IBrush? SelectionForegroundBrush
{
get => GetValue(SelectionForegroundBrushProperty);
set => SetValue(SelectionForegroundBrushProperty, value);
}
- public IBrush CaretBrush
+ public IBrush? CaretBrush
{
get => GetValue(CaretBrushProperty);
set => SetValue(CaretBrushProperty, value);
@@ -271,37 +272,26 @@ namespace Avalonia.Controls.Presenters
}
}
- public int GetCaretIndex(Point point)
- {
- var hit = FormattedText.HitTestPoint(point);
- return hit.TextPosition + (hit.IsTrailing ? 1 : 0);
- }
-
///
- /// Creates the used to render the text.
+ /// Creates the used to render the text.
///
/// The constraint of the text.
/// The text to format.
- /// A object.
- private FormattedText CreateFormattedTextInternal(Size constraint, string text)
- {
- return new FormattedText
- {
- Constraint = constraint,
- Typeface = new Typeface(FontFamily, FontStyle, FontWeight),
- FontSize = FontSize,
- Text = text ?? string.Empty,
- TextAlignment = TextAlignment,
- TextWrapping = TextWrapping,
- };
- }
+ ///
+ ///
+ /// A object.
+ private TextLayout CreateTextLayoutInternal(Size constraint, string? text, Typeface typeface,
+ IReadOnlyList>? textStyleOverrides)
+ {
+ var foreground = Foreground;
+ var maxWidth = MathUtilities.IsZero(constraint.Width) ? double.PositiveInfinity : constraint.Width;
+ var maxHeight = MathUtilities.IsZero(constraint.Height) ? double.PositiveInfinity : constraint.Height;
+
+ var textLayout = new TextLayout(text, typeface, FontSize, foreground, TextAlignment,
+ TextWrapping, maxWidth: maxWidth, maxHeight: maxHeight, textStyleOverrides: textStyleOverrides,
+ flowDirection: FlowDirection);
- ///
- /// Invalidates .
- ///
- protected void InvalidateFormattedText()
- {
- _formattedText = null;
+ return textLayout;
}
///
@@ -317,84 +307,90 @@ namespace Avalonia.Controls.Presenters
context.FillRectangle(background, new Rect(Bounds.Size));
}
- double top = 0;
- var textSize = FormattedText.Bounds.Size;
+ var top = 0d;
+ var left = 0.0;
- if (Bounds.Height < textSize.Height)
+ var (_, textHeight) = TextLayout.Size;
+
+ if (Bounds.Height < textHeight)
{
switch (VerticalAlignment)
{
case VerticalAlignment.Center:
- top += (Bounds.Height - textSize.Height) / 2;
+ top += (Bounds.Height - textHeight) / 2;
break;
case VerticalAlignment.Bottom:
- top += (Bounds.Height - textSize.Height);
+ top += (Bounds.Height - textHeight);
break;
}
}
- context.DrawText(Foreground, new Point(0, top), FormattedText);
+ TextLayout.Draw(context, new Point(left, top));
}
public override void Render(DrawingContext context)
{
- FormattedText.Constraint = Bounds.Size;
-
- _constraint = Bounds.Size;
-
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
+ var selectionBrush = SelectionBrush;
- if (selectionStart != selectionEnd)
+ if (selectionStart != selectionEnd && selectionBrush != null)
{
var start = Math.Min(selectionStart, selectionEnd);
var length = Math.Max(selectionStart, selectionEnd) - start;
- var rects = FormattedText.HitTestTextRange(start, length);
+ var rects = TextLayout.HitTestTextRange(start, length);
foreach (var rect in rects)
{
- context.FillRectangle(SelectionBrush, rect);
+ context.FillRectangle(selectionBrush, rect);
}
}
RenderInternal(context);
- if (selectionStart == selectionEnd && _caretBlink)
+ if (selectionStart != selectionEnd || !_caretBlink)
+ {
+ return;
+ }
+
+ var caretBrush = CaretBrush?.ToImmutable();
+
+ if (caretBrush is null)
{
- var caretBrush = CaretBrush?.ToImmutable();
+ var backgroundColor = (Background as ISolidColorBrush)?.Color;
- if (caretBrush is null)
+ if (backgroundColor.HasValue)
{
- var backgroundColor = (Background as ISolidColorBrush)?.Color;
- if (backgroundColor.HasValue)
- {
- byte red = (byte)~(backgroundColor.Value.R);
- byte green = (byte)~(backgroundColor.Value.G);
- byte blue = (byte)~(backgroundColor.Value.B);
+ var red = (byte)~(backgroundColor.Value.R);
+ var green = (byte)~(backgroundColor.Value.G);
+ var blue = (byte)~(backgroundColor.Value.B);
- caretBrush = new ImmutableSolidColorBrush(Color.FromRgb(red, green, blue));
- }
- else
- {
- caretBrush = Brushes.Black;
- }
+ caretBrush = new ImmutableSolidColorBrush(Color.FromRgb(red, green, blue));
+ }
+ else
+ {
+ caretBrush = Brushes.Black;
}
-
- var (p1, p2) = GetCaretPoints();
- context.DrawLine(
- new ImmutablePen(caretBrush, 1),
- p1, p2);
}
- }
- (Point, Point) GetCaretPoints()
+ var (p1, p2) = GetCaretPoints();
+
+ context.DrawLine(new ImmutablePen(caretBrush), p1, p2);
+ }
+
+ private (Point, Point) GetCaretPoints()
{
- var charPos = FormattedText.HitTestTextPosition(CaretIndex);
- var x = Math.Floor(charPos.X) + 0.5;
- var y = Math.Floor(charPos.Y) + 0.5;
- var b = Math.Ceiling(charPos.Bottom) - 0.5;
+ var x = Math.Floor(_caretBounds.X) + 0.5;
+ var y = Math.Floor(_caretBounds.Y) + 0.5;
+ var b = Math.Ceiling(_caretBounds.Bottom) - 0.5;
+
+ if (x >= Bounds.Width)
+ {
+ x = Math.Floor(_caretBounds.X - 1) + 0.5;
+ }
+
return (new Point(x, y), new Point(x, b));
}
@@ -412,144 +408,371 @@ namespace Avalonia.Controls.Presenters
InvalidateVisual();
}
- internal void CaretIndexChanged(int caretIndex)
+ internal void CaretChanged()
{
- if (this.GetVisualParent() != null)
+ if (this.GetVisualParent() == null)
{
- if (_caretTimer.IsEnabled)
- {
- _caretBlink = true;
- _caretTimer.Stop();
- _caretTimer.Start();
- InvalidateVisual();
- }
- else
- {
- _caretTimer.Start();
- InvalidateVisual();
- _caretTimer.Stop();
- }
+ return;
+ }
- if (IsMeasureValid)
- {
- var rect = FormattedText.HitTestTextPosition(caretIndex);
- this.BringIntoView(rect);
- }
- else
- {
- // The measure is currently invalid so there's no point trying to bring the
- // current char into view until a measure has been carried out as the scroll
- // viewer extents may not be up-to-date.
- Dispatcher.UIThread.Post(
- () =>
- {
- var rect = FormattedText.HitTestTextPosition(caretIndex);
- this.BringIntoView(rect);
- },
- DispatcherPriority.Render);
- }
+ if (_caretTimer.IsEnabled)
+ {
+ _caretBlink = true;
+ _caretTimer.Stop();
+ _caretTimer.Start();
+ InvalidateVisual();
+ }
+ else
+ {
+ _caretTimer.Start();
+ InvalidateVisual();
+ _caretTimer.Stop();
+ }
+
+ if (IsMeasureValid)
+ {
+ this.BringIntoView(_caretBounds);
+ }
+ else
+ {
+ // The measure is currently invalid so there's no point trying to bring the
+ // current char into view until a measure has been carried out as the scroll
+ // viewer extents may not be up-to-date.
+ Dispatcher.UIThread.Post(
+ () =>
+ {
+ this.BringIntoView(_caretBounds);
+ },
+ DispatcherPriority.Render);
}
}
///
- /// Creates the used to render the text.
+ /// Creates the used to render the text.
///
- /// A object.
- protected virtual FormattedText CreateFormattedText()
+ /// A object.
+ protected virtual TextLayout CreateTextLayout()
{
- FormattedText result = null;
+ TextLayout result;
var text = Text;
- if (PasswordChar != default(char) && !RevealPassword)
- {
- result = CreateFormattedTextInternal(_constraint, new string(PasswordChar, text?.Length ?? 0));
- }
- else
- {
- result = CreateFormattedTextInternal(_constraint, text);
- }
+ var typeface = new Typeface(FontFamily, FontStyle, FontWeight);
var selectionStart = SelectionStart;
var selectionEnd = SelectionEnd;
var start = Math.Min(selectionStart, selectionEnd);
var length = Math.Max(selectionStart, selectionEnd) - start;
+ IReadOnlyList>? textStyleOverrides = null;
+
if (length > 0)
{
- result.Spans = new[]
+ textStyleOverrides = new[]
{
- new FormattedTextStyleSpan(start, length, SelectionForegroundBrush),
+ new ValueSpan(start, length,
+ new GenericTextRunProperties(typeface, FontSize,
+ foregroundBrush: SelectionForegroundBrush ?? Brushes.White))
};
}
+ if (PasswordChar != default(char) && !RevealPassword)
+ {
+ result = CreateTextLayoutInternal(_constraint, new string(PasswordChar, text?.Length ?? 0), typeface,
+ textStyleOverrides);
+ }
+ else
+ {
+ result = CreateTextLayoutInternal(_constraint, text, typeface, textStyleOverrides);
+ }
+
return result;
}
- ///
- /// Measures the control.
- ///
- /// The available size for the control.
- /// The desired size.
- private Size MeasureInternal(Size availableSize)
+ protected virtual void InvalidateTextLayout()
+ {
+ _textLayout = null;
+
+ InvalidateMeasure();
+ }
+
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ _textLayout = null;
+
+ _constraint = availableSize;
+
+ return TextLayout.Size;
+ }
+
+ protected override Size ArrangeOverride(Size finalSize)
+ {
+ if (!double.IsInfinity(_constraint.Width))
+ {
+ return base.ArrangeOverride(finalSize);
+ }
+
+ _constraint = finalSize;
+
+ _textLayout = null;
+
+ return base.ArrangeOverride(finalSize);
+ }
+
+ private int CoerceCaretIndex(int value)
+ {
+ var text = Text;
+ var length = text?.Length ?? 0;
+ return Math.Max(0, Math.Min(length, value));
+ }
+
+ private void CaretTimerTick(object? sender, EventArgs e)
+ {
+ _caretBlink = !_caretBlink;
+
+ InvalidateVisual();
+ }
+
+ public void MoveCaretToTextPosition(int textPosition, bool trailingEdge = false)
+ {
+ var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(textPosition, trailingEdge);
+ var textLine = TextLayout.TextLines[lineIndex];
+
+ var characterHit = textLine.GetPreviousCaretCharacterHit(new CharacterHit(textPosition));
+
+ var nextCaretCharacterHit = textLine.GetNextCaretCharacterHit(characterHit);
+
+ if (nextCaretCharacterHit.FirstCharacterIndex <= textPosition)
+ {
+ characterHit = nextCaretCharacterHit;
+ }
+
+ if (textPosition == characterHit.FirstCharacterIndex + characterHit.TrailingLength)
+ {
+ UpdateCaret(characterHit);
+ }
+ else
+ {
+ UpdateCaret(trailingEdge ? characterHit : new CharacterHit(characterHit.FirstCharacterIndex));
+ }
+
+ _navigationPosition = _caretBounds.Position;
+
+ CaretChanged();
+ }
+
+ public void MoveCaretToPoint(Point point)
+ {
+ var hit = TextLayout.HitTestPoint(point);
+
+ UpdateCaret(hit.CharacterHit);
+
+ _navigationPosition = _caretBounds.Position;
+
+ CaretChanged();
+ }
+
+ public void MoveCaretVertical(LogicalDirection direction = LogicalDirection.Forward)
{
- if (!string.IsNullOrEmpty(Text))
+ var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(CaretIndex, _lastCharacterHit.TrailingLength > 0);
+
+ if (lineIndex < 0)
+ {
+ return;
+ }
+
+ var (currentX, currentY) = _navigationPosition;
+
+ if (direction == LogicalDirection.Forward)
{
- if (TextWrapping == TextWrapping.Wrap)
+ if (lineIndex + 1 > TextLayout.TextLines.Count - 1)
{
- _constraint = new Size(availableSize.Width, double.PositiveInfinity);
+ return;
}
- else
+
+ var textLine = TextLayout.TextLines[lineIndex];
+
+ currentY += textLine.Height;
+ }
+ else
+ {
+ if (lineIndex - 1 < 0)
{
- _constraint = Size.Infinity;
+ return;
}
- _formattedText = null;
+ var textLine = TextLayout.TextLines[--lineIndex];
- return FormattedText.Bounds.Size;
+ currentY -= textLine.Height;
}
- return new Size();
+ var navigationPosition = _navigationPosition;
+
+ MoveCaretToPoint(new Point(currentX, currentY));
+
+ _navigationPosition = navigationPosition.WithY(_caretBounds.Y);
+
+ CaretChanged();
}
- protected override Size MeasureOverride(Size availableSize)
+ public void MoveCaretHorizontal(LogicalDirection direction = LogicalDirection.Forward)
{
- var text = Text;
+ if (Text is null)
+ {
+ return;
+ }
+
+ if (FlowDirection == FlowDirection.RightToLeft)
+ {
+ direction = direction == LogicalDirection.Forward ?
+ LogicalDirection.Backward :
+ LogicalDirection.Forward;
+ }
+
+ var characterHit = _lastCharacterHit;
+ var caretIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
+
+ var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(caretIndex, false);
- if (!string.IsNullOrEmpty(text))
+ if (lineIndex < 0)
{
- return MeasureInternal(availableSize);
+ return;
+ }
+
+ if (direction == LogicalDirection.Forward)
+ {
+ while (lineIndex < TextLayout.TextLines.Count)
+ {
+ var textLine = TextLayout.TextLines[lineIndex];
+
+ characterHit = textLine.GetNextCaretCharacterHit(characterHit);
+
+ caretIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
+
+ if (textLine.NewLineLength > 0 && caretIndex == textLine.TextRange.Start + textLine.TextRange.Length)
+ {
+ characterHit = new CharacterHit(caretIndex);
+ }
+
+ if (caretIndex >= Text.Length)
+ {
+ characterHit = new CharacterHit(Text.Length);
+
+ break;
+ }
+
+ if (caretIndex - textLine.NewLineLength == textLine.TextRange.Start + textLine.TextRange.Length)
+ {
+ break;
+ }
+
+ if (caretIndex <= CaretIndex)
+ {
+ lineIndex++;
+
+ continue;
+ }
+
+ break;
+ }
}
else
{
- return new FormattedText
+ while (lineIndex >= 0)
{
- Text = "X",
- Typeface = new Typeface(FontFamily, FontStyle, FontWeight),
- FontSize = FontSize,
- TextAlignment = TextAlignment,
- Constraint = availableSize,
- }.Bounds.Size;
+ var textLine = TextLayout.TextLines[lineIndex];
+
+ characterHit = textLine.GetPreviousCaretCharacterHit(characterHit);
+
+ caretIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
+
+ if (caretIndex >= CaretIndex)
+ {
+ lineIndex--;
+
+ continue;
+ }
+
+ break;
+ }
}
+
+ UpdateCaret(characterHit);
+
+ _navigationPosition = _caretBounds.Position;
+
+ CaretChanged();
}
- private int CoerceCaretIndex(int value)
+ private void UpdateCaret(CharacterHit characterHit)
{
- var text = Text;
- var length = text?.Length ?? 0;
- return Math.Max(0, Math.Min(length, value));
+ _lastCharacterHit = characterHit;
+
+ var caretIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
+
+ var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(caretIndex, characterHit.TrailingLength > 0);
+ var textLine = TextLayout.TextLines[lineIndex];
+ var distanceX = textLine.GetDistanceFromCharacterHit(characterHit);
+
+ var distanceY = 0d;
+
+ for (var i = 0; i < lineIndex; i++)
+ {
+ var currentLine = TextLayout.TextLines[i];
+
+ distanceY += currentLine.Height;
+ }
+
+ var caretBounds = new Rect(distanceX, distanceY, 0, textLine.Height);
+
+ if (caretBounds != _caretBounds)
+ {
+ _caretBounds = caretBounds;
+
+ CaretBoundsChanged?.Invoke(this, EventArgs.Empty);
+ }
+
+ SetAndRaise(CaretIndexProperty, ref _caretIndex, caretIndex);
}
- private void CaretTimerTick(object sender, EventArgs e)
+ internal Rect GetCursorRectangle()
{
- _caretBlink = !_caretBlink;
- InvalidateVisual();
+ return _caretBounds;
}
- internal Rect GetCursorRectangle()
+ protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
- var (p1, p2) = GetCaretPoints();
- return new Rect(p1, p2);
+ base.OnDetachedFromVisualTree(e);
+
+ _caretTimer.Stop();
+
+ _caretTimer.Tick -= CaretTimerTick;
+ }
+
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ switch (change.Property.Name)
+ {
+ case nameof (TextBlock.Foreground):
+ case nameof (TextBlock.FontSize):
+ case nameof (TextBlock.FontStyle):
+ case nameof (TextBlock.FontWeight):
+ case nameof (TextBlock.FontFamily):
+ case nameof (Text):
+ case nameof (TextAlignment):
+ case nameof (TextWrapping):
+ case nameof (SelectionStart):
+ case nameof (SelectionEnd):
+ case nameof (SelectionForegroundBrush):
+ case nameof (PasswordChar):
+ case nameof (RevealPassword):
+ {
+ InvalidateTextLayout();
+ break;
+ }
+ }
}
}
}
diff --git a/src/Avalonia.Controls/Primitives/AccessText.cs b/src/Avalonia.Controls/Primitives/AccessText.cs
index 3c82386991..a6976721b1 100644
--- a/src/Avalonia.Controls/Primitives/AccessText.cs
+++ b/src/Avalonia.Controls/Primitives/AccessText.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using Avalonia.Input;
using Avalonia.Media;
using Avalonia.Media.TextFormatting;
@@ -19,7 +20,7 @@ namespace Avalonia.Controls.Primitives
///
/// The access key handler for the current window.
///
- private IAccessKeyHandler _accessKeys;
+ private IAccessKeyHandler? _accessKeys;
///
/// Initializes static members of the class.
@@ -67,7 +68,7 @@ namespace Avalonia.Controls.Primitives
if (underscore != -1 && ShowAccessKey)
{
- var rect = TextLayout.HitTestTextPosition(underscore);
+ var rect = TextLayout!.HitTestTextPosition(underscore);
var offset = new Vector(0, -1.5);
context.DrawLine(
new Pen(Foreground, 1),
@@ -77,7 +78,7 @@ namespace Avalonia.Controls.Primitives
}
///
- protected override TextLayout CreateTextLayout(Size constraint, string text)
+ protected override TextLayout? CreateTextLayout(Size constraint, string? text)
{
return base.CreateTextLayout(constraint, StripAccessKey(text));
}
@@ -111,8 +112,14 @@ namespace Avalonia.Controls.Primitives
///
/// The text.
/// The text with the first underscore stripped.
- private string StripAccessKey(string text)
+ [return: NotNullIfNotNull("text")]
+ private string? StripAccessKey(string? text)
{
+ if (text is null)
+ {
+ return null;
+ }
+
var position = text.IndexOf('_');
if (position == -1)
@@ -129,7 +136,7 @@ namespace Avalonia.Controls.Primitives
/// Called when the property changes.
///
/// The new text.
- private void TextChanged(string text)
+ private void TextChanged(string? text)
{
var key = (char)0;
diff --git a/src/Avalonia.Controls/Primitives/AdornerLayer.cs b/src/Avalonia.Controls/Primitives/AdornerLayer.cs
index 2ead82f95d..353f12118f 100644
--- a/src/Avalonia.Controls/Primitives/AdornerLayer.cs
+++ b/src/Avalonia.Controls/Primitives/AdornerLayer.cs
@@ -4,8 +4,6 @@ using Avalonia.Media;
using Avalonia.Rendering;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
///
@@ -142,12 +140,12 @@ namespace Avalonia.Controls.Primitives
clip.Rect = clipBounds;
}
- private void ChildrenCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void ChildrenCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
- foreach (Visual i in e.NewItems)
+ foreach (Visual i in e.NewItems!)
{
UpdateAdornedElement(i, i.GetValue(AdornedElementProperty));
}
diff --git a/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs b/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs
index 7171ecc302..a774368af6 100644
--- a/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs
+++ b/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs
@@ -2,8 +2,6 @@
using Avalonia.Rendering;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
public class ChromeOverlayLayer : Panel, ICustomSimpleHitTest
diff --git a/src/Avalonia.Controls/Primitives/HeaderedContentControl.cs b/src/Avalonia.Controls/Primitives/HeaderedContentControl.cs
index e55bdbb0eb..d44ef5666c 100644
--- a/src/Avalonia.Controls/Primitives/HeaderedContentControl.cs
+++ b/src/Avalonia.Controls/Primitives/HeaderedContentControl.cs
@@ -2,8 +2,6 @@ using Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
using Avalonia.LogicalTree;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
///
diff --git a/src/Avalonia.Controls/Primitives/HeaderedItemsControl.cs b/src/Avalonia.Controls/Primitives/HeaderedItemsControl.cs
index be3c100ecf..2f051c4fda 100644
--- a/src/Avalonia.Controls/Primitives/HeaderedItemsControl.cs
+++ b/src/Avalonia.Controls/Primitives/HeaderedItemsControl.cs
@@ -1,5 +1,4 @@
using Avalonia.Collections;
-using Avalonia.Controls.Mixins;
using Avalonia.Controls.Presenters;
using Avalonia.LogicalTree;
@@ -13,7 +12,7 @@ namespace Avalonia.Controls.Primitives
///
/// Defines the property.
///
- public static readonly StyledProperty HeaderProperty =
+ public static readonly StyledProperty HeaderProperty =
HeaderedContentControl.HeaderProperty.AddOwner();
///
@@ -27,7 +26,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets or sets the content of the control's header.
///
- public object Header
+ public object? Header
{
get { return GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
@@ -36,7 +35,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets the header presenter from the control's template.
///
- public IContentPresenter HeaderPresenter
+ public IContentPresenter? HeaderPresenter
{
get;
private set;
diff --git a/src/Avalonia.Controls/Primitives/HeaderedSelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/HeaderedSelectingItemsControl.cs
index 78b5771b80..49fc58c8f5 100644
--- a/src/Avalonia.Controls/Primitives/HeaderedSelectingItemsControl.cs
+++ b/src/Avalonia.Controls/Primitives/HeaderedSelectingItemsControl.cs
@@ -1,5 +1,4 @@
using Avalonia.Collections;
-using Avalonia.Controls.Mixins;
using Avalonia.Controls.Presenters;
using Avalonia.LogicalTree;
@@ -13,7 +12,7 @@ namespace Avalonia.Controls.Primitives
///
/// Defines the property.
///
- public static readonly StyledProperty HeaderProperty =
+ public static readonly StyledProperty HeaderProperty =
HeaderedContentControl.HeaderProperty.AddOwner();
///
@@ -27,7 +26,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets or sets the content of the control's header.
///
- public object Header
+ public object? Header
{
get { return GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
@@ -36,7 +35,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets the header presenter from the control's template.
///
- public IContentPresenter HeaderPresenter
+ public IContentPresenter? HeaderPresenter
{
get;
private set;
diff --git a/src/Avalonia.Controls/Primitives/ILogicalScrollable.cs b/src/Avalonia.Controls/Primitives/ILogicalScrollable.cs
index 5c29945735..2be91c046e 100644
--- a/src/Avalonia.Controls/Primitives/ILogicalScrollable.cs
+++ b/src/Avalonia.Controls/Primitives/ILogicalScrollable.cs
@@ -48,7 +48,7 @@ namespace Avalonia.Controls.Primitives
/// This event notifies an attached of a change in
/// one of the scroll properties.
///
- event EventHandler ScrollInvalidated;
+ event EventHandler? ScrollInvalidated;
///
/// Attempts to bring a portion of the target visual into view by scrolling the content.
@@ -64,7 +64,7 @@ namespace Avalonia.Controls.Primitives
/// The movement direction.
/// The control from which movement begins.
/// The control.
- IControl GetControlInDirection(NavigationDirection direction, IControl from);
+ IControl? GetControlInDirection(NavigationDirection direction, IControl from);
///
/// Raises the event.
diff --git a/src/Avalonia.Controls/Primitives/IPopupHost.cs b/src/Avalonia.Controls/Primitives/IPopupHost.cs
index ab81fe869e..36d2ae9230 100644
--- a/src/Avalonia.Controls/Primitives/IPopupHost.cs
+++ b/src/Avalonia.Controls/Primitives/IPopupHost.cs
@@ -20,23 +20,23 @@ namespace Avalonia.Controls.Primitives
/// Sets the control to display in the popup.
///
///
- void SetChild(IControl control);
+ void SetChild(IControl? control);
///
/// Gets the presenter from the control's template.
///
- IContentPresenter Presenter { get; }
+ IContentPresenter? Presenter { get; }
///
/// Gets the root of the visual tree in the case where the popup is presented using a
/// separate visual tree.
///
- IVisual HostedVisualTreeRoot { get; }
+ IVisual? HostedVisualTreeRoot { get; }
///
/// Raised when the control's template is applied.
///
- event EventHandler TemplateApplied;
+ event EventHandler? TemplateApplied;
///
/// Configures the position of the popup according to a target control and a set of
diff --git a/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs b/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs
index 74d804f2bf..04c30b0f33 100644
--- a/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs
+++ b/src/Avalonia.Controls/Primitives/LightDismissOverlayLayer.cs
@@ -7,8 +7,6 @@ using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
///
@@ -52,7 +50,7 @@ namespace Avalonia.Controls.Primitives
{
if (InputPassThroughElement is object)
{
- var hit = VisualRoot.GetVisualAt(point, x => x != this);
+ var hit = VisualRoot?.GetVisualAt(point, x => x != this);
if (hit is object)
{
diff --git a/src/Avalonia.Controls/Primitives/OverlayLayer.cs b/src/Avalonia.Controls/Primitives/OverlayLayer.cs
index 5150033a53..6a0408d6d1 100644
--- a/src/Avalonia.Controls/Primitives/OverlayLayer.cs
+++ b/src/Avalonia.Controls/Primitives/OverlayLayer.cs
@@ -7,7 +7,7 @@ namespace Avalonia.Controls.Primitives
public class OverlayLayer : Canvas, ICustomSimpleHitTest
{
public Size AvailableSize { get; private set; }
- public static OverlayLayer GetOverlayLayer(IVisual visual)
+ public static OverlayLayer? GetOverlayLayer(IVisual visual)
{
foreach(var v in visual.GetVisualAncestors())
if(v is VisualLayerManager vlm)
diff --git a/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs b/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs
index 403902f676..6251d5cda7 100644
--- a/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs
+++ b/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs
@@ -23,15 +23,15 @@ namespace Avalonia.Controls.Primitives
_positioner = new ManagedPopupPositioner(this);
}
- public void SetChild(IControl control)
+ public void SetChild(IControl? control)
{
Content = control;
}
- public IVisual HostedVisualTreeRoot => null;
+ public IVisual? HostedVisualTreeRoot => null;
///
- IInteractive IInteractive.InteractiveParent => Parent;
+ IInteractive? IInteractive.InteractiveParent => Parent;
public void Dispose() => Hide();
@@ -75,7 +75,7 @@ namespace Avalonia.Controls.Primitives
PopupPositionerConstraintAdjustment constraintAdjustment = PopupPositionerConstraintAdjustment.All,
Rect? rect = null)
{
- _positionerParameters.ConfigurePosition((TopLevel)_overlayLayer.GetVisualRoot(), target, placement, offset, anchor,
+ _positionerParameters.ConfigurePosition((TopLevel)_overlayLayer.GetVisualRoot()!, target, placement, offset, anchor,
gravity, constraintAdjustment, rect);
UpdatePosition();
}
@@ -126,11 +126,11 @@ namespace Avalonia.Controls.Primitives
double IManagedPopupPositionerPopup.Scaling => 1;
- public static IPopupHost CreatePopupHost(IVisual target, IAvaloniaDependencyResolver dependencyResolver)
+ public static IPopupHost CreatePopupHost(IVisual target, IAvaloniaDependencyResolver? dependencyResolver)
{
var platform = (target.GetVisualRoot() as TopLevel)?.PlatformImpl?.CreatePopup();
if (platform != null)
- return new PopupRoot((TopLevel)target.GetVisualRoot(), platform, dependencyResolver);
+ return new PopupRoot((TopLevel)target.GetVisualRoot()!, platform, dependencyResolver);
var overlayLayer = OverlayLayer.GetOverlayLayer(target);
if (overlayLayer == null)
diff --git a/src/Avalonia.Controls/Primitives/Popup.cs b/src/Avalonia.Controls/Primitives/Popup.cs
index a47149a9e0..f3fec95bcc 100644
--- a/src/Avalonia.Controls/Primitives/Popup.cs
+++ b/src/Avalonia.Controls/Primitives/Popup.cs
@@ -14,8 +14,6 @@ using Avalonia.Metadata;
using Avalonia.Platform;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
///
@@ -419,7 +417,7 @@ namespace Avalonia.Controls.Primitives
(x, handler) => x.TemplateApplied += handler,
(x, handler) => x.TemplateApplied -= handler).DisposeWith(handlerCleanup);
- if (topLevel is Window window)
+ if (topLevel is Window window && window.PlatformImpl != null)
{
SubscribeToEventHandler(window, WindowDeactivated,
(x, handler) => x.Deactivated += handler,
@@ -571,7 +569,7 @@ namespace Avalonia.Controls.Primitives
private void WindowManagerAddShadowHintChanged(IPopupHost host, bool hint)
{
- if(host is PopupRoot pr)
+ if(host is PopupRoot pr && pr.PlatformImpl is not null)
{
pr.PlatformImpl.SetWindowManagerAddShadowHint(hint);
}
@@ -676,7 +674,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void PointerPressedDismissOverlay(object sender, PointerPressedEventArgs e)
+ private void PointerPressedDismissOverlay(object? sender, PointerPressedEventArgs e)
{
if (IsLightDismissEnabled && e.Source is IVisual v && !IsChildOrThis(v))
{
@@ -706,7 +704,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void RootTemplateApplied(object sender, TemplateAppliedEventArgs e)
+ private void RootTemplateApplied(object? sender, TemplateAppliedEventArgs e)
{
if (_openState is null)
{
@@ -733,7 +731,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void SetTemplatedParentAndApplyChildTemplates(IControl control)
+ private void SetTemplatedParentAndApplyChildTemplates(IControl? control)
{
if (control != null)
{
@@ -794,7 +792,7 @@ namespace Avalonia.Controls.Primitives
public bool IsPointerOverPopup => ((IInputElement?)_openState?.PopupHost)?.IsPointerOver ?? false;
- private void WindowDeactivated(object sender, EventArgs e)
+ private void WindowDeactivated(object? sender, EventArgs e)
{
if (IsLightDismissEnabled)
{
@@ -802,7 +800,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void ParentClosed(object sender, EventArgs e)
+ private void ParentClosed(object? sender, EventArgs e)
{
if (IsLightDismissEnabled)
{
@@ -818,9 +816,9 @@ namespace Avalonia.Controls.Primitives
private void WindowPositionChanged(PixelPoint pp) => HandlePositionChange();
- private void PlacementTargetLayoutUpdated(object src, EventArgs e) => HandlePositionChange();
+ private void PlacementTargetLayoutUpdated(object? src, EventArgs e) => HandlePositionChange();
- private void ParentPopupPositionChanged(object src, PixelPointEventArgs e) => HandlePositionChange();
+ private void ParentPopupPositionChanged(object? src, PixelPointEventArgs e) => HandlePositionChange();
private IgnoreIsOpenScope BeginIgnoringIsOpen()
{
diff --git a/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs b/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs
index 844069965b..340076a407 100644
--- a/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs
+++ b/src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs
@@ -448,7 +448,7 @@ namespace Avalonia.Controls.Primitives.PopupPositioning
{
// We need a better way for tracking the last pointer position
#pragma warning disable CS0618 // Type or member is obsolete
- var pointer = topLevel.PointToClient(topLevel.PlatformImpl.MouseDevice.Position);
+ var pointer = topLevel.PointToClient(topLevel.PlatformImpl?.MouseDevice.Position ?? default);
#pragma warning restore CS0618 // Type or member is obsolete
positionerParameters.Offset = offset;
diff --git a/src/Avalonia.Controls/Primitives/PopupRoot.cs b/src/Avalonia.Controls/Primitives/PopupRoot.cs
index c59c7c11d9..be447ea512 100644
--- a/src/Avalonia.Controls/Primitives/PopupRoot.cs
+++ b/src/Avalonia.Controls/Primitives/PopupRoot.cs
@@ -43,7 +43,7 @@ namespace Avalonia.Controls.Primitives
///
/// The dependency resolver to use. If null the default dependency resolver will be used.
///
- public PopupRoot(TopLevel parent, IPopupImpl impl, IAvaloniaDependencyResolver dependencyResolver)
+ public PopupRoot(TopLevel parent, IPopupImpl impl, IAvaloniaDependencyResolver? dependencyResolver)
: base(ValidatingPopupImpl.Wrap(impl), dependencyResolver)
{
_parent = parent;
@@ -52,8 +52,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets the platform-specific window implementation.
///
- [CanBeNull]
- public new IPopupImpl PlatformImpl => (IPopupImpl)base.PlatformImpl;
+ public new IPopupImpl? PlatformImpl => (IPopupImpl?)base.PlatformImpl;
///
/// Gets the parent control in the event route.
@@ -61,20 +60,24 @@ namespace Avalonia.Controls.Primitives
///
/// Popup events are passed to their parent window. This facilitates this.
///
- IInteractive IInteractive.InteractiveParent => Parent;
+ IInteractive? IInteractive.InteractiveParent => Parent;
///
/// Gets the control that is hosting the popup root.
///
- IVisual IHostedVisualTreeRoot.Host => Parent;
+ IVisual? IHostedVisualTreeRoot.Host => Parent;
///
/// Gets the styling parent of the popup root.
///
- IStyleHost IStyleHost.StylingParent => Parent;
+ IStyleHost? IStyleHost.StylingParent => Parent;
///
- public void Dispose() => PlatformImpl?.Dispose();
+ public void Dispose()
+ {
+ PlatformImpl?.Dispose();
+ HandleClosed();
+ }
private void UpdatePosition()
{
@@ -94,7 +97,7 @@ namespace Avalonia.Controls.Primitives
UpdatePosition();
}
- public void SetChild(IControl control) => Content = control;
+ public void SetChild(IControl? control) => Content = control;
IVisual IPopupHost.HostedVisualTreeRoot => this;
diff --git a/src/Avalonia.Controls/Primitives/ScrollBar.cs b/src/Avalonia.Controls/Primitives/ScrollBar.cs
index d5d6af8bfa..8460fe3017 100644
--- a/src/Avalonia.Controls/Primitives/ScrollBar.cs
+++ b/src/Avalonia.Controls/Primitives/ScrollBar.cs
@@ -69,11 +69,11 @@ namespace Avalonia.Controls.Primitives
public static readonly StyledProperty ShowDelayProperty =
AvaloniaProperty.Register(nameof(ShowDelay), TimeSpan.FromSeconds(0.5));
- private Button _lineUpButton;
- private Button _lineDownButton;
- private Button _pageUpButton;
- private Button _pageDownButton;
- private DispatcherTimer _timer;
+ private Button? _lineUpButton;
+ private Button? _lineDownButton;
+ private Button? _pageUpButton;
+ private Button? _pageDownButton;
+ private DispatcherTimer? _timer;
private bool _isExpanded;
///
@@ -157,7 +157,7 @@ namespace Avalonia.Controls.Primitives
set => SetValue(ShowDelayProperty, value);
}
- public event EventHandler Scroll;
+ public event EventHandler? Scroll;
///
/// Calculates and updates whether the scrollbar should be visible.
@@ -293,7 +293,7 @@ namespace Avalonia.Controls.Primitives
_timer = new DispatcherTimer(DispatcherPriority.Normal);
_timer.Tick += (sender, args) =>
{
- var senderTimer = (DispatcherTimer)sender;
+ var senderTimer = (DispatcherTimer)sender!;
if (senderTimer.Tag is Action action)
{
@@ -344,22 +344,22 @@ namespace Avalonia.Controls.Primitives
IsExpanded = true;
}
- private void LineUpClick(object sender, RoutedEventArgs e)
+ private void LineUpClick(object? sender, RoutedEventArgs e)
{
SmallDecrement();
}
- private void LineDownClick(object sender, RoutedEventArgs e)
+ private void LineDownClick(object? sender, RoutedEventArgs e)
{
SmallIncrement();
}
- private void PageUpClick(object sender, RoutedEventArgs e)
+ private void PageUpClick(object? sender, RoutedEventArgs e)
{
LargeDecrement();
}
- private void PageDownClick(object sender, RoutedEventArgs e)
+ private void PageDownClick(object? sender, RoutedEventArgs e)
{
LargeIncrement();
}
diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
index 80f3d345a6..b4cfd9404c 100644
--- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
+++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
@@ -13,8 +13,6 @@ using Avalonia.Interactivity;
using Avalonia.Threading;
using Avalonia.VisualTree;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
///
@@ -116,6 +114,12 @@ namespace Avalonia.Controls.Primitives
"SelectionChanged",
RoutingStrategies.Bubble);
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty WrapSelectionProperty =
+ AvaloniaProperty.Register(nameof(WrapSelection), defaultValue: false);
+
private static readonly IList Empty = Array.Empty();
private string _textSearchTerm = string.Empty;
private DispatcherTimer? _textSearchTimer;
@@ -138,7 +142,7 @@ namespace Avalonia.Controls.Primitives
///
/// Occurs when the control's selection changes.
///
- public event EventHandler SelectionChanged
+ public event EventHandler? SelectionChanged
{
add { AddHandler(SelectionChangedEvent, value); }
remove { RemoveHandler(SelectionChangedEvent, value); }
@@ -323,6 +327,16 @@ namespace Avalonia.Controls.Primitives
set { SetValue(IsTextSearchEnabledProperty, value); }
}
+ ///
+ /// Gets or sets a value which indicates whether to wrap around when the first
+ /// or last item is reached.
+ ///
+ public bool WrapSelection
+ {
+ get { return GetValue(WrapSelectionProperty); }
+ set { SetValue(WrapSelectionProperty, value); }
+ }
+
///
/// Gets or sets the selection mode.
///
@@ -386,9 +400,9 @@ namespace Avalonia.Controls.Primitives
return null;
}
- protected override void ItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ protected override void ItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
- base.ItemsCollectionChanged(sender, e);
+ base.ItemsCollectionChanged(sender!, e);
if (AlwaysSelected && SelectedIndex == -1 && ItemCount > 0)
{
@@ -406,7 +420,7 @@ namespace Avalonia.Controls.Primitives
{
base.OnApplyTemplate(e);
- void ExecuteScrollWhenLayoutUpdated(object sender, EventArgs e)
+ void ExecuteScrollWhenLayoutUpdated(object? sender, EventArgs e)
{
LayoutUpdated -= ExecuteScrollWhenLayoutUpdated;
AutoScrollToSelectedItemIfNecessary();
@@ -443,9 +457,7 @@ namespace Avalonia.Controls.Primitives
{
base.OnContainersDematerialized(e);
- var panel = (InputElement)Presenter.Panel;
-
- if (panel != null)
+ if (Presenter?.Panel is InputElement panel)
{
foreach (var container in e.Containers)
{
@@ -523,7 +535,7 @@ namespace Avalonia.Controls.Primitives
info.ContainerControl is IContentControl control &&
control.Content?.ToString()?.StartsWith(_textSearchTerm, StringComparison.OrdinalIgnoreCase) == true;
- var info = ItemContainerGenerator.Containers.FirstOrDefault(match);
+ var info = ItemContainerGenerator?.Containers.FirstOrDefault(match);
if (info != null)
{
@@ -584,6 +596,10 @@ namespace Avalonia.Controls.Primitives
var newValue = change.NewValue.GetValueOrDefault();
_selection.SingleSelect = !newValue.HasAllFlags(SelectionMode.Multiple);
}
+ else if (change.Property == WrapSelectionProperty)
+ {
+ WrapFocus = WrapSelection;
+ }
}
///
@@ -594,7 +610,7 @@ namespace Avalonia.Controls.Primitives
/// True if the selection was moved; otherwise false.
protected bool MoveSelection(NavigationDirection direction, bool wrap)
{
- var from = SelectedIndex != -1 ? ItemContainerGenerator.ContainerFromIndex(SelectedIndex) : null;
+ var from = SelectedIndex != -1 ? ItemContainerGenerator?.ContainerFromIndex(SelectedIndex) : null;
return MoveSelection(from, direction, wrap);
}
@@ -610,7 +626,7 @@ namespace Avalonia.Controls.Primitives
if (Presenter?.Panel is INavigableContainer container &&
GetNextControl(container, direction, from, wrap) is IControl next)
{
- var index = ItemContainerGenerator.IndexFromContainer(next);
+ var index = ItemContainerGenerator?.IndexFromContainer(next) ?? -1;
if (index != -1)
{
@@ -688,7 +704,7 @@ namespace Avalonia.Controls.Primitives
if (Presenter?.Panel != null)
{
- var container = ItemContainerGenerator.ContainerFromIndex(index);
+ var container = ItemContainerGenerator?.ContainerFromIndex(index);
KeyboardNavigation.SetTabOnceActiveElement(
(InputElement)Presenter.Panel,
container);
@@ -755,7 +771,7 @@ namespace Avalonia.Controls.Primitives
///
/// The sender.
/// The event args.
- private void OnSelectionModelPropertyChanged(object sender, PropertyChangedEventArgs e)
+ private void OnSelectionModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(ISelectionModel.AnchorIndex))
{
@@ -789,11 +805,11 @@ namespace Avalonia.Controls.Primitives
///
/// The sender.
/// The event args.
- private void OnSelectionModelSelectionChanged(object sender, SelectionModelSelectionChangedEventArgs e)
+ private void OnSelectionModelSelectionChanged(object? sender, SelectionModelSelectionChangedEventArgs e)
{
void Mark(int index, bool selected)
{
- var container = ItemContainerGenerator.ContainerFromIndex(index);
+ var container = ItemContainerGenerator?.ContainerFromIndex(index);
if (container != null)
{
@@ -829,7 +845,7 @@ namespace Avalonia.Controls.Primitives
///
/// The sender.
/// The event args.
- private void OnSelectionModelLostSelection(object sender, EventArgs e)
+ private void OnSelectionModelLostSelection(object? sender, EventArgs e)
{
if (AlwaysSelected && Items is object)
{
@@ -1034,7 +1050,7 @@ namespace Avalonia.Controls.Primitives
_textSearchTimer = null;
}
- private void TextSearchTimer_Tick(object sender, EventArgs e)
+ private void TextSearchTimer_Tick(object? sender, EventArgs e)
{
_textSearchTerm = string.Empty;
StopTextSearchTimer();
diff --git a/src/Avalonia.Controls/Primitives/TemplatedControl.cs b/src/Avalonia.Controls/Primitives/TemplatedControl.cs
index 59975b072d..af681d6930 100644
--- a/src/Avalonia.Controls/Primitives/TemplatedControl.cs
+++ b/src/Avalonia.Controls/Primitives/TemplatedControl.cs
@@ -6,8 +6,6 @@ using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.Styling;
-#nullable enable
-
namespace Avalonia.Controls.Primitives
{
///
@@ -109,7 +107,7 @@ namespace Avalonia.Controls.Primitives
///
/// Raised when the control's template is applied.
///
- public event EventHandler TemplateApplied
+ public event EventHandler? TemplateApplied
{
add { AddHandler(TemplateAppliedEvent, value); }
remove { RemoveHandler(TemplateAppliedEvent, value); }
diff --git a/src/Avalonia.Controls/Primitives/Thumb.cs b/src/Avalonia.Controls/Primitives/Thumb.cs
index 91141058e4..cb3195cf52 100644
--- a/src/Avalonia.Controls/Primitives/Thumb.cs
+++ b/src/Avalonia.Controls/Primitives/Thumb.cs
@@ -26,19 +26,19 @@ namespace Avalonia.Controls.Primitives
DragCompletedEvent.AddClassHandler((x, e) => x.OnDragCompleted(e), RoutingStrategies.Bubble);
}
- public event EventHandler DragStarted
+ public event EventHandler? DragStarted
{
add { AddHandler(DragStartedEvent, value); }
remove { RemoveHandler(DragStartedEvent, value); }
}
- public event EventHandler DragDelta
+ public event EventHandler? DragDelta
{
add { AddHandler(DragDeltaEvent, value); }
remove { RemoveHandler(DragDeltaEvent, value); }
}
- public event EventHandler DragCompleted
+ public event EventHandler? DragCompleted
{
add { AddHandler(DragCompletedEvent, value); }
remove { RemoveHandler(DragCompletedEvent, value); }
diff --git a/src/Avalonia.Controls/Primitives/ToggleButton.cs b/src/Avalonia.Controls/Primitives/ToggleButton.cs
index 6b2c566422..4bdf6db2fc 100644
--- a/src/Avalonia.Controls/Primitives/ToggleButton.cs
+++ b/src/Avalonia.Controls/Primitives/ToggleButton.cs
@@ -61,7 +61,7 @@ namespace Avalonia.Controls.Primitives
///
/// Raised when a is checked.
///
- public event EventHandler Checked
+ public event EventHandler? Checked
{
add => AddHandler(CheckedEvent, value);
remove => RemoveHandler(CheckedEvent, value);
@@ -70,7 +70,7 @@ namespace Avalonia.Controls.Primitives
///
/// Raised when a is unchecked.
///
- public event EventHandler Unchecked
+ public event EventHandler? Unchecked
{
add => AddHandler(UncheckedEvent, value);
remove => RemoveHandler(UncheckedEvent, value);
@@ -79,7 +79,7 @@ namespace Avalonia.Controls.Primitives
///
/// Raised when a is neither checked nor unchecked.
///
- public event EventHandler Indeterminate
+ public event EventHandler? Indeterminate
{
add => AddHandler(IndeterminateEvent, value);
remove => RemoveHandler(IndeterminateEvent, value);
diff --git a/src/Avalonia.Controls/Primitives/Track.cs b/src/Avalonia.Controls/Primitives/Track.cs
index 9399f5fb31..f8d6046101 100644
--- a/src/Avalonia.Controls/Primitives/Track.cs
+++ b/src/Avalonia.Controls/Primitives/Track.cs
@@ -403,8 +403,8 @@ namespace Avalonia.Controls.Primitives
private void ThumbChanged(AvaloniaPropertyChangedEventArgs e)
{
- var oldThumb = (Thumb)e.OldValue;
- var newThumb = (Thumb)e.NewValue;
+ var oldThumb = (Thumb?)e.OldValue;
+ var newThumb = (Thumb?)e.NewValue;
if (oldThumb != null)
{
@@ -424,8 +424,8 @@ namespace Avalonia.Controls.Primitives
private void ButtonChanged(AvaloniaPropertyChangedEventArgs e)
{
- var oldButton = (Button)e.OldValue;
- var newButton = (Button)e.NewValue;
+ var oldButton = (Button?)e.OldValue;
+ var newButton = (Button?)e.NewValue;
if (oldButton != null)
{
@@ -440,7 +440,7 @@ namespace Avalonia.Controls.Primitives
}
}
- private void ThumbDragged(object sender, VectorEventArgs e)
+ private void ThumbDragged(object? sender, VectorEventArgs e)
{
if (IsThumbDragHandled)
return;
diff --git a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs
index 03a84e26f2..df4edbd252 100644
--- a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs
+++ b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Controls.Primitives
private const int LightDismissOverlayZIndex = int.MaxValue - 98;
private const int OverlayZIndex = int.MaxValue - 97;
- private ILogicalRoot _logicalRoot;
+ private ILogicalRoot? _logicalRoot;
private readonly List _layers = new List();
public static readonly StyledProperty ChromeOverlayLayerProperty =
@@ -50,7 +50,7 @@ namespace Avalonia.Controls.Primitives
}
}
- public OverlayLayer OverlayLayer
+ public OverlayLayer? OverlayLayer
{
get
{
@@ -81,7 +81,7 @@ namespace Avalonia.Controls.Primitives
}
}
- T FindLayer() where T : class
+ T? FindLayer() where T : class
{
foreach (var layer in _layers)
if (layer is T match)
@@ -97,7 +97,7 @@ namespace Avalonia.Controls.Primitives
VisualChildren.Add(layer);
if (((ILogical)this).IsAttachedToLogicalTree)
((ILogical)layer).NotifyAttachedToLogicalTree(
- new LogicalTreeAttachmentEventArgs(_logicalRoot, layer, this));
+ new LogicalTreeAttachmentEventArgs(_logicalRoot!, layer, this));
InvalidateArrange();
}
diff --git a/src/Avalonia.Controls/ProgressBar.cs b/src/Avalonia.Controls/ProgressBar.cs
index a848901bc3..017a053c48 100644
--- a/src/Avalonia.Controls/ProgressBar.cs
+++ b/src/Avalonia.Controls/ProgressBar.cs
@@ -96,7 +96,7 @@ namespace Avalonia.Controls
private double _indeterminateStartingOffset;
private double _indeterminateEndingOffset;
- private Border _indicator;
+ private Border? _indicator;
public static readonly StyledProperty IsIndeterminateProperty =
AvaloniaProperty.Register(nameof(IsIndeterminate));
diff --git a/src/Avalonia.Controls/Properties/AssemblyInfo.cs b/src/Avalonia.Controls/Properties/AssemblyInfo.cs
index d1743611cd..05561a38ef 100644
--- a/src/Avalonia.Controls/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.Controls/Properties/AssemblyInfo.cs
@@ -3,6 +3,7 @@ using Avalonia.Metadata;
[assembly: InternalsVisibleTo("Avalonia.Controls.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
[assembly: InternalsVisibleTo("Avalonia.DesignerSupport, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
+[assembly: InternalsVisibleTo("Avalonia.LeakTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")]
diff --git a/src/Avalonia.Controls/RadioButton.cs b/src/Avalonia.Controls/RadioButton.cs
index 681278d247..9dbc5f040e 100644
--- a/src/Avalonia.Controls/RadioButton.cs
+++ b/src/Avalonia.Controls/RadioButton.cs
@@ -22,7 +22,7 @@ namespace Avalonia.Controls
readonly Dictionary>> s_registeredGroups
= new Dictionary>>();
- public static RadioButtonGroupManager GetOrCreateForRoot(IRenderRoot root)
+ public static RadioButtonGroupManager GetOrCreateForRoot(IRenderRoot? root)
{
if (root == null)
return Default;
@@ -33,7 +33,7 @@ namespace Avalonia.Controls
{
lock (s_registeredGroups)
{
- string groupName = radioButton.GroupName;
+ string groupName = radioButton.GroupName!;
if (!s_registeredGroups.TryGetValue(groupName, out var group))
{
group = new List>();
@@ -71,7 +71,7 @@ namespace Avalonia.Controls
{
lock (s_registeredGroups)
{
- string groupName = radioButton.GroupName;
+ string groupName = radioButton.GroupName!;
if (s_registeredGroups.TryGetValue(groupName, out var group))
{
int i = 0;
@@ -95,21 +95,21 @@ namespace Avalonia.Controls
}
}
- public static readonly DirectProperty GroupNameProperty =
- AvaloniaProperty.RegisterDirect(
+ public static readonly DirectProperty GroupNameProperty =
+ AvaloniaProperty.RegisterDirect(
nameof(GroupName),
o => o.GroupName,
(o, v) => o.GroupName = v);
- private string _groupName;
- private RadioButtonGroupManager _groupManager;
+ private string? _groupName;
+ private RadioButtonGroupManager? _groupManager;
public RadioButton()
{
this.GetObservable(IsCheckedProperty).Subscribe(IsCheckedChanged);
}
- public string GroupName
+ public string? GroupName
{
get { return _groupName; }
set { SetGroupName(value); }
@@ -127,7 +127,7 @@ namespace Avalonia.Controls
{
if (!string.IsNullOrEmpty(GroupName))
{
- _groupManager?.Remove(this, _groupName);
+ _groupManager?.Remove(this, GroupName);
_groupManager = RadioButtonGroupManager.GetOrCreateForRoot(e.Root);
@@ -142,13 +142,13 @@ namespace Avalonia.Controls
if (!string.IsNullOrEmpty(GroupName))
{
- _groupManager?.Remove(this, _groupName);
+ _groupManager?.Remove(this, GroupName);
}
}
- private void SetGroupName(string newGroupName)
+ private void SetGroupName(string? newGroupName)
{
- string oldGroupName = GroupName;
+ var oldGroupName = GroupName;
if (newGroupName != oldGroupName)
{
if (!string.IsNullOrEmpty(oldGroupName))
@@ -169,7 +169,7 @@ namespace Avalonia.Controls
private void IsCheckedChanged(bool? value)
{
- string groupName = GroupName;
+ var groupName = GroupName;
if (string.IsNullOrEmpty(groupName))
{
var parent = this.GetVisualParent();
diff --git a/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs b/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
index 562b104b04..18cf96ddca 100644
--- a/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
+++ b/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
@@ -1,7 +1,5 @@
using Avalonia.Layout;
-#nullable enable
-
namespace Avalonia.Controls
{
public partial class RelativePanel
diff --git a/src/Avalonia.Controls/RelativePanel.cs b/src/Avalonia.Controls/RelativePanel.cs
index c5de004f09..1125f0eb0e 100644
--- a/src/Avalonia.Controls/RelativePanel.cs
+++ b/src/Avalonia.Controls/RelativePanel.cs
@@ -4,8 +4,6 @@ using System.Collections.Generic;
using System.Linq;
using Avalonia.Layout;
-#nullable enable
-
namespace Avalonia.Controls
{
///
diff --git a/src/Avalonia.Controls/Remote/RemoteServer.cs b/src/Avalonia.Controls/Remote/RemoteServer.cs
index 419792f004..f4cc91a0e6 100644
--- a/src/Avalonia.Controls/Remote/RemoteServer.cs
+++ b/src/Avalonia.Controls/Remote/RemoteServer.cs
@@ -24,7 +24,7 @@ namespace Avalonia.Controls.Remote
//TODO: Somehow react on closed connection?
}
- public object Content
+ public object? Content
{
get => _topLevel.Content;
set => _topLevel.Content = value;
diff --git a/src/Avalonia.Controls/Remote/RemoteWidget.cs b/src/Avalonia.Controls/Remote/RemoteWidget.cs
index b839a8769a..a88e0fd3d8 100644
--- a/src/Avalonia.Controls/Remote/RemoteWidget.cs
+++ b/src/Avalonia.Controls/Remote/RemoteWidget.cs
@@ -18,8 +18,8 @@ namespace Avalonia.Controls.Remote
}
private readonly IAvaloniaRemoteTransportConnection _connection;
- private FrameMessage _lastFrame;
- private WriteableBitmap _bitmap;
+ private FrameMessage? _lastFrame;
+ private WriteableBitmap? _bitmap;
public RemoteWidget(IAvaloniaRemoteTransportConnection connection)
{
Mode = SizingMode.Local;
diff --git a/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs b/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs
index 931c27c575..c9fd1dc3b8 100644
--- a/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs
+++ b/src/Avalonia.Controls/Remote/Server/RemoteServerTopLevelImpl.cs
@@ -21,22 +21,22 @@ namespace Avalonia.Controls.Remote.Server
public class RemoteServerTopLevelImpl : OffscreenTopLevelImplBase, IFramebufferPlatformSurface
{
private readonly IAvaloniaRemoteTransportConnection _transport;
- private LockedFramebuffer _framebuffer;
+ private LockedFramebuffer? _framebuffer;
private object _lock = new object();
private long _lastSentFrame = -1;
private long _lastReceivedFrame = -1;
private long _nextFrameNumber = 1;
- private ClientViewportAllocatedMessage _pendingAllocation;
+ private ClientViewportAllocatedMessage? _pendingAllocation;
private bool _invalidated;
private Vector _dpi = new Vector(96, 96);
- private ProtocolPixelFormat[] _supportedFormats;
+ private ProtocolPixelFormat[]? _supportedFormats;
public RemoteServerTopLevelImpl(IAvaloniaRemoteTransportConnection transport)
{
_transport = transport;
_transport.OnMessage += OnMessage;
- KeyboardDevice = AvaloniaLocator.Current.GetService();
+ KeyboardDevice = AvaloniaLocator.Current.GetRequiredService();
}
private static RawPointerEventType GetAvaloniaEventType (Avalonia.Remote.Protocol.Input.MouseButton button, bool pressed)
@@ -155,7 +155,7 @@ namespace Avalonia.Controls.Remote.Server
ClientViewportAllocatedMessage allocation;
lock (_lock)
{
- allocation = _pendingAllocation;
+ allocation = _pendingAllocation!;
_pendingAllocation = null;
}
_dpi = new Vector(allocation.DpiX, allocation.DpiY);
@@ -173,7 +173,7 @@ namespace Avalonia.Controls.Remote.Server
Input?.Invoke(new RawPointerEventArgs(
MouseDevice,
0,
- InputRoot,
+ InputRoot!,
RawPointerEventType.Move,
new Point(pointer.X, pointer.Y),
GetAvaloniaInputModifiers(pointer.Modifiers)));
@@ -186,7 +186,7 @@ namespace Avalonia.Controls.Remote.Server
Input?.Invoke(new RawPointerEventArgs(
MouseDevice,
0,
- InputRoot,
+ InputRoot!,
GetAvaloniaEventType(pressed.Button, true),
new Point(pressed.X, pressed.Y),
GetAvaloniaInputModifiers(pressed.Modifiers)));
@@ -199,7 +199,7 @@ namespace Avalonia.Controls.Remote.Server
Input?.Invoke(new RawPointerEventArgs(
MouseDevice,
0,
- InputRoot,
+ InputRoot!,
GetAvaloniaEventType(released.Button, false),
new Point(released.X, released.Y),
GetAvaloniaInputModifiers(released.Modifiers)));
@@ -212,7 +212,7 @@ namespace Avalonia.Controls.Remote.Server
Input?.Invoke(new RawMouseWheelEventArgs(
MouseDevice,
0,
- InputRoot,
+ InputRoot!,
new Point(scroll.X, scroll.Y),
new Vector(scroll.DeltaX, scroll.DeltaY),
GetAvaloniaInputModifiers(scroll.Modifiers)));
@@ -227,7 +227,7 @@ namespace Avalonia.Controls.Remote.Server
Input?.Invoke(new RawKeyEventArgs(
KeyboardDevice,
0,
- InputRoot,
+ InputRoot!,
key.IsDown ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
(Key)key.Key,
GetAvaloniaRawInputModifiers(key.Modifiers)));
@@ -242,7 +242,7 @@ namespace Avalonia.Controls.Remote.Server
Input?.Invoke(new RawTextInputEventArgs(
KeyboardDevice,
0,
- InputRoot,
+ InputRoot!,
text.Text));
}, DispatcherPriority.Input);
}
@@ -257,7 +257,7 @@ namespace Avalonia.Controls.Remote.Server
protected virtual Size Measure(Size constraint)
{
- var l = (ILayoutable) InputRoot;
+ var l = (ILayoutable) InputRoot!;
l.Measure(constraint);
return l.DesiredSize;
}
@@ -294,7 +294,7 @@ namespace Avalonia.Controls.Remote.Server
return new FrameMessage
{
Data = data,
- Format = (ProtocolPixelFormat) format,
+ Format = fmt,
Width = width,
Height = height,
Stride = width * bpp,
diff --git a/src/Avalonia.Controls/RepeatButton.cs b/src/Avalonia.Controls/RepeatButton.cs
index a21725cadf..0415a78721 100644
--- a/src/Avalonia.Controls/RepeatButton.cs
+++ b/src/Avalonia.Controls/RepeatButton.cs
@@ -21,7 +21,7 @@ namespace Avalonia.Controls
public static readonly StyledProperty DelayProperty =
AvaloniaProperty.Register(nameof(Delay), 300);
- private DispatcherTimer _repeatTimer;
+ private DispatcherTimer? _repeatTimer;
///
/// Gets or sets the amount of time, in milliseconds, of repeating clicks.
@@ -55,10 +55,10 @@ namespace Avalonia.Controls
_repeatTimer.Start();
}
- private void RepeatTimerOnTick(object sender, EventArgs e)
+ private void RepeatTimerOnTick(object? sender, EventArgs e)
{
var interval = TimeSpan.FromMilliseconds(Interval);
- if (_repeatTimer.Interval != interval)
+ if (_repeatTimer!.Interval != interval)
{
_repeatTimer.Interval = interval;
}
diff --git a/src/Avalonia.Controls/Repeater/ElementFactory.cs b/src/Avalonia.Controls/Repeater/ElementFactory.cs
index 644e077221..6b776803d7 100644
--- a/src/Avalonia.Controls/Repeater/ElementFactory.cs
+++ b/src/Avalonia.Controls/Repeater/ElementFactory.cs
@@ -4,7 +4,7 @@ namespace Avalonia.Controls
{
public abstract class ElementFactory : IElementFactory
{
- public IControl Build(object data)
+ public IControl Build(object? data)
{
return GetElementCore(new ElementFactoryGetArgs { Data = data });
}
@@ -14,7 +14,7 @@ namespace Avalonia.Controls
return GetElementCore(args);
}
- public bool Match(object data) => true;
+ public bool Match(object? data) => true;
public void RecycleElement(ElementFactoryRecycleArgs args)
{
diff --git a/src/Avalonia.Controls/Repeater/IElementFactory.cs b/src/Avalonia.Controls/Repeater/IElementFactory.cs
index f424ae29b7..daab7e855f 100644
--- a/src/Avalonia.Controls/Repeater/IElementFactory.cs
+++ b/src/Avalonia.Controls/Repeater/IElementFactory.cs
@@ -12,13 +12,13 @@ namespace Avalonia.Controls
/// Gets or sets the data item for which an appropriate element tree should be realized
/// when calling .
///
- public object Data { get; set; }
+ public object? Data { get; set; }
///
/// Gets or sets the that is expected to be the parent of the
/// realized element from .
///
- public IControl Parent { get; set; }
+ public IControl? Parent { get; set; }
///
/// Gets or sets the index of the item that should be realized.
@@ -36,13 +36,13 @@ namespace Avalonia.Controls
/// Gets or sets the to recycle when calling
/// .
///
- public IControl Element { get; set; }
+ public IControl? Element { get; set; }
///
/// Gets or sets the that is expected to be the parent of the
/// realized element from .
///
- public IControl Parent { get; set; }
+ public IControl? Parent { get; set; }
}
///
diff --git a/src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs b/src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs
index dd97cde218..eb3b2ea787 100644
--- a/src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs
+++ b/src/Avalonia.Controls/Repeater/ItemTemplateWrapper.cs
@@ -13,8 +13,8 @@ namespace Avalonia.Controls
public ItemTemplateWrapper(IDataTemplate dataTemplate) => _dataTemplate = dataTemplate;
- public IControl Build(object param) => GetElement(null, param);
- public bool Match(object data) => _dataTemplate.Match(data);
+ public IControl Build(object? param) => GetElement(null, param);
+ public bool Match(object? data) => _dataTemplate.Match(data);
public IControl GetElement(ElementFactoryGetArgs args)
{
@@ -23,14 +23,14 @@ namespace Avalonia.Controls
public void RecycleElement(ElementFactoryRecycleArgs args)
{
- RecycleElement(args.Parent, args.Element);
+ RecycleElement(args.Parent, args.Element!);
}
- private IControl GetElement(IControl parent, object data)
+ private IControl GetElement(IControl? parent, object? data)
{
var selectedTemplate = _dataTemplate;
var recyclePool = RecyclePool.GetPoolInstance(selectedTemplate);
- IControl element = null;
+ IControl? element = null;
if (recyclePool != null)
{
@@ -41,7 +41,7 @@ namespace Avalonia.Controls
if (element == null)
{
// no element was found in recycle pool, create a new element
- element = selectedTemplate.Build(data);
+ element = selectedTemplate.Build(data)!;
// Associate template with element
element.SetValue(RecyclePool.OriginTemplateProperty, selectedTemplate);
@@ -50,7 +50,7 @@ namespace Avalonia.Controls
return element;
}
- private void RecycleElement(IControl parent, IControl element)
+ private void RecycleElement(IControl? parent, IControl element)
{
var selectedTemplate = _dataTemplate;
var recyclePool = RecyclePool.GetPoolInstance(selectedTemplate);
diff --git a/src/Avalonia.Controls/Repeater/ItemsRepeater.cs b/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
index b40cf26df5..09c0e58332 100644
--- a/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
+++ b/src/Avalonia.Controls/Repeater/ItemsRepeater.cs
@@ -31,13 +31,13 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty ItemTemplateProperty =
+ public static readonly StyledProperty ItemTemplateProperty =
ItemsControl.ItemTemplateProperty.AddOwner();
///
/// Defines the property.
///
- public static readonly DirectProperty ItemsProperty =
+ public static readonly DirectProperty ItemsProperty =
ItemsControl.ItemsProperty.AddOwner(o => o.Items, (o, v) => o.Items = v);
///
@@ -60,14 +60,14 @@ namespace Avalonia.Controls
private readonly ViewManager _viewManager;
private readonly ViewportManager _viewportManager;
- private IEnumerable _items;
- private VirtualizingLayoutContext _layoutContext;
- private EventHandler _childIndexChanged;
+ private IEnumerable? _items;
+ private VirtualizingLayoutContext? _layoutContext;
+ private EventHandler? _childIndexChanged;
private bool _isLayoutInProgress;
- private NotifyCollectionChangedEventArgs _processingItemsSourceChange;
- private ItemsRepeaterElementPreparedEventArgs _elementPreparedArgs;
- private ItemsRepeaterElementClearingEventArgs _elementClearingArgs;
- private ItemsRepeaterElementIndexChangedEventArgs _elementIndexChangedArgs;
+ private NotifyCollectionChangedEventArgs? _processingItemsSourceChange;
+ private ItemsRepeaterElementPreparedEventArgs? _elementPreparedArgs;
+ private ItemsRepeaterElementClearingEventArgs? _elementClearingArgs;
+ private ItemsRepeaterElementIndexChangedEventArgs? _elementIndexChangedArgs;
///
/// Initializes a new instance of the class.
@@ -102,7 +102,7 @@ namespace Avalonia.Controls
///
/// Gets or sets an object source used to generate the content of the ItemsRepeater.
///
- public IEnumerable Items
+ public IEnumerable? Items
{
get => _items;
set => SetAndRaise(ItemsProperty, ref _items, value);
@@ -111,7 +111,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the template used to display each item.
///
- public IDataTemplate ItemTemplate
+ public IDataTemplate? ItemTemplate
{
get => GetValue(ItemTemplateProperty);
set => SetValue(ItemTemplateProperty, value);
@@ -141,14 +141,14 @@ namespace Avalonia.Controls
/// Gets a standardized view of the supported interactions between a given Items object and
/// the ItemsRepeater control and its associated components.
///
- public ItemsSourceView ItemsSourceView { get; private set; }
+ public ItemsSourceView? ItemsSourceView { get; private set; }
- internal IElementFactory ItemTemplateShim { get; set; }
+ internal IElementFactory? ItemTemplateShim { get; set; }
internal Point LayoutOrigin { get; set; }
- internal object LayoutState { get; set; }
- internal IControl MadeAnchor => _viewportManager.MadeAnchor;
+ internal object? LayoutState { get; set; }
+ internal IControl? MadeAnchor => _viewportManager.MadeAnchor;
internal Rect RealizationWindow => _viewportManager.GetLayoutRealizationWindow();
- internal IControl SuggestedAnchor => _viewportManager.SuggestedAnchor;
+ internal IControl? SuggestedAnchor => _viewportManager.SuggestedAnchor;
private bool IsProcessingCollectionChange => _processingItemsSourceChange != null;
@@ -165,7 +165,7 @@ namespace Avalonia.Controls
}
}
- event EventHandler IChildIndexProvider.ChildIndexChanged
+ event EventHandler? IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
@@ -180,7 +180,7 @@ namespace Avalonia.Controls
bool IChildIndexProvider.TryGetTotalCount(out int count)
{
- count = ItemsSourceView.Count;
+ count = ItemsSourceView?.Count ?? 0;
return true;
}
@@ -192,7 +192,7 @@ namespace Avalonia.Controls
/// outside the range of realized items. Elements are cleared when they become available
/// for re-use.
///
- public event EventHandler ElementClearing;
+ public event EventHandler? ElementClearing;
///
/// Occurs for each realized when the index for the item it
@@ -207,7 +207,7 @@ namespace Avalonia.Controls
/// represents has changed. For example, when another item is added or removed in the data
/// source, the index for items that come after in the ordering will be impacted.
///
- public event EventHandler ElementIndexChanged;
+ public event EventHandler? ElementIndexChanged;
///
/// Occurs each time an element is prepared for use.
@@ -216,7 +216,7 @@ namespace Avalonia.Controls
/// The prepared element might be newly created or an existing element that is being re-
/// used.
///
- public event EventHandler ElementPrepared;
+ public event EventHandler? ElementPrepared;
///
/// Retrieves the index of the item from the data source that corresponds to the specified
@@ -240,7 +240,7 @@ namespace Avalonia.Controls
/// he UIElement that corresponds to the item at the specified index if the item is
/// realized, or null if the item is not realized.
///
- public IControl TryGetElement(int index) => GetElementFromIndexImpl(index);
+ public IControl? TryGetElement(int index) => GetElementFromIndexImpl(index);
///
/// Retrieves the UIElement that corresponds to the item at the specified index in the
@@ -497,9 +497,9 @@ namespace Avalonia.Controls
return -1;
}
- private IControl GetElementFromIndexImpl(int index)
+ private IControl? GetElementFromIndexImpl(int index)
{
- IControl result = null;
+ IControl? result = null;
var children = Children;
for (var i = 0; i < children.Count && result == null; ++i)
@@ -517,7 +517,7 @@ namespace Avalonia.Controls
private IControl GetOrCreateElementImpl(int index)
{
- if (index >= 0 && index >= ItemsSourceView.Count)
+ if (index >= 0 && index >= (ItemsSourceView?.Count ?? 0))
{
throw new ArgumentException("Argument index is invalid.", "index");
}
@@ -544,7 +544,7 @@ namespace Avalonia.Controls
_viewportManager.OnMakeAnchor(element, isAnchorOutsideRealizedRange);
InvalidateMeasure();
- return element;
+ return element!;
}
internal void OnElementPrepared(IControl element, VirtualizationInfo virtInfo)
@@ -608,7 +608,7 @@ namespace Avalonia.Controls
_childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs(element));
}
- private void OnDataSourcePropertyChanged(ItemsSourceView oldValue, ItemsSourceView newValue)
+ private void OnDataSourcePropertyChanged(ItemsSourceView? oldValue, ItemsSourceView? newValue)
{
if (_isLayoutInProgress)
{
@@ -664,7 +664,7 @@ namespace Avalonia.Controls
}
}
- private void OnItemTemplateChanged(IDataTemplate oldValue, IDataTemplate newValue)
+ private void OnItemTemplateChanged(IDataTemplate? oldValue, IDataTemplate? newValue)
{
if (_isLayoutInProgress && oldValue != null)
{
@@ -705,12 +705,17 @@ namespace Avalonia.Controls
}
}
- ItemTemplateShim = newValue as IElementFactory ?? new ItemTemplateWrapper(newValue);
+ ItemTemplateShim = newValue switch
+ {
+ IElementFactory factory => factory,
+ null => null,
+ _ => new ItemTemplateWrapper(newValue)
+ };
InvalidateMeasure();
}
- private void OnLayoutChanged(AttachedLayout oldValue, AttachedLayout newValue)
+ private void OnLayoutChanged(AttachedLayout? oldValue, AttachedLayout? newValue)
{
if (_isLayoutInProgress)
{
@@ -751,7 +756,7 @@ namespace Avalonia.Controls
InvalidateMeasure();
}
- private void OnItemsSourceViewChanged(object sender, NotifyCollectionChangedEventArgs args)
+ private void OnItemsSourceViewChanged(object? sender, NotifyCollectionChangedEventArgs args)
{
if (_isLayoutInProgress)
{
diff --git a/src/Avalonia.Controls/Repeater/RecyclePool.cs b/src/Avalonia.Controls/Repeater/RecyclePool.cs
index 28f299043c..9e2da81f99 100644
--- a/src/Avalonia.Controls/Repeater/RecyclePool.cs
+++ b/src/Avalonia.Controls/Repeater/RecyclePool.cs
@@ -22,7 +22,7 @@ namespace Avalonia.Controls
private static ConditionalWeakTable s_pools = new ConditionalWeakTable();
private readonly Dictionary> _elements = new Dictionary>();
- public static RecyclePool GetPoolInstance(IDataTemplate dataTemplate)
+ public static RecyclePool? GetPoolInstance(IDataTemplate dataTemplate)
{
s_pools.TryGetValue(dataTemplate, out var result);
return result;
@@ -30,7 +30,7 @@ namespace Avalonia.Controls
public static void SetPoolInstance(IDataTemplate dataTemplate, RecyclePool value) => s_pools.Add(dataTemplate, value);
- public void PutElement(IControl element, string key, IControl owner)
+ public void PutElement(IControl element, string key, IControl? owner)
{
var ownerAsPanel = EnsureOwnerIsPanelOrNull(owner);
var elementInfo = new ElementInfo(element, ownerAsPanel);
@@ -44,7 +44,7 @@ namespace Avalonia.Controls
pool.Add(elementInfo);
}
- public IControl TryGetElement(string key, IControl owner)
+ public IControl? TryGetElement(string key, IControl? owner)
{
if (_elements.TryGetValue(key, out var elements))
{
@@ -54,10 +54,10 @@ namespace Avalonia.Controls
// the enter/leave cost during recycling.
// TODO: prioritize elements with the same owner to those without an owner.
var elementInfo = elements.FirstOrDefault(x => x.Owner == owner) ?? elements.LastOrDefault();
- elements.Remove(elementInfo);
+ elements.Remove(elementInfo!);
var ownerAsPanel = EnsureOwnerIsPanelOrNull(owner);
- if (elementInfo.Owner != null && elementInfo.Owner != ownerAsPanel)
+ if (elementInfo!.Owner != null && elementInfo.Owner != ownerAsPanel)
{
// Element is still under its parent. remove it from its parent.
var panel = elementInfo.Owner;
@@ -83,7 +83,7 @@ namespace Avalonia.Controls
internal string GetReuseKey(IControl element) => element.GetValue(ReuseKeyProperty);
internal void SetReuseKey(IControl element, string value) => element.SetValue(ReuseKeyProperty, value);
- private IPanel EnsureOwnerIsPanelOrNull(IControl owner)
+ private IPanel? EnsureOwnerIsPanelOrNull(IControl? owner)
{
if (owner is IPanel panel)
{
@@ -99,14 +99,14 @@ namespace Avalonia.Controls
private class ElementInfo
{
- public ElementInfo(IControl element, IPanel owner)
+ public ElementInfo(IControl element, IPanel? owner)
{
Element = element;
Owner = owner;
}
public IControl Element { get; }
- public IPanel Owner { get;}
+ public IPanel? Owner { get;}
}
}
}
diff --git a/src/Avalonia.Controls/Repeater/RecyclingElementFactory.cs b/src/Avalonia.Controls/Repeater/RecyclingElementFactory.cs
index 9503239e34..c1baa66433 100644
--- a/src/Avalonia.Controls/Repeater/RecyclingElementFactory.cs
+++ b/src/Avalonia.Controls/Repeater/RecyclingElementFactory.cs
@@ -3,8 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using Avalonia.Controls.Templates;
-#nullable enable
-
namespace Avalonia.Controls
{
public class SelectTemplateEventArgs : EventArgs
@@ -71,7 +69,7 @@ namespace Avalonia.Controls
}
var dataTemplate = Templates[templateKey];
- element = dataTemplate.Build(args.Data);
+ element = dataTemplate.Build(args.Data)!;
// Associate ReuseKey with element
RecyclePool.SetReuseKey(element, templateKey);
@@ -82,12 +80,12 @@ namespace Avalonia.Controls
protected override void RecycleElementCore(ElementFactoryRecycleArgs args)
{
- var element = args.Element;
+ var element = args.Element!;
var key = RecyclePool.GetReuseKey(element);
RecyclePool.PutElement(element, key, args.Parent);
}
- protected virtual string OnSelectTemplateKeyCore(object dataContext, IControl owner)
+ protected virtual string OnSelectTemplateKeyCore(object? dataContext, IControl? owner)
{
if (SelectTemplateKey is object)
{
diff --git a/src/Avalonia.Controls/Repeater/RepeaterLayoutContext.cs b/src/Avalonia.Controls/Repeater/RepeaterLayoutContext.cs
index 733b045e1b..3370b36801 100644
--- a/src/Avalonia.Controls/Repeater/RepeaterLayoutContext.cs
+++ b/src/Avalonia.Controls/Repeater/RepeaterLayoutContext.cs
@@ -26,7 +26,7 @@ namespace Avalonia.Controls
set => _owner.LayoutOrigin = value;
}
- protected override object LayoutStateCore
+ protected override object? LayoutStateCore
{
get => _owner.LayoutState;
set => _owner.LayoutState = value;
@@ -57,7 +57,7 @@ namespace Avalonia.Controls
options.HasAllFlags(ElementRealizationOptions.SuppressAutoRecycle));
}
- protected override object GetItemAtCore(int index) => _owner.ItemsSourceView.GetAt(index);
+ protected override object GetItemAtCore(int index) => _owner.ItemsSourceView!.GetAt(index)!;
protected override void RecycleElementCore(ILayoutable element)
{
diff --git a/src/Avalonia.Controls/Repeater/UniqueIdElementPool.cs b/src/Avalonia.Controls/Repeater/UniqueIdElementPool.cs
index 775aa3f113..778b8bebcc 100644
--- a/src/Avalonia.Controls/Repeater/UniqueIdElementPool.cs
+++ b/src/Avalonia.Controls/Repeater/UniqueIdElementPool.cs
@@ -20,7 +20,7 @@ namespace Avalonia.Controls
public void Add(IControl element)
{
var virtInfo = ItemsRepeater.GetVirtualizationInfo(element);
- var key = virtInfo.UniqueId;
+ var key = virtInfo.UniqueId!;
if (_elementMap.ContainsKey(key))
{
@@ -30,10 +30,10 @@ namespace Avalonia.Controls
_elementMap.Add(key, element);
}
- public IControl Remove(int index)
+ public IControl? Remove(int index)
{
// Check if there is already a element in the mapping and if so, use it.
- string key = _owner.ItemsSourceView.KeyFromIndex(index);
+ string key = _owner.ItemsSourceView!.KeyFromIndex(index);
if (_elementMap.TryGetValue(key, out var element))
{
diff --git a/src/Avalonia.Controls/Repeater/ViewManager.cs b/src/Avalonia.Controls/Repeater/ViewManager.cs
index a7b6cf7f18..b28753b518 100644
--- a/src/Avalonia.Controls/Repeater/ViewManager.cs
+++ b/src/Avalonia.Controls/Repeater/ViewManager.cs
@@ -22,10 +22,10 @@ namespace Avalonia.Controls
private readonly ItemsRepeater _owner;
private readonly List _pinnedPool = new List();
private readonly UniqueIdElementPool _resetPool;
- private IControl _lastFocusedElement;
+ private IControl? _lastFocusedElement;
private bool _isDataSourceStableResetPending;
- private ElementFactoryGetArgs _elementFactoryGetArgs;
- private ElementFactoryRecycleArgs _elementFactoryRecycleArgs;
+ private ElementFactoryGetArgs? _elementFactoryGetArgs;
+ private ElementFactoryRecycleArgs? _elementFactoryRecycleArgs;
private int _firstRealizedElementIndexHeldByLayout = FirstRealizedElementIndexDefault;
private int _lastRealizedElementIndexHeldByLayout = LastRealizedElementIndexDefault;
private bool _eventsSubscribed;
@@ -170,7 +170,7 @@ namespace Avalonia.Controls
_lastFocusedElement = focusedChild;
// Add pin to hold the focused element.
- UpdatePin(focusedChild, true /* addPin */);
+ UpdatePin(focusedChild!, true /* addPin */);
}
else
{
@@ -179,14 +179,14 @@ namespace Avalonia.Controls
}
}
- IControl FindFocusCandidate(int clearedIndex, out IControl focusedChild)
+ IControl? FindFocusCandidate(int clearedIndex, out IControl? focusedChild)
{
// Walk through all the children and find elements with index before and after the cleared index.
// Note that during a delete the next element would now have the same index.
int previousIndex = int.MinValue;
int nextIndex = int.MaxValue;
- IControl nextElement = null;
- IControl previousElement = null;
+ IControl? nextElement = null;
+ IControl? previousElement = null;
foreach (var child in _owner.Children)
{
@@ -287,7 +287,7 @@ namespace Avalonia.Controls
}
}
- public void OnItemsSourceChanged(object sender, NotifyCollectionChangedEventArgs args)
+ public void OnItemsSourceChanged(object? sender, NotifyCollectionChangedEventArgs args)
{
// Note: For items that have been removed, the index will not be touched. It will hold
// the old index before it was removed. It is not valid anymore.
@@ -296,7 +296,7 @@ namespace Avalonia.Controls
case NotifyCollectionChangedAction.Add:
{
var newIndex = args.NewStartingIndex;
- var newCount = args.NewItems.Count;
+ var newCount = args.NewItems!.Count;
EnsureFirstLastRealizedIndices();
if (newIndex <= _lastRealizedElementIndexHeldByLayout)
{
@@ -343,8 +343,8 @@ namespace Avalonia.Controls
// depending on the counts.
var oldStartIndex = args.OldStartingIndex;
var newStartingIndex = args.NewStartingIndex;
- var oldCount = args.OldItems.Count;
- var newCount = args.NewItems.Count;
+ var oldCount = args.OldItems!.Count;
+ var newCount = args.NewItems!.Count;
if (oldStartIndex != newStartingIndex)
{
throw new NotSupportedException("Replace is only allowed with OldStartingIndex equals to NewStartingIndex.");
@@ -388,7 +388,7 @@ namespace Avalonia.Controls
case NotifyCollectionChangedAction.Remove:
{
var oldStartIndex = args.OldStartingIndex;
- var oldCount = args.OldItems.Count;
+ var oldCount = args.OldItems!.Count;
foreach (var element in _owner.Children)
{
var virtInfo = ItemsRepeater.GetVirtualizationInfo(element);
@@ -417,7 +417,7 @@ namespace Avalonia.Controls
// running layout, we dont have to clear all the elements again.
if (!_isDataSourceStableResetPending)
{
- if (_owner.ItemsSourceView.HasKeyIndexMapping)
+ if (_owner.ItemsSourceView!.HasKeyIndexMapping)
{
_isDataSourceStableResetPending = true;
}
@@ -482,9 +482,9 @@ namespace Avalonia.Controls
// If an index that is realized is requested by the layout, we unfortunately have to walk the
// children. Not ideal, but a reasonable default to provide consistent behavior between virtualizing
// and non-virtualizing hosts.
- private IControl GetElementIfAlreadyHeldByLayout(int index)
+ private IControl? GetElementIfAlreadyHeldByLayout(int index)
{
- IControl element = null;
+ IControl? element = null;
bool cachedFirstLastIndicesInvalid = _firstRealizedElementIndexHeldByLayout == FirstRealizedElementIndexDefault;
bool isRequestedIndexInRealizedRange = (_firstRealizedElementIndexHeldByLayout <= index && index <= _lastRealizedElementIndexHeldByLayout);
@@ -518,9 +518,9 @@ namespace Avalonia.Controls
return element;
}
- private IControl GetElementFromUniqueIdResetPool(int index)
+ private IControl? GetElementFromUniqueIdResetPool(int index)
{
- IControl element = null;
+ IControl? element = null;
// See if you can get it from the reset pool.
if (_isDataSourceStableResetPending)
{
@@ -541,9 +541,9 @@ namespace Avalonia.Controls
return element;
}
- private IControl GetElementFromPinnedElements(int index)
+ private IControl? GetElementFromPinnedElements(int index)
{
- IControl element = null;
+ IControl? element = null;
// See if you can find something among the pinned elements.
for (var i = 0; i < _pinnedPool.Count; ++i)
@@ -583,7 +583,7 @@ namespace Avalonia.Controls
private IControl GetElementFromElementFactory(int index)
{
// The view generator is the provider of last resort.
- var data = _owner.ItemsSourceView.GetAt(index);
+ var data = _owner.ItemsSourceView!.GetAt(index);
var providedElementFactory = _owner.ItemTemplateShim;
IElementFactory GetElementFactory()
@@ -592,7 +592,7 @@ namespace Avalonia.Controls
{
var factory = FuncDataTemplate.Default;
_owner.ItemTemplate = factory;
- return _owner.ItemTemplateShim;
+ return _owner.ItemTemplateShim!;
}
return providedElementFactory;
@@ -697,9 +697,9 @@ namespace Avalonia.Controls
private void UpdateFocusedElement()
{
- IControl focusedElement = null;
+ IControl? focusedElement = null;
- var child = FocusManager.Instance.Current;
+ var child = FocusManager.Instance?.Current;
if (child != null)
{
@@ -713,7 +713,9 @@ namespace Avalonia.Controls
if (parent is ItemsRepeater repeater)
{
var element = child as IControl;
- if (repeater == owner && ItemsRepeater.GetVirtualizationInfo(element).IsRealized)
+ if (repeater == owner &&
+ element is not null &&
+ ItemsRepeater.GetVirtualizationInfo(element).IsRealized)
{
focusedElement = element;
}
@@ -722,7 +724,7 @@ namespace Avalonia.Controls
}
child = parent as IInputElement;
- parent = child.VisualParent;
+ parent = child?.VisualParent;
}
}
@@ -744,7 +746,7 @@ namespace Avalonia.Controls
}
}
- private void OnFocusChanged(object sender, RoutedEventArgs e) => UpdateFocusedElement();
+ private void OnFocusChanged(object? sender, RoutedEventArgs e) => UpdateFocusedElement();
private void EnsureEventSubscriptions()
{
diff --git a/src/Avalonia.Controls/Repeater/ViewportManager.cs b/src/Avalonia.Controls/Repeater/ViewportManager.cs
index 1a90da5830..ec25fcb265 100644
--- a/src/Avalonia.Controls/Repeater/ViewportManager.cs
+++ b/src/Avalonia.Controls/Repeater/ViewportManager.cs
@@ -24,8 +24,8 @@ namespace Avalonia.Controls
private const double CacheBufferPerSideInflationPixelDelta = 40.0;
private readonly ItemsRepeater _owner;
private bool _ensuredScroller;
- private IScrollAnchorProvider _scroller;
- private IControl _makeAnchorElement;
+ private IScrollAnchorProvider? _scroller;
+ private IControl? _makeAnchorElement;
private bool _isAnchorOutsideRealizedRange;
private Rect _visibleWindow;
private Rect _layoutExtent;
@@ -57,7 +57,7 @@ namespace Avalonia.Controls
_owner = owner;
}
- public IControl SuggestedAnchor
+ public IControl? SuggestedAnchor
{
get
{
@@ -97,7 +97,7 @@ namespace Avalonia.Controls
public bool HasScroller => _scroller != null;
- public IControl MadeAnchor => _makeAnchorElement;
+ public IControl? MadeAnchor => _makeAnchorElement;
public double HorizontalCacheLength
{
@@ -213,7 +213,7 @@ namespace Avalonia.Controls
// We just finished a measure pass and have a new extent.
// Let's make sure the scrollers will run its arrange so that they track the anchor.
- ((IControl)_scroller)?.InvalidateArrange();
+ ((IControl?)_scroller)?.InvalidateArrange();
}
public Point GetOrigin() => _layoutExtent.TopLeft;
@@ -294,7 +294,7 @@ namespace Avalonia.Controls
}
}
- private void OnLayoutUpdated(object sender, EventArgs args)
+ private void OnLayoutUpdated(object? sender, EventArgs args)
{
_owner.LayoutUpdated -= OnLayoutUpdated;
_layoutUpdatedSubscribed = false;
@@ -324,7 +324,7 @@ namespace Avalonia.Controls
}
}
- public void OnMakeAnchor(IControl anchor, bool isAnchorOutsideRealizedRange)
+ public void OnMakeAnchor(IControl? anchor, bool isAnchorOutsideRealizedRange)
{
if (_makeAnchorElement != anchor)
{
@@ -346,7 +346,7 @@ namespace Avalonia.Controls
// get the targetChild - i.e the immediate child of this repeater that is being brought into view.
// Note that the element being brought into view could be a descendant.
- var targetChild = GetImmediateChildOfRepeater((IControl)args.TargetObject);
+ var targetChild = GetImmediateChildOfRepeater((IControl)args.TargetObject!);
if (targetChild is null)
{
@@ -382,14 +382,14 @@ namespace Avalonia.Controls
_scroller?.RegisterAnchorCandidate(element);
}
- private IControl GetImmediateChildOfRepeater(IControl descendant)
+ private IControl? GetImmediateChildOfRepeater(IControl descendant)
{
var targetChild = descendant;
- var parent = (IControl)descendant.VisualParent;
+ var parent = (IControl?)descendant.VisualParent;
while (parent != null && parent != _owner)
{
targetChild = parent;
- parent = (IControl)parent.VisualParent;
+ parent = (IControl?)parent.VisualParent;
}
if (parent == null)
@@ -441,7 +441,7 @@ namespace Avalonia.Controls
_ensuredScroller = false;
}
- private void OnEffectiveViewportChanged(object sender, EffectiveViewportChangedEventArgs e)
+ private void OnEffectiveViewportChanged(object? sender, EffectiveViewportChangedEventArgs e)
{
Logger.TryGet(LogEventLevel.Verbose, "Repeater")?.Log(this, "{LayoutId}: EffectiveViewportChanged event callback", _owner.Layout.LayoutId);
UpdateViewport(e.EffectiveViewport);
diff --git a/src/Avalonia.Controls/Repeater/VirtualizationInfo.cs b/src/Avalonia.Controls/Repeater/VirtualizationInfo.cs
index 7e6b24f1b5..7378dbcfa1 100644
--- a/src/Avalonia.Controls/Repeater/VirtualizationInfo.cs
+++ b/src/Avalonia.Controls/Repeater/VirtualizationInfo.cs
@@ -39,7 +39,7 @@ namespace Avalonia.Controls
public bool KeepAlive { get; set; }
public bool IsRegisteredAsAnchorCandidate { get; set; }
public ElementOwner Owner { get; private set; } = ElementOwner.ElementFactory;
- public string UniqueId { get; private set; }
+ public string? UniqueId { get; private set; }
public void MoveOwnershipToLayoutFromElementFactory(int index, string uniqueId)
{
diff --git a/src/Avalonia.Controls/RequestBringIntoViewEventArgs.cs b/src/Avalonia.Controls/RequestBringIntoViewEventArgs.cs
index dd55de85d4..5396ad67a7 100644
--- a/src/Avalonia.Controls/RequestBringIntoViewEventArgs.cs
+++ b/src/Avalonia.Controls/RequestBringIntoViewEventArgs.cs
@@ -5,7 +5,7 @@ namespace Avalonia.Controls
{
public class RequestBringIntoViewEventArgs : RoutedEventArgs
{
- public IVisual TargetObject { get; set; }
+ public IVisual? TargetObject { get; set; }
public Rect TargetRect { get; set; }
}
diff --git a/src/Avalonia.Controls/Screens.cs b/src/Avalonia.Controls/Screens.cs
index 8a0a0fa728..ef438576a7 100644
--- a/src/Avalonia.Controls/Screens.cs
+++ b/src/Avalonia.Controls/Screens.cs
@@ -9,20 +9,20 @@ namespace Avalonia.Controls
{
public class Screens
{
- private readonly IScreenImpl _iScreenImpl;
+ private readonly IScreenImpl? _iScreenImpl;
- public int ScreenCount => _iScreenImpl.ScreenCount;
+ public int ScreenCount => _iScreenImpl?.ScreenCount ?? 0;
public IReadOnlyList All => _iScreenImpl?.AllScreens ?? Array.Empty();
- public Screen Primary => All.FirstOrDefault(x => x.Primary);
+ public Screen? Primary => All.FirstOrDefault(x => x.Primary);
- public Screens(IScreenImpl iScreenImpl)
+ public Screens(IScreenImpl? iScreenImpl)
{
_iScreenImpl = iScreenImpl;
}
- public Screen ScreenFromBounds(PixelRect bounds){
+ public Screen? ScreenFromBounds(PixelRect bounds){
- Screen currMaxScreen = null;
+ Screen? currMaxScreen = null;
double maxAreaSize = 0;
foreach (Screen screen in All)
{
@@ -41,12 +41,12 @@ namespace Avalonia.Controls
return currMaxScreen;
}
- public Screen ScreenFromPoint(PixelPoint point)
+ public Screen? ScreenFromPoint(PixelPoint point)
{
return All.FirstOrDefault(x => x.Bounds.Contains(point));
}
- public Screen ScreenFromVisual(IVisual visual)
+ public Screen? ScreenFromVisual(IVisual visual)
{
var tl = visual.PointToScreen(visual.Bounds.TopLeft);
var br = visual.PointToScreen(visual.Bounds.BottomRight);
diff --git a/src/Avalonia.Controls/ScrollViewer.cs b/src/Avalonia.Controls/ScrollViewer.cs
index eee6216587..7c4b87e66a 100644
--- a/src/Avalonia.Controls/ScrollViewer.cs
+++ b/src/Avalonia.Controls/ScrollViewer.cs
@@ -181,6 +181,14 @@ namespace Avalonia.Controls
nameof(AllowAutoHide),
true);
+ ///
+ /// Defines the property.
+ ///
+ public static readonly AttachedProperty IsScrollChainingEnabledProperty =
+ AvaloniaProperty.RegisterAttached(
+ nameof(IsScrollChainingEnabled),
+ defaultValue: true);
+
///
/// Defines the event.
///
@@ -191,8 +199,8 @@ namespace Avalonia.Controls
internal const double DefaultSmallChange = 16;
- private IDisposable _childSubscription;
- private ILogicalScrollable _logicalScrollable;
+ private IDisposable? _childSubscription;
+ private ILogicalScrollable? _logicalScrollable;
private Size _extent;
private Vector _offset;
private Size _viewport;
@@ -202,7 +210,7 @@ namespace Avalonia.Controls
private Size _largeChange;
private Size _smallChange = new Size(DefaultSmallChange, DefaultSmallChange);
private bool _isExpanded;
- private IDisposable _scrollBarExpandSubscription;
+ private IDisposable? _scrollBarExpandSubscription;
///
/// Initializes static members of the class.
@@ -224,7 +232,7 @@ namespace Avalonia.Controls
///
/// Occurs when changes are detected to the scroll position, extent, or viewport size.
///
- public event EventHandler ScrollChanged
+ public event EventHandler? ScrollChanged
{
add => AddHandler(ScrollChangedEvent, value);
remove => RemoveHandler(ScrollChangedEvent, value);
@@ -332,7 +340,7 @@ namespace Avalonia.Controls
}
///
- public IControl CurrentAnchor => (Presenter as IScrollAnchorProvider)?.CurrentAnchor;
+ public IControl? CurrentAnchor => (Presenter as IScrollAnchorProvider)?.CurrentAnchor;
///
/// Gets the maximum horizontal scrollbar value.
@@ -418,6 +426,20 @@ namespace Avalonia.Controls
set => SetValue(AllowAutoHideProperty, value);
}
+ ///
+ /// Gets or sets if scroll chaining is enabled. The default value is true.
+ ///
+ ///
+ /// After a user hits a scroll limit on an element that has been nested within another scrollable element,
+ /// you can specify whether that parent element should continue the scrolling operation begun in its child element.
+ /// This is called scroll chaining.
+ ///
+ public bool IsScrollChainingEnabled
+ {
+ get => GetValue(IsScrollChainingEnabledProperty);
+ set => SetValue(IsScrollChainingEnabledProperty, value);
+ }
+
///
/// Scrolls the content up one line.
///
@@ -548,6 +570,36 @@ namespace Avalonia.Controls
return control.GetValue(AllowAutoHideProperty);
}
+ ///
+ /// Sets the value of the IsScrollChainingEnabled attached property.
+ ///
+ /// The control to set the value on.
+ /// The value of the property.
+ ///
+ /// After a user hits a scroll limit on an element that has been nested within another scrollable element,
+ /// you can specify whether that parent element should continue the scrolling operation begun in its child element.
+ /// This is called scroll chaining.
+ ///
+ public static void SetIsScrollChainingEnabled(Control control, bool value)
+ {
+ control.SetValue(IsScrollChainingEnabledProperty, value);
+ }
+
+ ///
+ /// Gets the value of the IsScrollChainingEnabled attached property.
+ ///
+ /// The control to read the value from.
+ /// The value of the property.
+ ///
+ /// After a user hits a scroll limit on an element that has been nested within another scrollable element,
+ /// you can specify whether that parent element should continue the scrolling operation begun in its child element.
+ /// This is called scroll chaining.
+ ///
+ public static bool GetIsScrollChainingEnabled(Control control)
+ {
+ return control.GetValue(IsScrollChainingEnabledProperty);
+ }
+
///
/// Gets the value of the VerticalScrollBarVisibility attached property.
///
@@ -604,7 +656,7 @@ namespace Avalonia.Controls
return double.IsNaN(result) ? 0 : result;
}
- private void ChildChanged(IControl child)
+ private void ChildChanged(IControl? child)
{
if (_logicalScrollable is object)
{
@@ -621,7 +673,7 @@ namespace Avalonia.Controls
CalculatedPropertiesChanged();
}
- private void LogicalScrollInvalidated(object sender, EventArgs e)
+ private void LogicalScrollInvalidated(object? sender, EventArgs e)
{
CalculatedPropertiesChanged();
}
@@ -710,9 +762,9 @@ namespace Avalonia.Controls
_scrollBarExpandSubscription = SubscribeToScrollBars(e);
}
- private IDisposable SubscribeToScrollBars(TemplateAppliedEventArgs e)
+ private IDisposable? SubscribeToScrollBars(TemplateAppliedEventArgs e)
{
- static IObservable GetExpandedObservable(ScrollBar scrollBar)
+ static IObservable? GetExpandedObservable(ScrollBar? scrollBar)
{
return scrollBar?.GetObservable(ScrollBar.IsExpandedProperty);
}
@@ -723,7 +775,7 @@ namespace Avalonia.Controls
var horizontalExpanded = GetExpandedObservable(horizontalScrollBar);
var verticalExpanded = GetExpandedObservable(verticalScrollBar);
- IObservable actualExpanded = null;
+ IObservable? actualExpanded = null;
if (horizontalExpanded != null && verticalExpanded != null)
{
@@ -749,7 +801,7 @@ namespace Avalonia.Controls
IsExpanded = isExpanded;
}
- private void OnLayoutUpdated(object sender, EventArgs e) => RaiseScrollChanged();
+ private void OnLayoutUpdated(object? sender, EventArgs e) => RaiseScrollChanged();
private void RaiseScrollChanged()
{
diff --git a/src/Avalonia.Controls/Selection/ISelectionModel.cs b/src/Avalonia.Controls/Selection/ISelectionModel.cs
index 3b8fd0c8b7..3f4ae48263 100644
--- a/src/Avalonia.Controls/Selection/ISelectionModel.cs
+++ b/src/Avalonia.Controls/Selection/ISelectionModel.cs
@@ -3,8 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
public interface ISelectionModel : INotifyPropertyChanged
diff --git a/src/Avalonia.Controls/Selection/IndexRange.cs b/src/Avalonia.Controls/Selection/IndexRange.cs
index fa7b44faea..dd3445fb70 100644
--- a/src/Avalonia.Controls/Selection/IndexRange.cs
+++ b/src/Avalonia.Controls/Selection/IndexRange.cs
@@ -6,8 +6,6 @@
using System;
using System.Collections.Generic;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
internal readonly struct IndexRange : IEquatable
diff --git a/src/Avalonia.Controls/Selection/InternalSelectionModel.cs b/src/Avalonia.Controls/Selection/InternalSelectionModel.cs
index 73c0184ebb..40c6f63ed8 100644
--- a/src/Avalonia.Controls/Selection/InternalSelectionModel.cs
+++ b/src/Avalonia.Controls/Selection/InternalSelectionModel.cs
@@ -6,8 +6,6 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Avalonia.Collections;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
internal class InternalSelectionModel : SelectionModel
@@ -174,7 +172,7 @@ namespace Avalonia.Controls.Selection
}
}
- private void OnSelectionChanged(object sender, SelectionModelSelectionChangedEventArgs e)
+ private void OnSelectionChanged(object? sender, SelectionModelSelectionChangedEventArgs e)
{
if (_ignoreModelChanges > 0)
{
@@ -227,9 +225,9 @@ namespace Avalonia.Controls.Selection
}
}
- private void OnSourceReset(object sender, EventArgs e) => SyncFromSelectedItems();
+ private void OnSourceReset(object? sender, EventArgs e) => SyncFromSelectedItems();
- private void OnSelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ private void OnSelectedItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (_ignoreSelectedItemsChanges)
{
@@ -243,7 +241,7 @@ namespace Avalonia.Controls.Selection
void Remove()
{
- foreach (var i in e.OldItems)
+ foreach (var i in e.OldItems!)
{
var index = IndexOf(Source, i);
@@ -263,14 +261,14 @@ namespace Avalonia.Controls.Selection
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
- Add(e.NewItems);
+ Add(e.NewItems!);
break;
case NotifyCollectionChangedAction.Remove:
Remove();
break;
case NotifyCollectionChangedAction.Replace:
Remove();
- Add(e.NewItems);
+ Add(e.NewItems!);
break;
case NotifyCollectionChangedAction.Reset:
Clear();
diff --git a/src/Avalonia.Controls/Selection/SelectedIndexes.cs b/src/Avalonia.Controls/Selection/SelectedIndexes.cs
index 36df175ed2..a65f45e64f 100644
--- a/src/Avalonia.Controls/Selection/SelectedIndexes.cs
+++ b/src/Avalonia.Controls/Selection/SelectedIndexes.cs
@@ -3,8 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
internal class SelectedIndexes : IReadOnlyList
diff --git a/src/Avalonia.Controls/Selection/SelectedItems.cs b/src/Avalonia.Controls/Selection/SelectedItems.cs
index 92781fd54a..4fbcfde438 100644
--- a/src/Avalonia.Controls/Selection/SelectedItems.cs
+++ b/src/Avalonia.Controls/Selection/SelectedItems.cs
@@ -3,8 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
internal class SelectedItems : IReadOnlyList
diff --git a/src/Avalonia.Controls/Selection/SelectionModel.cs b/src/Avalonia.Controls/Selection/SelectionModel.cs
index 138a765b43..154f1868f3 100644
--- a/src/Avalonia.Controls/Selection/SelectionModel.cs
+++ b/src/Avalonia.Controls/Selection/SelectionModel.cs
@@ -6,8 +6,6 @@ using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
public class SelectionModel : SelectionNodeBase, ISelectionModel
@@ -78,8 +76,7 @@ namespace Avalonia.Controls.Selection
public IReadOnlyList SelectedIndexes => _selectedIndexes ??= new SelectedIndexes(this);
- [MaybeNull, AllowNull]
- public T SelectedItem
+ public T? SelectedItem
{
get
{
@@ -89,7 +86,7 @@ namespace Avalonia.Controls.Selection
}
else if (_initSelectedItems is object && _initSelectedItems.Count > 0)
{
- return (T)_initSelectedItems[0];
+ return (T?)_initSelectedItems[0];
}
return default;
@@ -394,9 +391,7 @@ namespace Avalonia.Controls.Selection
{
if (SingleSelect)
{
-#pragma warning disable CS8604
- removed = new List { (T)items[SelectedIndex - index] };
-#pragma warning restore CS8604
+ removed = new List { (T)items[SelectedIndex - index]! };
}
_selectedIndex = GetFirstSelectedIndexFromRanges();
@@ -466,12 +461,12 @@ namespace Avalonia.Controls.Selection
{
if (e.NewStartingIndex <= _selectedIndex)
{
- return _selectedIndex + e.NewItems.Count < ItemsView.Count;
+ return _selectedIndex + e.NewItems!.Count < ItemsView.Count;
}
if (e.NewStartingIndex <= _anchorIndex)
{
- return _anchorIndex + e.NewItems.Count < ItemsView.Count;
+ return _anchorIndex + e.NewItems!.Count < ItemsView.Count;
}
}
diff --git a/src/Avalonia.Controls/Selection/SelectionModelIndexesChangedEventArgs.cs b/src/Avalonia.Controls/Selection/SelectionModelIndexesChangedEventArgs.cs
index a1fef578a2..621fba48e8 100644
--- a/src/Avalonia.Controls/Selection/SelectionModelIndexesChangedEventArgs.cs
+++ b/src/Avalonia.Controls/Selection/SelectionModelIndexesChangedEventArgs.cs
@@ -1,7 +1,5 @@
using System;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
public class SelectionModelIndexesChangedEventArgs : EventArgs
diff --git a/src/Avalonia.Controls/Selection/SelectionModelSelectionChangedEventArgs.cs b/src/Avalonia.Controls/Selection/SelectionModelSelectionChangedEventArgs.cs
index 396943592d..64c1b14253 100644
--- a/src/Avalonia.Controls/Selection/SelectionModelSelectionChangedEventArgs.cs
+++ b/src/Avalonia.Controls/Selection/SelectionModelSelectionChangedEventArgs.cs
@@ -3,8 +3,6 @@ using System.Collections;
using System.Collections.Generic;
using Avalonia.Controls.Selection;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
public abstract class SelectionModelSelectionChangedEventArgs : EventArgs
diff --git a/src/Avalonia.Controls/Selection/SelectionNodeBase.cs b/src/Avalonia.Controls/Selection/SelectionNodeBase.cs
index 230575074a..5994025d56 100644
--- a/src/Avalonia.Controls/Selection/SelectionNodeBase.cs
+++ b/src/Avalonia.Controls/Selection/SelectionNodeBase.cs
@@ -5,8 +5,6 @@ using System.Collections.Specialized;
using System.Linq;
using Avalonia.Controls.Utils;
-#nullable enable
-
namespace Avalonia.Controls.Selection
{
public abstract class SelectionNodeBase