From 77d059be22291183f1c39cf89a181e7503ba9394 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sun, 30 Jan 2022 14:40:26 +0100 Subject: [PATCH] Add nullable annotations to Avalonia.Controls. --- src/Avalonia.Controls/AppBuilderBase.cs | 35 +- src/Avalonia.Controls/Application.cs | 4 +- .../ClassicDesktopStyleApplicationLifetime.cs | 26 +- ...IClassicDesktopStyleApplicationLifetime.cs | 6 +- src/Avalonia.Controls/AutoCompleteBox.cs | 309 +++++++++--------- .../Avalonia.Controls.csproj | 1 + src/Avalonia.Controls/Border.cs | 12 +- src/Avalonia.Controls/Button.cs | 28 +- src/Avalonia.Controls/ButtonSpinner.cs | 14 +- src/Avalonia.Controls/Calendar/Calendar.cs | 76 +++-- .../Calendar/CalendarButton.cs | 6 +- .../Calendar/CalendarDatePicker.cs | 87 +++-- .../Calendar/CalendarDateRange.cs | 2 +- .../Calendar/CalendarDayButton.cs | 6 +- .../Calendar/CalendarItem.cs | 99 +++--- .../Calendar/DateTimeHelper.cs | 2 + .../Calendar/SelectedDatesCollection.cs | 4 +- src/Avalonia.Controls/Canvas.cs | 2 +- src/Avalonia.Controls/Chrome/TitleBar.cs | 2 +- src/Avalonia.Controls/ComboBox.cs | 40 +-- src/Avalonia.Controls/ContentControl.cs | 14 +- src/Avalonia.Controls/ContextMenu.cs | 12 +- src/Avalonia.Controls/Control.cs | 2 +- src/Avalonia.Controls/ControlExtensions.cs | 35 +- .../Converters/MarginMultiplierConverter.cs | 4 +- .../MenuScrollingVisibilityConverter.cs | 2 +- .../Converters/PlatformKeyGestureConverter.cs | 4 +- src/Avalonia.Controls/DataValidationErrors.cs | 29 +- .../DateTimePickers/DatePicker.cs | 60 ++-- .../DateTimePickers/DatePickerPresenter.cs | 103 +++--- .../DateTimePickers/DateTimePickerPanel.cs | 28 +- .../DateTimePickers/PickerPresenterBase.cs | 6 +- .../DateTimePickers/TimePicker.cs | 56 ++-- .../DateTimePickers/TimePickerPresenter.cs | 75 +++-- src/Avalonia.Controls/Decorator.cs | 10 +- src/Avalonia.Controls/DefinitionBase.cs | 40 +-- src/Avalonia.Controls/DefinitionList.cs | 4 +- .../Offscreen/OffscreenTopLevelImpl.cs | 20 +- .../ExperimentalAcrylicBorder.cs | 7 +- src/Avalonia.Controls/Flyouts/FlyoutBase.cs | 18 +- src/Avalonia.Controls/Flyouts/MenuFlyout.cs | 6 +- .../Generators/IItemContainerGenerator.cs | 12 +- .../Generators/ITreeItemContainerGenerator.cs | 2 +- .../Generators/ItemContainerGenerator.cs | 26 +- .../Generators/ItemContainerGenerator`1.cs | 11 +- .../Generators/MenuItemContainerGenerator.cs | 2 +- .../Generators/TabItemContainerGenerator.cs | 12 +- .../Generators/TreeContainerIndex.cs | 8 +- .../Generators/TreeItemContainerGenerator.cs | 23 +- src/Avalonia.Controls/Grid.cs | 161 +++++---- src/Avalonia.Controls/GridLength.cs | 2 +- src/Avalonia.Controls/GridSplitter.cs | 62 ++-- src/Avalonia.Controls/HotkeyManager.cs | 40 +-- src/Avalonia.Controls/IContentControl.cs | 6 +- src/Avalonia.Controls/IHeadered.cs | 2 +- src/Avalonia.Controls/IVirtualizingPanel.cs | 2 +- src/Avalonia.Controls/ItemsControl.cs | 56 ++-- src/Avalonia.Controls/ItemsSourceView.cs | 6 +- src/Avalonia.Controls/Label.cs | 8 +- .../LayoutTransformControl.cs | 14 +- src/Avalonia.Controls/ListBox.cs | 12 +- src/Avalonia.Controls/MaskedTextBox.cs | 8 +- src/Avalonia.Controls/MenuBase.cs | 11 +- src/Avalonia.Controls/MenuItem.cs | 42 +-- .../MenuItemAccessKeyHandler.cs | 8 +- .../Mixins/SelectableMixin.cs | 2 +- src/Avalonia.Controls/NativeControlHost.cs | 19 +- src/Avalonia.Controls/NativeMenu.Export.cs | 2 +- src/Avalonia.Controls/NativeMenu.cs | 16 +- src/Avalonia.Controls/NativeMenuBar.cs | 4 +- src/Avalonia.Controls/NativeMenuItem.cs | 48 +-- src/Avalonia.Controls/NativeMenuItemBase.cs | 8 +- .../Notifications/INotification.cs | 8 +- .../Notifications/Notification.cs | 16 +- .../Notifications/NotificationCard.cs | 15 +- .../WindowNotificationManager.cs | 8 +- .../NumericUpDown/NumericUpDown.cs | 94 +++--- src/Avalonia.Controls/Panel.cs | 24 +- .../Platform/DefaultMenuInteractionHandler.cs | 35 +- .../ExportWindowingSubsystemAttribute.cs | 4 +- .../Platform/INativeControlHostImpl.cs | 6 +- .../Platform/ITopLevelImpl.cs | 18 +- .../ITopLevelImplWithTextInputMethod.cs | 2 +- .../Platform/ITopLevelNativeMenuExporter.cs | 2 +- .../Platform/IWindowBaseImpl.cs | 6 +- src/Avalonia.Controls/Platform/IWindowImpl.cs | 4 +- .../Platform/InProcessDragSource.cs | 16 +- .../InternalPlatformThreadingInterface.cs | 10 +- .../Platform/MountedDriveInfo.cs | 10 +- .../Presenters/CarouselPresenter.cs | 28 +- .../Presenters/ContentPresenter.cs | 30 +- .../Presenters/IContentPresenter.cs | 4 +- .../Presenters/IItemsPresenter.cs | 4 +- .../Presenters/ItemContainerSync.cs | 12 +- .../Presenters/ItemVirtualizer.cs | 34 +- .../Presenters/ItemVirtualizerNone.cs | 17 +- .../Presenters/ItemVirtualizerSimple.cs | 16 +- .../Presenters/ItemsPresenter.cs | 10 +- .../Presenters/ItemsPresenterBase.cs | 28 +- .../Presenters/ScrollContentPresenter.cs | 25 +- .../Presenters/TextPresenter.cs | 17 +- .../Primitives/AccessText.cs | 15 +- .../Primitives/AdornerLayer.cs | 4 +- .../Primitives/HeaderedItemsControl.cs | 7 +- .../HeaderedSelectingItemsControl.cs | 7 +- .../Primitives/ILogicalScrollable.cs | 4 +- .../Primitives/IPopupHost.cs | 8 +- .../Primitives/LightDismissOverlayLayer.cs | 2 +- .../Primitives/OverlayLayer.cs | 2 +- .../Primitives/OverlayPopupHost.cs | 12 +- src/Avalonia.Controls/Primitives/Popup.cs | 18 +- .../PopupPositioning/IPopupPositioner.cs | 2 +- src/Avalonia.Controls/Primitives/PopupRoot.cs | 13 +- src/Avalonia.Controls/Primitives/ScrollBar.cs | 22 +- .../Primitives/SelectingItemsControl.cs | 32 +- .../Primitives/TemplatedControl.cs | 2 +- src/Avalonia.Controls/Primitives/Thumb.cs | 6 +- .../Primitives/ToggleButton.cs | 6 +- src/Avalonia.Controls/Primitives/Track.cs | 10 +- .../Primitives/VisualLayerManager.cs | 8 +- src/Avalonia.Controls/ProgressBar.cs | 2 +- src/Avalonia.Controls/RadioButton.cs | 26 +- src/Avalonia.Controls/Remote/RemoteServer.cs | 2 +- src/Avalonia.Controls/Remote/RemoteWidget.cs | 4 +- .../Remote/Server/RemoteServerTopLevelImpl.cs | 26 +- src/Avalonia.Controls/RepeatButton.cs | 6 +- .../Repeater/ElementFactory.cs | 4 +- .../Repeater/IElementFactory.cs | 8 +- .../Repeater/ItemTemplateWrapper.cs | 14 +- .../Repeater/ItemsRepeater.cs | 67 ++-- src/Avalonia.Controls/Repeater/RecyclePool.cs | 16 +- .../Repeater/RecyclingElementFactory.cs | 6 +- .../Repeater/RepeaterLayoutContext.cs | 4 +- .../Repeater/UniqueIdElementPool.cs | 6 +- src/Avalonia.Controls/Repeater/ViewManager.cs | 54 +-- .../Repeater/ViewportManager.cs | 24 +- .../Repeater/VirtualizationInfo.cs | 2 +- .../RequestBringIntoViewEventArgs.cs | 2 +- src/Avalonia.Controls/Screens.cs | 16 +- src/Avalonia.Controls/ScrollViewer.cs | 22 +- .../Selection/InternalSelectionModel.cs | 12 +- .../Selection/SelectionModel.cs | 13 +- .../Selection/SelectionNodeBase.cs | 14 +- src/Avalonia.Controls/Shapes/Path.cs | 10 +- src/Avalonia.Controls/Slider.cs | 25 +- src/Avalonia.Controls/Spinner.cs | 6 +- src/Avalonia.Controls/SplitView.cs | 44 +-- src/Avalonia.Controls/StackPanel.cs | 4 +- src/Avalonia.Controls/TabControl.cs | 22 +- .../Templates/DataTemplateExtensions.cs | 2 +- .../Templates/FuncDataTemplate.cs | 24 +- .../Templates/FuncDataTemplate`1.cs | 10 +- .../FuncTemplateNameScopeExtensions.cs | 3 + .../Templates/FuncTemplate`1.cs | 6 +- .../Templates/FuncTemplate`2.cs | 2 +- .../Templates/FuncTreeDataTemplate.cs | 16 +- .../Templates/FuncTreeDataTemplate`1.cs | 10 +- .../Templates/IDataTemplate.cs | 4 +- .../Templates/IRecyclingDataTemplate.cs | 4 +- .../Templates/ITreeDataTemplate.cs | 2 +- src/Avalonia.Controls/TextBlock.cs | 36 +- src/Avalonia.Controls/TextBox.cs | 96 +++--- .../TextBoxTextInputMethodClient.cs | 18 +- src/Avalonia.Controls/ToggleSwitch.cs | 48 +-- src/Avalonia.Controls/ToolTip.cs | 2 +- src/Avalonia.Controls/ToolTipService.cs | 20 +- src/Avalonia.Controls/TopLevel.cs | 69 ++-- src/Avalonia.Controls/TrayIcon.cs | 13 +- src/Avalonia.Controls/TreeView.cs | 109 +++--- src/Avalonia.Controls/TreeViewItem.cs | 8 +- src/Avalonia.Controls/Utils/AncestorFinder.cs | 22 +- .../Utils/BorderRenderHelper.cs | 22 +- .../Utils/IEnumerableUtils.cs | 10 +- .../Utils/ISelectionAdapter.cs | 10 +- .../SelectingItemsControlSelectionAdapter.cs | 24 +- src/Avalonia.Controls/Utils/UndoRedoHelper.cs | 8 +- src/Avalonia.Controls/ValidatingToplevel.cs | 34 +- .../VirtualizingStackPanel.cs | 12 +- src/Avalonia.Controls/Window.cs | 63 ++-- src/Avalonia.Controls/WindowBase.cs | 25 +- src/Avalonia.Controls/WindowIcon.cs | 6 +- src/Avalonia.Controls/WrapPanel.cs | 4 +- 182 files changed, 1926 insertions(+), 1891 deletions(-) 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 dataContextProvider = null) + public void Start(Func? dataContextProvider = null) where TMainWindow : Window, new() { AfterSetup(builder => @@ -134,7 +134,7 @@ namespace Avalonia.Controls var window = new TMainWindow(); if (dataContextProvider != null) window.DataContext = dataContextProvider(); - ((IClassicDesktopStyleApplicationLifetime)builder.Instance.ApplicationLifetime) + ((IClassicDesktopStyleApplicationLifetime)builder.Instance!.ApplicationLifetime!) .MainWindow = window; }); @@ -155,7 +155,7 @@ namespace Avalonia.Controls public void Start(AppMainDelegate main, string[] args) { Setup(); - main(Instance, args); + main(Instance!, args); } /// @@ -226,8 +226,8 @@ namespace Avalonia.Controls var platformClassName = assemblyName.Replace("Avalonia.", string.Empty) + "Platform"; var platformClassFullName = assemblyName + "." + platformClassName; var platformClass = assembly.GetType(platformClassFullName); - var init = platformClass.GetRuntimeMethod("Initialize", Type.EmptyTypes); - init.Invoke(null, null); + var init = platformClass!.GetRuntimeMethod("Initialize", Type.EmptyTypes); + init!.Invoke(null, null); }; public TAppBuilder UseAvaloniaModules() => AfterSetup(builder => SetupAvaloniaModules()); @@ -251,7 +251,7 @@ namespace Avalonia.Controls where constructor.GetParameters().Length == 0 && !constructor.IsStatic select constructor).Single() into constructor select (Action)(() => constructor.Invoke(Array.Empty())); - Delegate.Combine(moduleInitializers.ToArray()).DynamicInvoke(); + Delegate.Combine(moduleInitializers.ToArray())!.DynamicInvoke(); } /// @@ -292,6 +292,11 @@ namespace Avalonia.Controls throw new InvalidOperationException("No rendering system configured."); } + if (_appFactory == null) + { + throw new InvalidOperationException("No Application factory configured."); + } + if (s_setupWasAlreadyCalled && CheckSetup) { throw new InvalidOperationException("Setup was already called on one of AppBuilder instances"); diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index 584c3db23b..9f7f54d293 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -177,13 +177,13 @@ namespace Avalonia /// public IApplicationLifetime? ApplicationLifetime { get; set; } - event Action> IGlobalStyles.GlobalStylesAdded + event Action>? IGlobalStyles.GlobalStylesAdded { add => _stylesAdded += value; remove => _stylesAdded -= value; } - event Action> IGlobalStyles.GlobalStylesRemoved + event Action>? IGlobalStyles.GlobalStylesRemoved { add => _stylesRemoved += value; remove => _stylesRemoved -= value; diff --git a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs index edddf31d45..76e2d3a161 100644 --- a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs +++ b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs @@ -15,26 +15,26 @@ namespace Avalonia.Controls.ApplicationLifetimes public class ClassicDesktopStyleApplicationLifetime : IClassicDesktopStyleApplicationLifetime, IDisposable { private int _exitCode; - private CancellationTokenSource _cts; + private CancellationTokenSource? _cts; private bool _isShuttingDown; private HashSet _windows = new HashSet(); - private static ClassicDesktopStyleApplicationLifetime _activeLifetime; + private static ClassicDesktopStyleApplicationLifetime? _activeLifetime; static ClassicDesktopStyleApplicationLifetime() { Window.WindowOpenedEvent.AddClassHandler(typeof(Window), OnWindowOpened); Window.WindowClosedEvent.AddClassHandler(typeof(Window), WindowClosedEvent); } - private static void WindowClosedEvent(object sender, RoutedEventArgs e) + private static void WindowClosedEvent(object? sender, RoutedEventArgs e) { - _activeLifetime?._windows.Remove((Window)sender); - _activeLifetime?.HandleWindowClosed((Window)sender); + _activeLifetime?._windows.Remove((Window)sender!); + _activeLifetime?.HandleWindowClosed((Window)sender!); } - private static void OnWindowOpened(object sender, RoutedEventArgs e) + private static void OnWindowOpened(object? sender, RoutedEventArgs e) { - _activeLifetime?._windows.Add((Window)sender); + _activeLifetime?._windows.Add((Window)sender!); } public ClassicDesktopStyleApplicationLifetime() @@ -46,24 +46,24 @@ namespace Avalonia.Controls.ApplicationLifetimes } /// - public event EventHandler Startup; + public event EventHandler? Startup; /// - public event EventHandler ShutdownRequested; + public event EventHandler? ShutdownRequested; /// - public event EventHandler Exit; + public event EventHandler? Exit; /// /// Gets the arguments passed to the AppBuilder Start method. /// - public string[] Args { get; set; } + public string[]? Args { get; set; } /// public ShutdownMode ShutdownMode { get; set; } /// - public Window MainWindow { get; set; } + public Window? MainWindow { get; set; } public IReadOnlyList Windows => _windows.ToList(); @@ -183,7 +183,7 @@ namespace Avalonia.Controls.ApplicationLifetimes return true; } - private void OnShutdownRequested(object sender, ShutdownRequestedEventArgs e) => DoShutdown(e); + private void OnShutdownRequested(object? sender, ShutdownRequestedEventArgs e) => DoShutdown(e); } public class ClassicDesktopStyleApplicationLifetimeOptions diff --git a/src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs index a83229b732..2bd5c1238d 100644 --- a/src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs +++ b/src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs @@ -20,7 +20,7 @@ namespace Avalonia.Controls.ApplicationLifetimes /// /// method. /// - string[] Args { get; } + string[]? Args { get; } /// /// Gets or sets the . This property indicates whether the application is shutdown explicitly or implicitly. @@ -38,7 +38,7 @@ namespace Avalonia.Controls.ApplicationLifetimes /// /// The main window. /// - Window MainWindow { get; set; } + Window? MainWindow { get; set; } IReadOnlyList Windows { get; } @@ -58,6 +58,6 @@ namespace Avalonia.Controls.ApplicationLifetimes /// will try to close each non-owned open window, invoking the event on each and allowing /// each window to cancel the shutdown of the application. Windows cannot however prevent OS shutdown. /// - event EventHandler ShutdownRequested; + event EventHandler? ShutdownRequested; } } diff --git a/src/Avalonia.Controls/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox.cs index 0e946126ea..930e250334 100644 --- a/src/Avalonia.Controls/AutoCompleteBox.cs +++ b/src/Avalonia.Controls/AutoCompleteBox.cs @@ -69,7 +69,7 @@ namespace Avalonia.Controls /// /// The text that is used to determine which items to display in /// the . - public string Parameter { get; private set; } + public string? Parameter { get; private set; } /// /// Initializes a new instance of the @@ -79,7 +79,7 @@ namespace Avalonia.Controls /// /// property, which is used to filter items for the /// control. - public PopulatingEventArgs(string parameter) + public PopulatingEventArgs(string? parameter) { Parameter = parameter; } @@ -98,7 +98,7 @@ namespace Avalonia.Controls /// The type used for filtering the /// . This type can /// be either a string or an object. - public delegate bool AutoCompleteFilterPredicate(string search, T item); + public delegate bool AutoCompleteFilterPredicate(string? search, T item); /// /// Specifies how text in the text box portion of the @@ -245,7 +245,7 @@ namespace Avalonia.Controls /// . /// This type can be either a string or an object. /// - public delegate string AutoCompleteSelector(string search, T item); + public delegate string AutoCompleteSelector(string? search, T item); /// /// Represents a control that provides a text box for user input and a @@ -275,19 +275,19 @@ namespace Avalonia.Controls /// private const string ElementTextBox = "PART_TextBox"; - private IEnumerable _itemsEnumerable; + private IEnumerable? _itemsEnumerable; /// /// Gets or sets a local cached copy of the items data. /// - private List _items; + private List? _items; /// /// Gets or sets the observable collection that contains references to /// all of the items in the generated view of data that is provided to /// the selection-style control adapter. /// - private AvaloniaList _view; + private AvaloniaList? _view; /// /// Gets or sets a value to ignore a number of pending change handlers. @@ -338,7 +338,7 @@ namespace Avalonia.Controls /// Gets or sets the DispatcherTimer used for the MinimumPopulateDelay /// condition for auto completion. /// - private DispatcherTimer _delayTimer; + private DispatcherTimer? _delayTimer; /// /// Gets or sets a value indicating whether a read-only dependency @@ -351,47 +351,47 @@ namespace Avalonia.Controls /// /// The TextBox template part. /// - private TextBox _textBox; - private IDisposable _textBoxSubscriptions; + private TextBox? _textBox; + private IDisposable? _textBoxSubscriptions; /// /// The SelectionAdapter. /// - private ISelectionAdapter _adapter; + private ISelectionAdapter? _adapter; /// /// A control that can provide updated string values from a binding. /// - private BindingEvaluator _valueBindingEvaluator; + private BindingEvaluator? _valueBindingEvaluator; /// /// A weak subscription for the collection changed event. /// - private IDisposable _collectionChangeSubscription; + private IDisposable? _collectionChangeSubscription; - private Func>> _asyncPopulator; - private CancellationTokenSource _populationCancellationTokenSource; + private Func>>? _asyncPopulator; + private CancellationTokenSource? _populationCancellationTokenSource; private bool _itemTemplateIsFromValueMemberBinding = true; private bool _settingItemTemplateFromValueMemberBinding; - private object _selectedItem; + private object? _selectedItem; private bool _isDropDownOpen; private bool _isFocused = false; - private string _text = string.Empty; - private string _searchText = string.Empty; + private string? _text = string.Empty; + private string? _searchText = string.Empty; - private AutoCompleteFilterPredicate _itemFilter; - private AutoCompleteFilterPredicate _textFilter = AutoCompleteSearch.GetFilter(AutoCompleteFilterMode.StartsWith); + private AutoCompleteFilterPredicate? _itemFilter; + private AutoCompleteFilterPredicate? _textFilter = AutoCompleteSearch.GetFilter(AutoCompleteFilterMode.StartsWith); - private AutoCompleteSelector _itemSelector; - private AutoCompleteSelector _textSelector; + private AutoCompleteSelector? _itemSelector; + private AutoCompleteSelector? _textSelector; public static readonly RoutedEvent SelectionChangedEvent = RoutedEvent.Register(nameof(SelectionChanged), RoutingStrategies.Bubble, typeof(AutoCompleteBox)); - public static readonly StyledProperty WatermarkProperty = + public static readonly StyledProperty WatermarkProperty = TextBox.WatermarkProperty.AddOwner(); /// @@ -479,8 +479,8 @@ namespace Avalonia.Controls /// The identifier the /// /// dependency property. - public static readonly DirectProperty SelectedItemProperty = - AvaloniaProperty.RegisterDirect( + public static readonly DirectProperty SelectedItemProperty = + AvaloniaProperty.RegisterDirect( nameof(SelectedItem), o => o.SelectedItem, (o, v) => o.SelectedItem = v, @@ -495,7 +495,7 @@ namespace Avalonia.Controls /// The identifier for the /// /// dependency property. - public static readonly DirectProperty TextProperty = + public static readonly DirectProperty TextProperty = TextBlock.TextProperty.AddOwnerWithDataValidation( o => o.Text, (o, v) => o.Text = v, @@ -510,8 +510,8 @@ namespace Avalonia.Controls /// The identifier for the /// /// dependency property. - public static readonly DirectProperty SearchTextProperty = - AvaloniaProperty.RegisterDirect( + public static readonly DirectProperty SearchTextProperty = + AvaloniaProperty.RegisterDirect( nameof(SearchText), o => o.SearchText, unsetValue: string.Empty); @@ -535,8 +535,8 @@ namespace Avalonia.Controls /// The identifier for the /// /// dependency property. - public static readonly DirectProperty> ItemFilterProperty = - AvaloniaProperty.RegisterDirect>( + public static readonly DirectProperty?> ItemFilterProperty = + AvaloniaProperty.RegisterDirect?>( nameof(ItemFilter), o => o.ItemFilter, (o, v) => o.ItemFilter = v); @@ -549,8 +549,8 @@ namespace Avalonia.Controls /// The identifier for the /// /// dependency property. - public static readonly DirectProperty> TextFilterProperty = - AvaloniaProperty.RegisterDirect>( + public static readonly DirectProperty?> TextFilterProperty = + AvaloniaProperty.RegisterDirect?>( nameof(TextFilter), o => o.TextFilter, (o, v) => o.TextFilter = v, @@ -564,8 +564,8 @@ namespace Avalonia.Controls /// The identifier for the /// /// dependency property. - public static readonly DirectProperty> ItemSelectorProperty = - AvaloniaProperty.RegisterDirect>( + public static readonly DirectProperty?> ItemSelectorProperty = + AvaloniaProperty.RegisterDirect?>( nameof(ItemSelector), o => o.ItemSelector, (o, v) => o.ItemSelector = v); @@ -578,8 +578,8 @@ namespace Avalonia.Controls /// The identifier for the /// /// dependency property. - public static readonly DirectProperty> TextSelectorProperty = - AvaloniaProperty.RegisterDirect>( + public static readonly DirectProperty?> TextSelectorProperty = + AvaloniaProperty.RegisterDirect?>( nameof(TextSelector), o => o.TextSelector, (o, v) => o.TextSelector = v); @@ -592,14 +592,14 @@ namespace Avalonia.Controls /// The identifier for the /// /// dependency property. - public static readonly DirectProperty ItemsProperty = - AvaloniaProperty.RegisterDirect( + public static readonly DirectProperty ItemsProperty = + AvaloniaProperty.RegisterDirect( nameof(Items), o => o.Items, (o, v) => o.Items = v); - public static readonly DirectProperty>>> AsyncPopulatorProperty = - AvaloniaProperty.RegisterDirect>>>( + public static readonly DirectProperty>>?> AsyncPopulatorProperty = + AvaloniaProperty.RegisterDirect>>?>( nameof(AsyncPopulator), o => o.AsyncPopulator, (o, v) => o.AsyncPopulator = v); @@ -640,7 +640,7 @@ namespace Avalonia.Controls /// The event data. private void OnControlIsEnabledChanged(AvaloniaPropertyChangedEventArgs e) { - bool isEnabled = (bool)e.NewValue; + bool isEnabled = (bool)e.NewValue!; if (!isEnabled) { IsDropDownOpen = false; @@ -655,7 +655,7 @@ namespace Avalonia.Controls /// Event arguments. private void OnMinimumPopulateDelayChanged(AvaloniaPropertyChangedEventArgs e) { - var newValue = (TimeSpan)e.NewValue; + var newValue = (TimeSpan)e.NewValue!; // Stop any existing timer if (_delayTimer != null) @@ -695,8 +695,8 @@ namespace Avalonia.Controls return; } - bool oldValue = (bool)e.OldValue; - bool newValue = (bool)e.NewValue; + bool oldValue = (bool)e.OldValue!; + bool newValue = (bool)e.NewValue!; if (newValue) { @@ -750,7 +750,7 @@ namespace Avalonia.Controls /// Event arguments. private void OnTextPropertyChanged(AvaloniaPropertyChangedEventArgs e) { - TextUpdated((string)e.NewValue, false); + TextUpdated((string?)e.NewValue, false); } private void OnSearchTextPropertyChanged(AvaloniaPropertyChangedEventArgs e) @@ -778,7 +778,7 @@ namespace Avalonia.Controls /// Event arguments. private void OnFilterModePropertyChanged(AvaloniaPropertyChangedEventArgs e) { - AutoCompleteFilterMode mode = (AutoCompleteFilterMode)e.NewValue; + AutoCompleteFilterMode mode = (AutoCompleteFilterMode)e.NewValue!; // Sets the filter predicate for the new value TextFilter = AutoCompleteSearch.GetFilter(mode); @@ -790,7 +790,7 @@ namespace Avalonia.Controls /// Event arguments. private void OnItemFilterPropertyChanged(AvaloniaPropertyChangedEventArgs e) { - AutoCompleteFilterPredicate value = e.NewValue as AutoCompleteFilterPredicate; + var value = e.NewValue as AutoCompleteFilterPredicate; // If null, revert to the "None" predicate if (value == null) @@ -810,7 +810,7 @@ namespace Avalonia.Controls /// Event arguments. private void OnItemsPropertyChanged(AvaloniaPropertyChangedEventArgs e) { - OnItemsChanged((IEnumerable)e.NewValue); + OnItemsChanged((IEnumerable?)e.NewValue); } private void OnItemTemplatePropertyChanged(AvaloniaPropertyChangedEventArgs e) @@ -818,7 +818,7 @@ namespace Avalonia.Controls if (!_settingItemTemplateFromValueMemberBinding) _itemTemplateIsFromValueMemberBinding = false; } - private void OnValueMemberBindingChanged(IBinding value) + private void OnValueMemberBindingChanged(IBinding? value) { if(_itemTemplateIsFromValueMemberBinding) { @@ -828,7 +828,8 @@ namespace Avalonia.Controls (o, _) => { var control = new ContentControl(); - control.Bind(ContentControl.ContentProperty, value); + if (value is not null) + control.Bind(ContentControl.ContentProperty, value); return control; }); @@ -975,7 +976,7 @@ namespace Avalonia.Controls /// The object used /// when binding to a collection property. [AssignBinding] - public IBinding ValueMemberBinding + public IBinding? ValueMemberBinding { get { return _valueBindingEvaluator?.ValueBinding; } set @@ -998,7 +999,7 @@ namespace Avalonia.Controls /// then displayed in the text box, the SelectedItem property will be /// a null reference. /// - public object SelectedItem + public object? SelectedItem { get { return _selectedItem; } set { SetAndRaise(SelectedItemProperty, ref _selectedItem, value); } @@ -1010,7 +1011,7 @@ namespace Avalonia.Controls /// /// The text in the text box portion of the /// control. - public string Text + public string? Text { get { return _text; } set { SetAndRaise(TextProperty, ref _text, value); } @@ -1029,7 +1030,7 @@ namespace Avalonia.Controls /// Text property, but is set after the TextChanged event occurs /// and before the Populating event. /// - public string SearchText + public string? SearchText { get { return _searchText; } private set @@ -1071,7 +1072,7 @@ namespace Avalonia.Controls set { SetValue(FilterModeProperty, value); } } - public string Watermark + public string? Watermark { get { return GetValue(WatermarkProperty); } set { SetValue(WatermarkProperty, value); } @@ -1091,7 +1092,7 @@ namespace Avalonia.Controls /// The filter mode is automatically set to Custom if you set the /// ItemFilter property. /// - public AutoCompleteFilterPredicate ItemFilter + public AutoCompleteFilterPredicate? ItemFilter { get { return _itemFilter; } set { SetAndRaise(ItemFilterProperty, ref _itemFilter, value); } @@ -1111,7 +1112,7 @@ namespace Avalonia.Controls /// The search mode is automatically set to Custom if you set the /// TextFilter property. /// - public AutoCompleteFilterPredicate TextFilter + public AutoCompleteFilterPredicate? TextFilter { get { return _textFilter; } set { SetAndRaise(TextFilterProperty, ref _textFilter, value); } @@ -1127,7 +1128,7 @@ namespace Avalonia.Controls /// text and one of the items specified by the /// . /// - public AutoCompleteSelector ItemSelector + public AutoCompleteSelector? ItemSelector { get { return _itemSelector; } set { SetAndRaise(ItemSelectorProperty, ref _itemSelector, value); } @@ -1145,13 +1146,13 @@ namespace Avalonia.Controls /// /// in a text-based way. /// - public AutoCompleteSelector TextSelector + public AutoCompleteSelector? TextSelector { get { return _textSelector; } set { SetAndRaise(TextSelectorProperty, ref _textSelector, value); } } - public Func>> AsyncPopulator + public Func>>? AsyncPopulator { get { return _asyncPopulator; } set { SetAndRaise(AsyncPopulatorProperty, ref _asyncPopulator, value); } @@ -1165,7 +1166,7 @@ namespace Avalonia.Controls /// The collection that is used to generate the items of the /// drop-down portion of the /// control. - public IEnumerable Items + public IEnumerable? Items { get { return _itemsEnumerable; } set { SetAndRaise(ItemsProperty, ref _itemsEnumerable, value); } @@ -1174,12 +1175,12 @@ namespace Avalonia.Controls /// /// Gets or sets the drop down popup control. /// - private Popup DropDownPopup { get; set; } + private Popup? DropDownPopup { get; set; } /// /// Gets or sets the Text template part. /// - private TextBox TextBox + private TextBox? TextBox { get { return _textBox; } set @@ -1243,7 +1244,7 @@ namespace Avalonia.Controls /// use with AutoCompleteBox or deriving from AutoCompleteBox to /// create a custom control. /// - protected ISelectionAdapter SelectionAdapter + protected ISelectionAdapter? SelectionAdapter { get { return _adapter; } set @@ -1279,10 +1280,10 @@ namespace Avalonia.Controls /// A object, /// if possible. Otherwise, null. /// - protected virtual ISelectionAdapter GetSelectionAdapterPart(INameScope nameScope) + protected virtual ISelectionAdapter? GetSelectionAdapterPart(INameScope nameScope) { - ISelectionAdapter adapter = null; - SelectingItemsControl selector = nameScope.Find(ElementSelector); + ISelectionAdapter? adapter = null; + SelectingItemsControl? selector = nameScope.Find(ElementSelector); if (selector != null) { // Check if it is already an IItemsSelector @@ -1316,7 +1317,7 @@ namespace Avalonia.Controls // Set the template parts. Individual part setters remove and add // any event handlers. - Popup popup = e.NameScope.Find(ElementPopup); + Popup? popup = e.NameScope.Find(ElementPopup); if (popup != null) { DropDownPopup = popup; @@ -1358,7 +1359,7 @@ namespace Avalonia.Controls /// that contains the event data. protected override void OnKeyDown(KeyEventArgs e) { - Contract.Requires(e != null); + _ = e ?? throw new ArgumentNullException(nameof(e)); base.OnKeyDown(e); @@ -1453,7 +1454,7 @@ namespace Avalonia.Controls /// otherwise, false. protected bool HasFocus() { - IVisual focused = FocusManager.Instance.Current; + IVisual? focused = FocusManager.Instance?.Current; while (focused != null) { @@ -1464,11 +1465,11 @@ namespace Avalonia.Controls // This helps deal with popups that may not be in the same // visual tree - IVisual parent = focused.GetVisualParent(); + IVisual? parent = focused.GetVisualParent(); if (parent == null) { // Try the logical parent. - IControl element = focused as IControl; + IControl? element = focused as IControl; if (element != null) { parent = element.Parent; @@ -1519,7 +1520,7 @@ namespace Avalonia.Controls /// Occurs when the text in the text box portion of the /// changes. /// - public event EventHandler TextChanged; + public event EventHandler? TextChanged; /// /// Occurs when the @@ -1535,7 +1536,7 @@ namespace Avalonia.Controls /// In this case, if you want possible matches to appear, you must /// provide the logic for populating the selection adapter. /// - public event EventHandler Populating; + public event EventHandler? Populating; /// /// Occurs when the @@ -1544,35 +1545,35 @@ namespace Avalonia.Controls /// /// property. /// - public event EventHandler Populated; + public event EventHandler? Populated; /// /// Occurs when the value of the /// /// property is changing from false to true. /// - public event EventHandler DropDownOpening; + public event EventHandler? DropDownOpening; /// /// Occurs when the value of the /// /// property has changed from false to true and the drop-down is open. /// - public event EventHandler DropDownOpened; + public event EventHandler? DropDownOpened; /// /// Occurs when the /// /// property is changing from true to false. /// - public event EventHandler DropDownClosing; + public event EventHandler? DropDownClosing; /// /// Occurs when the /// /// property was changed from true to false and the drop-down is open. /// - public event EventHandler DropDownClosed; + public event EventHandler? DropDownClosed; /// /// Occurs when the selected item in the drop-down portion of the @@ -1740,7 +1741,7 @@ namespace Avalonia.Controls /// /// The source object. /// The event data. - private void DropDownPopup_Closed(object sender, EventArgs e) + private void DropDownPopup_Closed(object? sender, EventArgs e) { // Force the drop down dependency property to be false. if (IsDropDownOpen) @@ -1760,7 +1761,7 @@ namespace Avalonia.Controls /// /// The source object. /// The event arguments. - private void PopulateDropDown(object sender, EventArgs e) + private void PopulateDropDown(object? sender, EventArgs e) { if (_delayTimer != null) { @@ -1786,7 +1787,7 @@ namespace Avalonia.Controls PopulateComplete(); } } - private bool TryPopulateAsync(string searchText) + private bool TryPopulateAsync(string? searchText) { _populationCancellationTokenSource?.Cancel(false); _populationCancellationTokenSource?.Dispose(); @@ -1804,12 +1805,12 @@ namespace Avalonia.Controls return true; } - private async Task PopulateAsync(string searchText, CancellationToken cancellationToken) + private async Task PopulateAsync(string? searchText, CancellationToken cancellationToken) { try { - IEnumerable result = await _asyncPopulator.Invoke(searchText, cancellationToken); + IEnumerable result = await _asyncPopulator!.Invoke(searchText, cancellationToken); var resultList = result.ToList(); if (cancellationToken.IsCancellationRequested) @@ -1878,9 +1879,9 @@ namespace Avalonia.Controls /// A value indicating whether to clear /// the data context after the lookup is performed. /// Formatted Value. - private string FormatValue(object value, bool clearDataContext) + private string? FormatValue(object? value, bool clearDataContext) { - string result = FormatValue(value); + string? result = FormatValue(value); if(clearDataContext && _valueBindingEvaluator != null) { _valueBindingEvaluator.ClearDataContext(); @@ -1902,7 +1903,7 @@ namespace Avalonia.Controls /// /// Override this method to provide a custom string conversion. /// - protected virtual string FormatValue(object value) + protected virtual string? FormatValue(object? value) { if (_valueBindingEvaluator != null) { @@ -1923,7 +1924,7 @@ namespace Avalonia.Controls Dispatcher.UIThread.Post(() => { // Call the central updated text method as a user-initiated action - TextUpdated(_textBox.Text, true); + TextUpdated(_textBox!.Text, true); }); } @@ -1933,7 +1934,7 @@ namespace Avalonia.Controls /// text changed events when there is a change. /// /// The new string value. - private void UpdateTextValue(string value) + private void UpdateTextValue(string? value) { UpdateTextValue(value, null); } @@ -1949,7 +1950,7 @@ namespace Avalonia.Controls /// underlying text dependency property is updated. In a non-user /// interaction, the text box value is updated. When user initiated is /// null, all values are updated. - private void UpdateTextValue(string value, bool? userInitiated) + private void UpdateTextValue(string? value, bool? userInitiated) { bool callTextChanged = false; // Update the Text dependency property @@ -1987,7 +1988,7 @@ namespace Avalonia.Controls /// A value indicating whether the update /// is a user-initiated action. This should be a True value when the /// TextUpdated method is called from a TextBox event handler. - private void TextUpdated(string newText, bool userInitiated) + private void TextUpdated(string? newText, bool userInitiated) { // Only process this event if it is coming from someone outside // setting the Text dependency property directly. @@ -2087,7 +2088,7 @@ namespace Avalonia.Controls bool objectFiltering = FilterMode == AutoCompleteFilterMode.Custom && TextFilter == null; int view_index = 0; - int view_count = _view.Count; + int view_count = _view!.Count; List items = _items; foreach (object item in items) { @@ -2096,7 +2097,7 @@ namespace Avalonia.Controls { if (stringFiltering) { - inResults = TextFilter(text, FormatValue(item)); + inResults = TextFilter!(text, FormatValue(item)); } else { @@ -2166,7 +2167,7 @@ namespace Avalonia.Controls /// adapter's ItemsSource to the view if appropriate. /// /// The new enumerable reference. - private void OnItemsChanged(IEnumerable newValue) + private void OnItemsChanged(IEnumerable? newValue) { // Remove handler for oldValue.CollectionChanged (if present) _collectionChangeSubscription?.Dispose(); @@ -2198,28 +2199,28 @@ namespace Avalonia.Controls /// /// 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 ce41b90bb0..a2efc7fba0 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -42,21 +42,21 @@ namespace Avalonia.Controls /// /// Defines the property. /// - public static readonly DirectProperty CommandProperty = - AvaloniaProperty.RegisterDirect(nameof(Command), + public static readonly DirectProperty CommandProperty = + AvaloniaProperty.RegisterDirect(nameof(Command), button => button.Command, (button, command) => button.Command = command, enableDataValidation: true); /// /// Defines the property. /// - public static readonly StyledProperty HotKeyProperty = + public static readonly StyledProperty HotKeyProperty = HotKeyManager.HotKeyProperty.AddOwner