Browse Source

Merge pull request #7477 from AvaloniaUI/fixes/avalonia-controls-nullability

Added nullable annotations to Avalonia.Controls.
pull/7508/head
Max Katz 4 years ago
committed by GitHub
parent
commit
2c7ae3a50f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 35
      src/Avalonia.Controls/AppBuilderBase.cs
  2. 5
      src/Avalonia.Controls/Application.cs
  3. 26
      src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
  4. 6
      src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs
  5. 2
      src/Avalonia.Controls/ApplicationLifetimes/ISingleViewApplicationLifetime.cs
  6. 309
      src/Avalonia.Controls/AutoCompleteBox.cs
  7. 1
      src/Avalonia.Controls/Avalonia.Controls.csproj
  8. 12
      src/Avalonia.Controls/Border.cs
  9. 28
      src/Avalonia.Controls/Button.cs
  10. 14
      src/Avalonia.Controls/ButtonSpinner.cs
  11. 76
      src/Avalonia.Controls/Calendar/Calendar.cs
  12. 6
      src/Avalonia.Controls/Calendar/CalendarButton.cs
  13. 87
      src/Avalonia.Controls/Calendar/CalendarDatePicker.cs
  14. 2
      src/Avalonia.Controls/Calendar/CalendarDateRange.cs
  15. 6
      src/Avalonia.Controls/Calendar/CalendarDayButton.cs
  16. 100
      src/Avalonia.Controls/Calendar/CalendarItem.cs
  17. 2
      src/Avalonia.Controls/Calendar/DateTimeHelper.cs
  18. 4
      src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs
  19. 2
      src/Avalonia.Controls/Canvas.cs
  20. 2
      src/Avalonia.Controls/Chrome/CaptionButtons.cs
  21. 4
      src/Avalonia.Controls/Chrome/TitleBar.cs
  22. 40
      src/Avalonia.Controls/ComboBox.cs
  23. 14
      src/Avalonia.Controls/ContentControl.cs
  24. 14
      src/Avalonia.Controls/ContextMenu.cs
  25. 2
      src/Avalonia.Controls/ContextRequestedEventArgs.cs
  26. 4
      src/Avalonia.Controls/Control.cs
  27. 35
      src/Avalonia.Controls/ControlExtensions.cs
  28. 3
      src/Avalonia.Controls/Converters/CornerRadiusFilterConverter.cs
  29. 4
      src/Avalonia.Controls/Converters/MarginMultiplierConverter.cs
  30. 2
      src/Avalonia.Controls/Converters/MenuScrollingVisibilityConverter.cs
  31. 4
      src/Avalonia.Controls/Converters/PlatformKeyGestureConverter.cs
  32. 29
      src/Avalonia.Controls/DataValidationErrors.cs
  33. 60
      src/Avalonia.Controls/DateTimePickers/DatePicker.cs
  34. 103
      src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
  35. 28
      src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
  36. 6
      src/Avalonia.Controls/DateTimePickers/PickerPresenterBase.cs
  37. 56
      src/Avalonia.Controls/DateTimePickers/TimePicker.cs
  38. 75
      src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
  39. 10
      src/Avalonia.Controls/Decorator.cs
  40. 40
      src/Avalonia.Controls/DefinitionBase.cs
  41. 6
      src/Avalonia.Controls/DefinitionList.cs
  42. 2
      src/Avalonia.Controls/Diagnostics/IPopupHostProvider.cs
  43. 4
      src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs
  44. 20
      src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
  45. 3
      src/Avalonia.Controls/Expander.cs
  46. 7
      src/Avalonia.Controls/ExperimentalAcrylicBorder.cs
  47. 2
      src/Avalonia.Controls/Flyouts/Flyout.cs
  48. 20
      src/Avalonia.Controls/Flyouts/FlyoutBase.cs
  49. 8
      src/Avalonia.Controls/Flyouts/MenuFlyout.cs
  50. 12
      src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
  51. 2
      src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs
  52. 26
      src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
  53. 11
      src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
  54. 2
      src/Avalonia.Controls/Generators/MenuItemContainerGenerator.cs
  55. 12
      src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs
  56. 8
      src/Avalonia.Controls/Generators/TreeContainerIndex.cs
  57. 23
      src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
  58. 165
      src/Avalonia.Controls/Grid.cs
  59. 2
      src/Avalonia.Controls/GridLength.cs
  60. 62
      src/Avalonia.Controls/GridSplitter.cs
  61. 40
      src/Avalonia.Controls/HotkeyManager.cs
  62. 6
      src/Avalonia.Controls/IContentControl.cs
  63. 2
      src/Avalonia.Controls/IControl.cs
  64. 2
      src/Avalonia.Controls/IHeadered.cs
  65. 2
      src/Avalonia.Controls/IMenuElement.cs
  66. 4
      src/Avalonia.Controls/IMenuItem.cs
  67. 4
      src/Avalonia.Controls/IScrollAnchorProvider.cs
  68. 2
      src/Avalonia.Controls/IVirtualizingPanel.cs
  69. 56
      src/Avalonia.Controls/ItemsControl.cs
  70. 8
      src/Avalonia.Controls/ItemsSourceView.cs
  71. 8
      src/Avalonia.Controls/Label.cs
  72. 14
      src/Avalonia.Controls/LayoutTransformControl.cs
  73. 12
      src/Avalonia.Controls/ListBox.cs
  74. 10
      src/Avalonia.Controls/MaskedTextBox.cs
  75. 2
      src/Avalonia.Controls/Menu.cs
  76. 13
      src/Avalonia.Controls/MenuBase.cs
  77. 44
      src/Avalonia.Controls/MenuItem.cs
  78. 8
      src/Avalonia.Controls/MenuItemAccessKeyHandler.cs
  79. 2
      src/Avalonia.Controls/Mixins/SelectableMixin.cs
  80. 19
      src/Avalonia.Controls/NativeControlHost.cs
  81. 2
      src/Avalonia.Controls/NativeMenu.Export.cs
  82. 16
      src/Avalonia.Controls/NativeMenu.cs
  83. 4
      src/Avalonia.Controls/NativeMenuBar.cs
  84. 48
      src/Avalonia.Controls/NativeMenuItem.cs
  85. 8
      src/Avalonia.Controls/NativeMenuItemBase.cs
  86. 8
      src/Avalonia.Controls/Notifications/INotification.cs
  87. 16
      src/Avalonia.Controls/Notifications/Notification.cs
  88. 15
      src/Avalonia.Controls/Notifications/NotificationCard.cs
  89. 8
      src/Avalonia.Controls/Notifications/WindowNotificationManager.cs
  90. 94
      src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
  91. 24
      src/Avalonia.Controls/Panel.cs
  92. 37
      src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
  93. 4
      src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs
  94. 6
      src/Avalonia.Controls/Platform/INativeControlHostImpl.cs
  95. 2
      src/Avalonia.Controls/Platform/ISystemDialogImpl.cs
  96. 18
      src/Avalonia.Controls/Platform/ITopLevelImpl.cs
  97. 2
      src/Avalonia.Controls/Platform/ITopLevelImplWithTextInputMethod.cs
  98. 4
      src/Avalonia.Controls/Platform/ITopLevelNativeMenuExporter.cs
  99. 2
      src/Avalonia.Controls/Platform/ITrayIconImpl.cs
  100. 6
      src/Avalonia.Controls/Platform/IWindowBaseImpl.cs

35
src/Avalonia.Controls/AppBuilderBase.cs

@ -14,9 +14,9 @@ namespace Avalonia.Controls
public abstract class AppBuilderBase<TAppBuilder> where TAppBuilder : AppBuilderBase<TAppBuilder>, new()
{
private static bool s_setupWasAlreadyCalled;
private Action _optionsInitializers;
private Func<Application> _appFactory;
private IApplicationLifetime _lifetime;
private Action? _optionsInitializers;
private Func<Application>? _appFactory;
private IApplicationLifetime? _lifetime;
/// <summary>
/// Gets or sets the <see cref="IRuntimePlatform"/> instance.
@ -31,32 +31,32 @@ namespace Avalonia.Controls
/// <summary>
/// Gets the <see cref="Application"/> instance being initialized.
/// </summary>
public Application Instance { get; private set; }
public Application? Instance { get; private set; }
/// <summary>
/// Gets the type of the Instance (even if it's not created yet)
/// </summary>
public Type ApplicationType { get; private set; }
public Type? ApplicationType { get; private set; }
/// <summary>
/// Gets or sets a method to call the initialize the windowing subsystem.
/// </summary>
public Action WindowingSubsystemInitializer { get; private set; }
public Action? WindowingSubsystemInitializer { get; private set; }
/// <summary>
/// Gets the name of the currently selected windowing subsystem.
/// </summary>
public string WindowingSubsystemName { get; private set; }
public string? WindowingSubsystemName { get; private set; }
/// <summary>
/// Gets or sets a method to call the initialize the windowing subsystem.
/// </summary>
public Action RenderingSubsystemInitializer { get; private set; }
public Action? RenderingSubsystemInitializer { get; private set; }
/// <summary>
/// Gets the name of the currently selected rendering subsystem.
/// </summary>
public string RenderingSubsystemName { get; private set; }
public string? RenderingSubsystemName { get; private set; }
/// <summary>
/// Gets or sets a method to call after the <see cref="Application"/> is setup.
@ -126,7 +126,7 @@ namespace Avalonia.Controls
/// <typeparam name="TMainWindow">The window type.</typeparam>
/// <param name="dataContextProvider">A delegate that will be called to create a data context for the window (optional).</param>
[Obsolete("Use either lifetimes or AppMain overload. See see https://github.com/AvaloniaUI/Avalonia/wiki/Application-lifetimes for details")]
public void Start<TMainWindow>(Func<object> dataContextProvider = null)
public void Start<TMainWindow>(Func<object>? 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);
}
/// <summary>
@ -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<object>()));
Delegate.Combine(moduleInitializers.ToArray()).DynamicInvoke();
Delegate.Combine(moduleInitializers.ToArray())!.DynamicInvoke();
}
/// <summary>
@ -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");

5
src/Avalonia.Controls/Application.cs

@ -13,7 +13,6 @@ using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.Threading;
#nullable enable
namespace Avalonia
{
@ -177,13 +176,13 @@ namespace Avalonia
/// </summary>
public IApplicationLifetime? ApplicationLifetime { get; set; }
event Action<IReadOnlyList<IStyle>> IGlobalStyles.GlobalStylesAdded
event Action<IReadOnlyList<IStyle>>? IGlobalStyles.GlobalStylesAdded
{
add => _stylesAdded += value;
remove => _stylesAdded -= value;
}
event Action<IReadOnlyList<IStyle>> IGlobalStyles.GlobalStylesRemoved
event Action<IReadOnlyList<IStyle>>? IGlobalStyles.GlobalStylesRemoved
{
add => _stylesRemoved += value;
remove => _stylesRemoved -= value;

26
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<Window> _windows = new HashSet<Window>();
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
}
/// <inheritdoc/>
public event EventHandler<ControlledApplicationLifetimeStartupEventArgs> Startup;
public event EventHandler<ControlledApplicationLifetimeStartupEventArgs>? Startup;
/// <inheritdoc/>
public event EventHandler<ShutdownRequestedEventArgs> ShutdownRequested;
public event EventHandler<ShutdownRequestedEventArgs>? ShutdownRequested;
/// <inheritdoc/>
public event EventHandler<ControlledApplicationLifetimeExitEventArgs> Exit;
public event EventHandler<ControlledApplicationLifetimeExitEventArgs>? Exit;
/// <summary>
/// Gets the arguments passed to the AppBuilder Start method.
/// </summary>
public string[] Args { get; set; }
public string[]? Args { get; set; }
/// <inheritdoc/>
public ShutdownMode ShutdownMode { get; set; }
/// <inheritdoc/>
public Window MainWindow { get; set; }
public Window? MainWindow { get; set; }
public IReadOnlyList<Window> 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

6
src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs

@ -20,7 +20,7 @@ namespace Avalonia.Controls.ApplicationLifetimes
/// <see cref="ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime{T}(T, string[], ShutdownMode)"/>
/// method.
/// </summary>
string[] Args { get; }
string[]? Args { get; }
/// <summary>
/// Gets or sets the <see cref="ShutdownMode"/>. This property indicates whether the application is shutdown explicitly or implicitly.
@ -38,7 +38,7 @@ namespace Avalonia.Controls.ApplicationLifetimes
/// <value>
/// The main window.
/// </value>
Window MainWindow { get; set; }
Window? MainWindow { get; set; }
IReadOnlyList<Window> Windows { get; }
@ -58,6 +58,6 @@ namespace Avalonia.Controls.ApplicationLifetimes
/// will try to close each non-owned open window, invoking the <see cref="Window.Closing"/> event on each and allowing
/// each window to cancel the shutdown of the application. Windows cannot however prevent OS shutdown.
/// </remarks>
event EventHandler<ShutdownRequestedEventArgs> ShutdownRequested;
event EventHandler<ShutdownRequestedEventArgs>? ShutdownRequested;
}
}

2
src/Avalonia.Controls/ApplicationLifetimes/ISingleViewApplicationLifetime.cs

@ -2,6 +2,6 @@ namespace Avalonia.Controls.ApplicationLifetimes
{
public interface ISingleViewApplicationLifetime : IApplicationLifetime
{
Control MainView { get; set; }
Control? MainView { get; set; }
}
}

309
src/Avalonia.Controls/AutoCompleteBox.cs

@ -69,7 +69,7 @@ namespace Avalonia.Controls
/// </summary>
/// <value>The text that is used to determine which items to display in
/// the <see cref="T:Avalonia.Controls.AutoCompleteBox" />.</value>
public string Parameter { get; private set; }
public string? Parameter { get; private set; }
/// <summary>
/// Initializes a new instance of the
@ -79,7 +79,7 @@ namespace Avalonia.Controls
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.SearchText" />
/// property, which is used to filter items for the
/// <see cref="T:Avalonia.Controls.AutoCompleteBox" /> control.</param>
public PopulatingEventArgs(string parameter)
public PopulatingEventArgs(string? parameter)
{
Parameter = parameter;
}
@ -98,7 +98,7 @@ namespace Avalonia.Controls
/// <typeparam name="T">The type used for filtering the
/// <see cref="T:Avalonia.Controls.AutoCompleteBox" />. This type can
/// be either a string or an object.</typeparam>
public delegate bool AutoCompleteFilterPredicate<T>(string search, T item);
public delegate bool AutoCompleteFilterPredicate<T>(string? search, T item);
/// <summary>
/// Specifies how text in the text box portion of the
@ -245,7 +245,7 @@ namespace Avalonia.Controls
/// <see cref="T:Avalonia.Controls.AutoCompleteBox" />.
/// This type can be either a string or an object.
/// </typeparam>
public delegate string AutoCompleteSelector<T>(string search, T item);
public delegate string AutoCompleteSelector<T>(string? search, T item);
/// <summary>
/// Represents a control that provides a text box for user input and a
@ -275,19 +275,19 @@ namespace Avalonia.Controls
/// </summary>
private const string ElementTextBox = "PART_TextBox";
private IEnumerable _itemsEnumerable;
private IEnumerable? _itemsEnumerable;
/// <summary>
/// Gets or sets a local cached copy of the items data.
/// </summary>
private List<object> _items;
private List<object>? _items;
/// <summary>
/// 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.
/// </summary>
private AvaloniaList<object> _view;
private AvaloniaList<object>? _view;
/// <summary>
/// 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.
/// </summary>
private DispatcherTimer _delayTimer;
private DispatcherTimer? _delayTimer;
/// <summary>
/// Gets or sets a value indicating whether a read-only dependency
@ -351,47 +351,47 @@ namespace Avalonia.Controls
/// <summary>
/// The TextBox template part.
/// </summary>
private TextBox _textBox;
private IDisposable _textBoxSubscriptions;
private TextBox? _textBox;
private IDisposable? _textBoxSubscriptions;
/// <summary>
/// The SelectionAdapter.
/// </summary>
private ISelectionAdapter _adapter;
private ISelectionAdapter? _adapter;
/// <summary>
/// A control that can provide updated string values from a binding.
/// </summary>
private BindingEvaluator<string> _valueBindingEvaluator;
private BindingEvaluator<string>? _valueBindingEvaluator;
/// <summary>
/// A weak subscription for the collection changed event.
/// </summary>
private IDisposable _collectionChangeSubscription;
private IDisposable? _collectionChangeSubscription;
private Func<string, CancellationToken, Task<IEnumerable<object>>> _asyncPopulator;
private CancellationTokenSource _populationCancellationTokenSource;
private Func<string?, CancellationToken, Task<IEnumerable<object>>>? _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<object> _itemFilter;
private AutoCompleteFilterPredicate<string> _textFilter = AutoCompleteSearch.GetFilter(AutoCompleteFilterMode.StartsWith);
private AutoCompleteFilterPredicate<object?>? _itemFilter;
private AutoCompleteFilterPredicate<string?>? _textFilter = AutoCompleteSearch.GetFilter(AutoCompleteFilterMode.StartsWith);
private AutoCompleteSelector<object> _itemSelector;
private AutoCompleteSelector<string> _textSelector;
private AutoCompleteSelector<object>? _itemSelector;
private AutoCompleteSelector<string?>? _textSelector;
public static readonly RoutedEvent<SelectionChangedEventArgs> SelectionChangedEvent =
RoutedEvent.Register<SelectionChangedEventArgs>(nameof(SelectionChanged), RoutingStrategies.Bubble, typeof(AutoCompleteBox));
public static readonly StyledProperty<string> WatermarkProperty =
public static readonly StyledProperty<string?> WatermarkProperty =
TextBox.WatermarkProperty.AddOwner<AutoCompleteBox>();
/// <summary>
@ -479,8 +479,8 @@ namespace Avalonia.Controls
/// <value>The identifier the
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.SelectedItem" />
/// dependency property.</value>
public static readonly DirectProperty<AutoCompleteBox, object> SelectedItemProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, object>(
public static readonly DirectProperty<AutoCompleteBox, object?> SelectedItemProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, object?>(
nameof(SelectedItem),
o => o.SelectedItem,
(o, v) => o.SelectedItem = v,
@ -495,7 +495,7 @@ namespace Avalonia.Controls
/// <value>The identifier for the
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.Text" />
/// dependency property.</value>
public static readonly DirectProperty<AutoCompleteBox, string> TextProperty =
public static readonly DirectProperty<AutoCompleteBox, string?> TextProperty =
TextBlock.TextProperty.AddOwnerWithDataValidation<AutoCompleteBox>(
o => o.Text,
(o, v) => o.Text = v,
@ -510,8 +510,8 @@ namespace Avalonia.Controls
/// <value>The identifier for the
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.SearchText" />
/// dependency property.</value>
public static readonly DirectProperty<AutoCompleteBox, string> SearchTextProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, string>(
public static readonly DirectProperty<AutoCompleteBox, string?> SearchTextProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, string?>(
nameof(SearchText),
o => o.SearchText,
unsetValue: string.Empty);
@ -535,8 +535,8 @@ namespace Avalonia.Controls
/// <value>The identifier for the
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.ItemFilter" />
/// dependency property.</value>
public static readonly DirectProperty<AutoCompleteBox, AutoCompleteFilterPredicate<object>> ItemFilterProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, AutoCompleteFilterPredicate<object>>(
public static readonly DirectProperty<AutoCompleteBox, AutoCompleteFilterPredicate<object?>?> ItemFilterProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, AutoCompleteFilterPredicate<object?>?>(
nameof(ItemFilter),
o => o.ItemFilter,
(o, v) => o.ItemFilter = v);
@ -549,8 +549,8 @@ namespace Avalonia.Controls
/// <value>The identifier for the
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.TextFilter" />
/// dependency property.</value>
public static readonly DirectProperty<AutoCompleteBox, AutoCompleteFilterPredicate<string>> TextFilterProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, AutoCompleteFilterPredicate<string>>(
public static readonly DirectProperty<AutoCompleteBox, AutoCompleteFilterPredicate<string?>?> TextFilterProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, AutoCompleteFilterPredicate<string?>?>(
nameof(TextFilter),
o => o.TextFilter,
(o, v) => o.TextFilter = v,
@ -564,8 +564,8 @@ namespace Avalonia.Controls
/// <value>The identifier for the
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.ItemSelector" />
/// dependency property.</value>
public static readonly DirectProperty<AutoCompleteBox, AutoCompleteSelector<object>> ItemSelectorProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, AutoCompleteSelector<object>>(
public static readonly DirectProperty<AutoCompleteBox, AutoCompleteSelector<object>?> ItemSelectorProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, AutoCompleteSelector<object>?>(
nameof(ItemSelector),
o => o.ItemSelector,
(o, v) => o.ItemSelector = v);
@ -578,8 +578,8 @@ namespace Avalonia.Controls
/// <value>The identifier for the
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.TextSelector" />
/// dependency property.</value>
public static readonly DirectProperty<AutoCompleteBox, AutoCompleteSelector<string>> TextSelectorProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, AutoCompleteSelector<string>>(
public static readonly DirectProperty<AutoCompleteBox, AutoCompleteSelector<string?>?> TextSelectorProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, AutoCompleteSelector<string?>?>(
nameof(TextSelector),
o => o.TextSelector,
(o, v) => o.TextSelector = v);
@ -592,14 +592,14 @@ namespace Avalonia.Controls
/// <value>The identifier for the
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.ItemsSource" />
/// dependency property.</value>
public static readonly DirectProperty<AutoCompleteBox, IEnumerable> ItemsProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, IEnumerable>(
public static readonly DirectProperty<AutoCompleteBox, IEnumerable?> ItemsProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, IEnumerable?>(
nameof(Items),
o => o.Items,
(o, v) => o.Items = v);
public static readonly DirectProperty<AutoCompleteBox, Func<string, CancellationToken, Task<IEnumerable<object>>>> AsyncPopulatorProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, Func<string, CancellationToken, Task<IEnumerable<object>>>>(
public static readonly DirectProperty<AutoCompleteBox, Func<string?, CancellationToken, Task<IEnumerable<object>>>?> AsyncPopulatorProperty =
AvaloniaProperty.RegisterDirect<AutoCompleteBox, Func<string?, CancellationToken, Task<IEnumerable<object>>>?>(
nameof(AsyncPopulator),
o => o.AsyncPopulator,
(o, v) => o.AsyncPopulator = v);
@ -640,7 +640,7 @@ namespace Avalonia.Controls
/// <param name="e">The event data.</param>
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
/// <param name="e">Event arguments.</param>
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
/// <param name="e">Event arguments.</param>
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
/// <param name="e">Event arguments.</param>
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
/// <param name="e">Event arguments.</param>
private void OnItemFilterPropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
AutoCompleteFilterPredicate<object> value = e.NewValue as AutoCompleteFilterPredicate<object>;
var value = e.NewValue as AutoCompleteFilterPredicate<object>;
// If null, revert to the "None" predicate
if (value == null)
@ -810,7 +810,7 @@ namespace Avalonia.Controls
/// <param name="e">Event arguments.</param>
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
/// <value>The <see cref="T:Avalonia.Data.IBinding" /> object used
/// when binding to a collection property.</value>
[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.
/// </remarks>
public object SelectedItem
public object? SelectedItem
{
get { return _selectedItem; }
set { SetAndRaise(SelectedItemProperty, ref _selectedItem, value); }
@ -1010,7 +1011,7 @@ namespace Avalonia.Controls
/// </summary>
/// <value>The text in the text box portion of the
/// <see cref="T:Avalonia.Controls.AutoCompleteBox" /> control.</value>
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.
/// </remarks>
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.
/// </remarks>
public AutoCompleteFilterPredicate<object> ItemFilter
public AutoCompleteFilterPredicate<object?>? 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.
/// </remarks>
public AutoCompleteFilterPredicate<string> TextFilter
public AutoCompleteFilterPredicate<string?>? 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
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.ItemsSource" />.
/// </value>
public AutoCompleteSelector<object> ItemSelector
public AutoCompleteSelector<object>? ItemSelector
{
get { return _itemSelector; }
set { SetAndRaise(ItemSelectorProperty, ref _itemSelector, value); }
@ -1145,13 +1146,13 @@ namespace Avalonia.Controls
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.ItemsSource" />
/// in a text-based way.
/// </value>
public AutoCompleteSelector<string> TextSelector
public AutoCompleteSelector<string?>? TextSelector
{
get { return _textSelector; }
set { SetAndRaise(TextSelectorProperty, ref _textSelector, value); }
}
public Func<string, CancellationToken, Task<IEnumerable<object>>> AsyncPopulator
public Func<string?, CancellationToken, Task<IEnumerable<object>>>? AsyncPopulator
{
get { return _asyncPopulator; }
set { SetAndRaise(AsyncPopulatorProperty, ref _asyncPopulator, value); }
@ -1165,7 +1166,7 @@ namespace Avalonia.Controls
/// <value>The collection that is used to generate the items of the
/// drop-down portion of the
/// <see cref="T:Avalonia.Controls.AutoCompleteBox" /> control.</value>
public IEnumerable Items
public IEnumerable? Items
{
get { return _itemsEnumerable; }
set { SetAndRaise(ItemsProperty, ref _itemsEnumerable, value); }
@ -1174,12 +1175,12 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the drop down popup control.
/// </summary>
private Popup DropDownPopup { get; set; }
private Popup? DropDownPopup { get; set; }
/// <summary>
/// Gets or sets the Text template part.
/// </summary>
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.
/// </remarks>
protected ISelectionAdapter SelectionAdapter
protected ISelectionAdapter? SelectionAdapter
{
get { return _adapter; }
set
@ -1279,10 +1280,10 @@ namespace Avalonia.Controls
/// A <see cref="T:Avalonia.Controls.ISelectionAdapter" /> object,
/// if possible. Otherwise, null.
/// </returns>
protected virtual ISelectionAdapter GetSelectionAdapterPart(INameScope nameScope)
protected virtual ISelectionAdapter? GetSelectionAdapterPart(INameScope nameScope)
{
ISelectionAdapter adapter = null;
SelectingItemsControl selector = nameScope.Find<SelectingItemsControl>(ElementSelector);
ISelectionAdapter? adapter = null;
SelectingItemsControl? selector = nameScope.Find<SelectingItemsControl>(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<Popup>(ElementPopup);
Popup? popup = e.NameScope.Find<Popup>(ElementPopup);
if (popup != null)
{
DropDownPopup = popup;
@ -1358,7 +1359,7 @@ namespace Avalonia.Controls
/// that contains the event data.</param>
protected override void OnKeyDown(KeyEventArgs e)
{
Contract.Requires<ArgumentNullException>(e != null);
_ = e ?? throw new ArgumentNullException(nameof(e));
base.OnKeyDown(e);
@ -1453,7 +1454,7 @@ namespace Avalonia.Controls
/// otherwise, false.</returns>
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
/// <see cref="T:Avalonia.Controls.AutoCompleteBox" /> changes.
/// </summary>
public event EventHandler TextChanged;
public event EventHandler? TextChanged;
/// <summary>
/// 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.
/// </remarks>
public event EventHandler<PopulatingEventArgs> Populating;
public event EventHandler<PopulatingEventArgs>? Populating;
/// <summary>
/// Occurs when the
@ -1544,35 +1545,35 @@ namespace Avalonia.Controls
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.Text" />
/// property.
/// </summary>
public event EventHandler<PopulatedEventArgs> Populated;
public event EventHandler<PopulatedEventArgs>? Populated;
/// <summary>
/// Occurs when the value of the
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.IsDropDownOpen" />
/// property is changing from false to true.
/// </summary>
public event EventHandler<CancelEventArgs> DropDownOpening;
public event EventHandler<CancelEventArgs>? DropDownOpening;
/// <summary>
/// Occurs when the value of the
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.IsDropDownOpen" />
/// property has changed from false to true and the drop-down is open.
/// </summary>
public event EventHandler DropDownOpened;
public event EventHandler? DropDownOpened;
/// <summary>
/// Occurs when the
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.IsDropDownOpen" />
/// property is changing from true to false.
/// </summary>
public event EventHandler<CancelEventArgs> DropDownClosing;
public event EventHandler<CancelEventArgs>? DropDownClosing;
/// <summary>
/// Occurs when the
/// <see cref="P:Avalonia.Controls.AutoCompleteBox.IsDropDownOpen" />
/// property was changed from true to false and the drop-down is open.
/// </summary>
public event EventHandler DropDownClosed;
public event EventHandler? DropDownClosed;
/// <summary>
/// Occurs when the selected item in the drop-down portion of the
@ -1740,7 +1741,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="sender">The source object.</param>
/// <param name="e">The event data.</param>
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
/// </summary>
/// <param name="sender">The source object.</param>
/// <param name="e">The event arguments.</param>
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<object> result = await _asyncPopulator.Invoke(searchText, cancellationToken);
IEnumerable<object> result = await _asyncPopulator!.Invoke(searchText, cancellationToken);
var resultList = result.ToList();
if (cancellationToken.IsCancellationRequested)
@ -1878,9 +1879,9 @@ namespace Avalonia.Controls
/// <param name="clearDataContext">A value indicating whether to clear
/// the data context after the lookup is performed.</param>
/// <returns>Formatted Value.</returns>
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
/// <remarks>
/// Override this method to provide a custom string conversion.
/// </remarks>
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.
/// </summary>
/// <param name="value">The new string value.</param>
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.</param>
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
/// <param name="userInitiated">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.</param>
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<object> 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.
/// </summary>
/// <param name="newValue">The new enumerable reference.</param>
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
/// </summary>
/// <param name="sender">The object that raised the event.</param>
/// <param name="e">The event data.</param>
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<object>(_view));
PopulatedEventArgs populated = new PopulatedEventArgs(new ReadOnlyCollection<object>(_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
/// <param name="predicate">The predicate to use for the partial or
/// exact match.</param>
/// <returns>Returns the object or null.</returns>
private object TryGetMatch(string searchText, AvaloniaList<object> view, AutoCompleteFilterPredicate<string> predicate)
private object? TryGetMatch(string? searchText, AvaloniaList<object> view, AutoCompleteFilterPredicate<string?>? 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.
/// </summary>
/// <param name="newItem">The new item.</param>
private void OnSelectedItemChanged(object newItem)
private void OnSelectedItemChanged(object? newItem)
{
string text;
string? text;
if (newItem == null)
{
@ -2461,9 +2465,9 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="sender">The source object.</param>
/// <param name="e">The selection changed event data.</param>
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
/// </summary>
/// <param name="sender">The source object.</param>
/// <param name="e">The event data.</param>
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();
}
/// <summary>
@ -2490,7 +2494,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="sender">The source object.</param>
/// <param name="e">The event data.</param>
private void OnAdapterSelectionCanceled(object sender, RoutedEventArgs e)
private void OnAdapterSelectionCanceled(object? sender, RoutedEventArgs e)
{
UpdateTextValue(SearchText);
@ -2510,7 +2514,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="FilterMode">The built-in search mode.</param>
/// <returns>Returns the string-based comparison function.</returns>
public static AutoCompleteFilterPredicate<string> GetFilter(AutoCompleteFilterMode FilterMode)
public static AutoCompleteFilterPredicate<string?>? GetFilter(AutoCompleteFilterMode FilterMode)
{
switch (FilterMode)
{
@ -2566,9 +2570,11 @@ namespace Avalonia.Controls
/// <param name="value">The string value to search for.</param>
/// <param name="comparison">The string comparison type.</param>
/// <returns>Returns true when the substring is found.</returns>
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;
}
/// <summary>
@ -2577,9 +2583,11 @@ namespace Avalonia.Controls
/// <param name="text">The AutoCompleteBox prefix text.</param>
/// <param name="value">The item's string value.</param>
/// <returns>Returns true if the condition is met.</returns>
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;
}
/// <summary>
@ -2588,9 +2596,11 @@ namespace Avalonia.Controls
/// <param name="text">The AutoCompleteBox prefix text.</param>
/// <param name="value">The item's string value.</param>
/// <returns>Returns true if the condition is met.</returns>
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;
}
/// <summary>
@ -2599,9 +2609,11 @@ namespace Avalonia.Controls
/// <param name="text">The AutoCompleteBox prefix text.</param>
/// <param name="value">The item's string value.</param>
/// <returns>Returns true if the condition is met.</returns>
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;
}
/// <summary>
@ -2610,9 +2622,11 @@ namespace Avalonia.Controls
/// <param name="text">The AutoCompleteBox prefix text.</param>
/// <param name="value">The item's string value.</param>
/// <returns>Returns true if the condition is met.</returns>
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;
}
/// <summary>
@ -2622,7 +2636,7 @@ namespace Avalonia.Controls
/// <param name="text">The AutoCompleteBox prefix text.</param>
/// <param name="value">The item's string value.</param>
/// <returns>Returns true if the condition is met.</returns>
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
/// <param name="text">The AutoCompleteBox prefix text.</param>
/// <param name="value">The item's string value.</param>
/// <returns>Returns true if the condition is met.</returns>
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
/// <param name="text">The AutoCompleteBox prefix text.</param>
/// <param name="value">The item's string value.</param>
/// <returns>Returns true if the condition is met.</returns>
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
/// <param name="text">The AutoCompleteBox prefix text.</param>
/// <param name="value">The item's string value.</param>
/// <returns>Returns true if the condition is met.</returns>
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
/// <param name="text">The AutoCompleteBox prefix text.</param>
/// <param name="value">The item's string value.</param>
/// <returns>Returns true if the condition is met.</returns>
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);
}
/// <summary>
@ -2677,9 +2691,9 @@ namespace Avalonia.Controls
/// <param name="text">The AutoCompleteBox prefix text.</param>
/// <param name="value">The item's string value.</param>
/// <returns>Returns true if the condition is met.</returns>
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);
}
/// <summary>
@ -2688,9 +2702,9 @@ namespace Avalonia.Controls
/// <param name="text">The AutoCompleteBox prefix text.</param>
/// <param name="value">The item's string value.</param>
/// <returns>Returns true if the condition is met.</returns>
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);
}
/// <summary>
@ -2699,9 +2713,9 @@ namespace Avalonia.Controls
/// <param name="text">The AutoCompleteBox prefix text.</param>
/// <param name="value">The item's string value.</param>
/// <returns>Returns true if the condition is met.</returns>
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
/// <summary>
/// Gets or sets the string value binding used by the control.
/// </summary>
private IBinding _binding;
private IBinding? _binding;
#region public T Value
@ -2739,13 +2753,14 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the value binding.
/// </summary>
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.
/// </summary>
/// <param name="binding">The initial string value binding.</param>
public BindingEvaluator(IBinding binding)
public BindingEvaluator(IBinding? binding)
: this()
{
ValueBinding = binding;
@ -2802,7 +2817,7 @@ namespace Avalonia.Controls
/// <param name="o">The object to use as the data context.</param>
/// <returns>Returns the evaluated T value of the bound dependency
/// property.</returns>
public T GetDynamicValue(object o)
public T GetDynamicValue(object? o)
{
DataContext = o;
return Value;

1
src/Avalonia.Controls/Avalonia.Controls.csproj

@ -18,4 +18,5 @@
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\JetBrains.Annotations.props" />
<Import Project="..\..\build\ApiDiff.props" />
<Import Project="..\..\build\NullableEnable.props" />
</Project>

12
src/Avalonia.Controls/Border.cs

@ -17,14 +17,14 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="Background"/> property.
/// </summary>
public static readonly StyledProperty<IBrush> BackgroundProperty =
AvaloniaProperty.Register<Border, IBrush>(nameof(Background));
public static readonly StyledProperty<IBrush?> BackgroundProperty =
AvaloniaProperty.Register<Border, IBrush?>(nameof(Background));
/// <summary>
/// Defines the <see cref="BorderBrush"/> property.
/// </summary>
public static readonly StyledProperty<IBrush> BorderBrushProperty =
AvaloniaProperty.Register<Border, IBrush>(nameof(BorderBrush));
public static readonly StyledProperty<IBrush?> BorderBrushProperty =
AvaloniaProperty.Register<Border, IBrush?>(nameof(BorderBrush));
/// <summary>
/// Defines the <see cref="BorderThickness"/> property.
@ -91,7 +91,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets a brush with which to paint the background.
/// </summary>
public IBrush Background
public IBrush? Background
{
get { return GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
@ -100,7 +100,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets a brush with which to paint the border.
/// </summary>
public IBrush BorderBrush
public IBrush? BorderBrush
{
get { return GetValue(BorderBrushProperty); }
set { SetValue(BorderBrushProperty, value); }

28
src/Avalonia.Controls/Button.cs

@ -42,21 +42,21 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="Command"/> property.
/// </summary>
public static readonly DirectProperty<Button, ICommand> CommandProperty =
AvaloniaProperty.RegisterDirect<Button, ICommand>(nameof(Command),
public static readonly DirectProperty<Button, ICommand?> CommandProperty =
AvaloniaProperty.RegisterDirect<Button, ICommand?>(nameof(Command),
button => button.Command, (button, command) => button.Command = command, enableDataValidation: true);
/// <summary>
/// Defines the <see cref="HotKey"/> property.
/// </summary>
public static readonly StyledProperty<KeyGesture> HotKeyProperty =
public static readonly StyledProperty<KeyGesture?> HotKeyProperty =
HotKeyManager.HotKeyProperty.AddOwner<Button>();
/// <summary>
/// Defines the <see cref="CommandParameter"/> property.
/// </summary>
public static readonly StyledProperty<object> CommandParameterProperty =
AvaloniaProperty.Register<Button, object>(nameof(CommandParameter));
public static readonly StyledProperty<object?> CommandParameterProperty =
AvaloniaProperty.Register<Button, object?>(nameof(CommandParameter));
/// <summary>
/// Defines the <see cref="IsDefault"/> property.
@ -88,9 +88,9 @@ namespace Avalonia.Controls
public static readonly StyledProperty<FlyoutBase> FlyoutProperty =
AvaloniaProperty.Register<Button, FlyoutBase>(nameof(Flyout));
private ICommand _command;
private ICommand? _command;
private bool _commandCanExecute = true;
private KeyGesture _hotkey;
private KeyGesture? _hotkey;
/// <summary>
/// Initializes static members of the <see cref="Button"/> class.
@ -112,7 +112,7 @@ namespace Avalonia.Controls
/// <summary>
/// Raised when the user clicks the button.
/// </summary>
public event EventHandler<RoutedEventArgs> Click
public event EventHandler<RoutedEventArgs>? Click
{
add => AddHandler(ClickEvent, value);
remove => RemoveHandler(ClickEvent, value);
@ -130,7 +130,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets an <see cref="ICommand"/> to be invoked when the button is clicked.
/// </summary>
public ICommand Command
public ICommand? Command
{
get => _command;
set => SetAndRaise(CommandProperty, ref _command, value);
@ -139,7 +139,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets an <see cref="KeyGesture"/> associated with this control
/// </summary>
public KeyGesture HotKey
public KeyGesture? HotKey
{
get => GetValue(HotKeyProperty);
set => SetValue(HotKeyProperty, value);
@ -148,7 +148,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets a parameter to be passed to the <see cref="Command"/>.
/// </summary>
public object CommandParameter
public object? CommandParameter
{
get => GetValue(CommandParameterProperty);
set => SetValue(CommandParameterProperty, value);
@ -477,7 +477,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
private void CanExecuteChanged(object sender, EventArgs e)
private void CanExecuteChanged(object? sender, EventArgs e)
{
var canExecute = Command == null || Command.CanExecute(CommandParameter);
@ -529,7 +529,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
private void RootDefaultKeyDown(object sender, KeyEventArgs e)
private void RootDefaultKeyDown(object? sender, KeyEventArgs e)
{
if (e.Key == Key.Enter && IsVisible && IsEnabled)
{
@ -542,7 +542,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
private void RootCancelKeyDown(object sender, KeyEventArgs e)
private void RootCancelKeyDown(object? sender, KeyEventArgs e)
{
if (e.Key == Key.Escape && IsVisible && IsEnabled)
{

14
src/Avalonia.Controls/ButtonSpinner.cs

@ -42,11 +42,11 @@ namespace Avalonia.Controls
UpdatePseudoClasses(ButtonSpinnerLocation);
}
private Button _decreaseButton;
private Button? _decreaseButton;
/// <summary>
/// Gets or sets the DecreaseButton template part.
/// </summary>
private Button DecreaseButton
private Button? DecreaseButton
{
get { return _decreaseButton; }
set
@ -63,11 +63,11 @@ namespace Avalonia.Controls
}
}
private Button _increaseButton;
private Button? _increaseButton;
/// <summary>
/// Gets or sets the IncreaseButton template part.
/// </summary>
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
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
private void OnButtonClick(object sender, RoutedEventArgs e)
private void OnButtonClick(object? sender, RoutedEventArgs e)
{
if (AllowSpin)
{

76
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
/// <param name="e">The DependencyPropertyChangedEventArgs.</param>
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<ArgumentNullException>(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
/// </summary>
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<SelectionChangedEventArgs> SelectedDatesChanged;
public event EventHandler<SelectionChangedEventArgs>? SelectedDatesChanged;
/// <summary>
/// Occurs when the
@ -1410,19 +1421,19 @@ namespace Avalonia.Controls
/// <remarks>
/// This event occurs after DisplayDate is assigned its new value.
/// </remarks>
public event EventHandler<CalendarDateChangedEventArgs> DisplayDateChanged;
public event EventHandler<CalendarDateChangedEventArgs>? DisplayDateChanged;
/// <summary>
/// Occurs when the
/// <see cref="P:System.Windows.Controls.Calendar.DisplayMode" />
/// property is changed.
/// </summary>
public event EventHandler<CalendarModeChangedEventArgs> DisplayModeChanged;
public event EventHandler<CalendarModeChangedEventArgs>? DisplayModeChanged;
/// <summary>
/// Inherited code: Requires comment.
/// </summary>
internal event EventHandler<PointerReleasedEventArgs> DayButtonMouseUp;
internal event EventHandler<PointerReleasedEventArgs>? DayButtonMouseUp;
/// <summary>
/// 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<CalendarItem>(PART_ElementMonth);
CalendarItem? month = e.NameScope.Find<CalendarItem>(PART_ElementMonth);
if (month != null)
{

6
src/Avalonia.Controls/Calendar/CalendarButton.cs

@ -45,7 +45,7 @@ namespace Avalonia.Controls.Primitives
/// <summary>
/// Gets or sets the Calendar associated with this button.
/// </summary>
internal Calendar Owner { get; set; }
internal Calendar? Owner { get; set; }
/// <summary>
/// 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.
/// </summary>
public event EventHandler<PointerPressedEventArgs> CalendarLeftMouseButtonDown;
public event EventHandler<PointerPressedEventArgs>? CalendarLeftMouseButtonDown;
/// <summary>
/// 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).
/// </summary>
public event EventHandler<PointerReleasedEventArgs> CalendarLeftMouseButtonUp;
public event EventHandler<PointerReleasedEventArgs>? CalendarLeftMouseButtonUp;
/// <summary>
/// Provides class handling for the MouseLeftButtonDown event that

87
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.
/// </value>
public CalendarBlackoutDatesCollection BlackoutDates { get; private set; }
public CalendarBlackoutDatesCollection? BlackoutDates { get; private set; }
public static readonly DirectProperty<CalendarDatePicker, DateTime> DisplayDateProperty =
AvaloniaProperty.RegisterDirect<CalendarDatePicker, DateTime>(
@ -200,12 +200,12 @@ namespace Avalonia.Controls
defaultValue: "d",
validate: IsValidDateFormatString);
public static readonly DirectProperty<CalendarDatePicker, string> TextProperty =
AvaloniaProperty.RegisterDirect<CalendarDatePicker, string>(
public static readonly DirectProperty<CalendarDatePicker, string?> TextProperty =
AvaloniaProperty.RegisterDirect<CalendarDatePicker, string?>(
nameof(Text),
o => o.Text,
(o, v) => o.Text = v);
public static readonly StyledProperty<string> WatermarkProperty =
public static readonly StyledProperty<string?> WatermarkProperty =
TextBox.WatermarkProperty.AddOwner<CalendarDatePicker>();
public static readonly StyledProperty<bool> UseFloatingWatermarkProperty =
TextBox.UseFloatingWatermarkProperty.AddOwner<CalendarDatePicker>();
@ -361,13 +361,13 @@ namespace Avalonia.Controls
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The text entered parses to a date that is not selectable.
/// </exception>
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
/// <see cref="T:Avalonia.Controls.Calendar" /> is closed.
/// </summary>
public event EventHandler CalendarClosed;
public event EventHandler? CalendarClosed;
/// <summary>
/// Occurs when the drop-down
/// <see cref="T:Avalonia.Controls.Calendar" /> is opened.
/// </summary>
public event EventHandler CalendarOpened;
public event EventHandler? CalendarOpened;
/// <summary>
/// Occurs when <see cref="P:Avalonia.Controls.DatePicker.Text" />
/// is assigned a value that cannot be interpreted as a date.
/// </summary>
public event EventHandler<CalendarDatePickerDateValidationErrorEventArgs> DateValidationError;
public event EventHandler<CalendarDatePickerDateValidationErrorEventArgs>? DateValidationError;
/// <summary>
/// Occurs when the
/// <see cref="P:Avalonia.Controls.CalendarDatePicker.SelectedDate" />
/// property is changed.
/// </summary>
public event EventHandler<SelectionChangedEventArgs> SelectedDateChanged;
public event EventHandler<SelectionChangedEventArgs>? 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<SelectionChangedEventArgs> handler = this.SelectedDateChanged;
EventHandler<SelectionChangedEventArgs>? handler = this.SelectedDateChanged;
if (null != handler)
{
Collection<DateTime> addedItems = new Collection<DateTime>();
@ -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<ArgumentNullException>(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;
}
/// <summary>
@ -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;
}

2
src/Avalonia.Controls/Calendar/CalendarDateRange.cs

@ -65,7 +65,7 @@ namespace Avalonia.Controls
/// <returns>Inherited code: Requires comment 2.</returns>
internal bool ContainsAny(CalendarDateRange range)
{
Contract.Requires<ArgumentNullException>(range != null);
_ = range ?? throw new ArgumentNullException(nameof(range));
int start = DateTime.Compare(Start, range.Start);

6
src/Avalonia.Controls/Calendar/CalendarDayButton.cs

@ -40,7 +40,7 @@ namespace Avalonia.Controls.Primitives
/// <summary>
/// Gets or sets the Calendar associated with this button.
/// </summary>
internal Calendar Owner { get; set; }
internal Calendar? Owner { get; set; }
internal int Index { get; set; }
/// <summary>
@ -177,7 +177,7 @@ namespace Avalonia.Controls.Primitives
/// stylus touches the tablet PC) while the mouse pointer is over a
/// UIElement.
/// </summary>
public event EventHandler<PointerPressedEventArgs> CalendarDayButtonMouseDown;
public event EventHandler<PointerPressedEventArgs>? CalendarDayButtonMouseDown;
/// <summary>
/// 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).
/// </summary>
public event EventHandler<PointerReleasedEventArgs> CalendarDayButtonMouseUp;
public event EventHandler<PointerReleasedEventArgs>? CalendarDayButtonMouseUp;
/// <summary>
/// Provides class handling for the MouseLeftButtonDown event that

100
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<IControl> _dayTitleTemplate;
private Button? _headerButton;
private Button? _nextButton;
private Button? _previousButton;
private ITemplate<IControl>? _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<IBrush> HeaderBackgroundProperty = Calendar.HeaderBackgroundProperty.AddOwner<CalendarItem>();
public IBrush HeaderBackground
@ -57,13 +57,13 @@ namespace Avalonia.Controls.Primitives
get { return GetValue(HeaderBackgroundProperty); }
set { SetValue(HeaderBackgroundProperty, value); }
}
public static readonly DirectProperty<CalendarItem, ITemplate<IControl>> DayTitleTemplateProperty =
AvaloniaProperty.RegisterDirect<CalendarItem, ITemplate<IControl>>(
public static readonly DirectProperty<CalendarItem, ITemplate<IControl>?> DayTitleTemplateProperty =
AvaloniaProperty.RegisterDirect<CalendarItem, ITemplate<IControl>?>(
nameof(DayTitleTemplate),
o => o.DayTitleTemplate,
(o,v) => o.DayTitleTemplate = v,
defaultBindingMode: BindingMode.OneTime);
public ITemplate<IControl> DayTitleTemplate
public ITemplate<IControl>? 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.
/// </summary>
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.
/// </summary>
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.
/// </summary>
internal Button PreviousButton
internal Button? PreviousButton
{
get { return _previousButton; }
private set
@ -156,11 +156,11 @@ namespace Avalonia.Controls.Primitives
/// <summary>
/// Gets the Grid that hosts the content when in month mode.
/// </summary>
internal Grid MonthView { get; set; }
internal Grid? MonthView { get; set; }
/// <summary>
/// Gets the Grid that hosts the content when in year or decade mode.
/// </summary>
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<ArgumentNullException>(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<ArgumentNullException>(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<ArgumentNullException>(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<ArgumentNullException>(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<ArgumentNullException>(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<ArgumentNullException>(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<ArgumentNullException>(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<ArgumentNullException>(b != null);
CalendarButton b = (CalendarButton)sender!;
UpdateYearViewSelection(b);
}
}

2
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)

4
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));
}
/// <summary>
@ -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;

2
src/Avalonia.Controls/Canvas.cs

@ -135,7 +135,7 @@ namespace Avalonia.Controls
/// <param name="from">The control from which movement begins.</param>
/// <param name="wrap">Whether to wrap around when the first or last item is reached.</param>
/// <returns>The control.</returns>
IInputElement INavigableContainer.GetControl(NavigationDirection direction, IInputElement from, bool wrap)
IInputElement? INavigableContainer.GetControl(NavigationDirection direction, IInputElement? from, bool wrap)
{
// TODO: Implement this
return null;

2
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
{
/// <summary>

4
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
{
/// <summary>
@ -36,7 +34,7 @@ namespace Avalonia.Controls.Chrome
}
}
IsVisible = window.PlatformImpl.NeedsManagedDecorations;
IsVisible = window.PlatformImpl?.NeedsManagedDecorations ?? false;
}
}

40
src/Avalonia.Controls/ComboBox.cs

@ -46,8 +46,8 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="SelectionBoxItem"/> property.
/// </summary>
public static readonly DirectProperty<ComboBox, object> SelectionBoxItemProperty =
AvaloniaProperty.RegisterDirect<ComboBox, object>(nameof(SelectionBoxItem), o => o.SelectionBoxItem);
public static readonly DirectProperty<ComboBox, object?> SelectionBoxItemProperty =
AvaloniaProperty.RegisterDirect<ComboBox, object?>(nameof(SelectionBoxItem), o => o.SelectionBoxItem);
/// <summary>
/// Defines the <see cref="VirtualizationMode"/> property.
@ -58,14 +58,14 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="PlaceholderText"/> property.
/// </summary>
public static readonly StyledProperty<string> PlaceholderTextProperty =
AvaloniaProperty.Register<ComboBox, string>(nameof(PlaceholderText));
public static readonly StyledProperty<string?> PlaceholderTextProperty =
AvaloniaProperty.Register<ComboBox, string?>(nameof(PlaceholderText));
/// <summary>
/// Defines the <see cref="PlaceholderForeground"/> property.
/// </summary>
public static readonly StyledProperty<IBrush> PlaceholderForegroundProperty =
AvaloniaProperty.Register<ComboBox, IBrush>(nameof(PlaceholderForeground));
public static readonly StyledProperty<IBrush?> PlaceholderForegroundProperty =
AvaloniaProperty.Register<ComboBox, IBrush?>(nameof(PlaceholderForeground));
/// <summary>
/// Defines the <see cref="HorizontalContentAlignment"/> property.
@ -80,8 +80,8 @@ namespace Avalonia.Controls
ContentControl.VerticalContentAlignmentProperty.AddOwner<ComboBox>();
private bool _isDropDownOpen;
private Popup _popup;
private object _selectionBoxItem;
private Popup? _popup;
private object? _selectionBoxItem;
private readonly CompositeDisposable _subscriptionsOnOpen = new CompositeDisposable();
/// <summary>
@ -117,7 +117,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the item to display as the control's content.
/// </summary>
protected object SelectionBoxItem
protected object? SelectionBoxItem
{
get { return _selectionBoxItem; }
set { SetAndRaise(SelectionBoxItemProperty, ref _selectionBoxItem, value); }
@ -126,7 +126,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the PlaceHolder text.
/// </summary>
public string PlaceholderText
public string? PlaceholderText
{
get { return GetValue(PlaceholderTextProperty); }
set { SetValue(PlaceholderTextProperty, value); }
@ -135,7 +135,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the Brush that renders the placeholder text.
/// </summary>
public IBrush PlaceholderForeground
public IBrush? PlaceholderForeground
{
get { return GetValue(PlaceholderForegroundProperty); }
set { SetValue(PlaceholderForegroundProperty, value); }
@ -262,9 +262,9 @@ namespace Avalonia.Controls
/// <inheritdoc/>
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 +304,7 @@ namespace Avalonia.Controls
}
}
private void PopupClosed(object sender, EventArgs e)
private void PopupClosed(object? sender, EventArgs e)
{
_subscriptionsOnOpen.Clear();
@ -314,7 +314,7 @@ namespace Avalonia.Controls
}
}
private void PopupOpened(object sender, EventArgs e)
private void PopupOpened(object? sender, EventArgs e)
{
TryFocusSelectedItem();
@ -326,7 +326,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;
}
@ -360,12 +360,12 @@ namespace Avalonia.Controls
var selectedIndex = SelectedIndex;
if (IsDropDownOpen && selectedIndex != -1)
{
var container = ItemContainerGenerator.ContainerFromIndex(selectedIndex);
var container = ItemContainerGenerator!.ContainerFromIndex(selectedIndex);
if (container == null && SelectedIndex != -1)
{
ScrollIntoView(Selection.SelectedIndex);
container = ItemContainerGenerator.ContainerFromIndex(selectedIndex);
container = ItemContainerGenerator!.ContainerFromIndex(selectedIndex);
}
if (container != null && CanFocus(container))
@ -377,7 +377,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;
@ -415,7 +415,7 @@ namespace Avalonia.Controls
private void SelectFocusedItem()
{
foreach (ItemContainerInfo dropdownItem in ItemContainerGenerator.Containers)
foreach (ItemContainerInfo dropdownItem in ItemContainerGenerator!.Containers)
{
if (dropdownItem.ContainerControl.IsFocused)
{

14
src/Avalonia.Controls/ContentControl.cs

@ -17,14 +17,14 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="Content"/> property.
/// </summary>
public static readonly StyledProperty<object> ContentProperty =
AvaloniaProperty.Register<ContentControl, object>(nameof(Content));
public static readonly StyledProperty<object?> ContentProperty =
AvaloniaProperty.Register<ContentControl, object?>(nameof(Content));
/// <summary>
/// Defines the <see cref="ContentTemplate"/> property.
/// </summary>
public static readonly StyledProperty<IDataTemplate> ContentTemplateProperty =
AvaloniaProperty.Register<ContentControl, IDataTemplate>(nameof(ContentTemplate));
public static readonly StyledProperty<IDataTemplate?> ContentTemplateProperty =
AvaloniaProperty.Register<ContentControl, IDataTemplate?>(nameof(ContentTemplate));
/// <summary>
/// Defines the <see cref="HorizontalContentAlignment"/> property.
@ -48,7 +48,7 @@ namespace Avalonia.Controls
/// </summary>
[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
/// <summary>
/// Gets or sets the data template used to display the content of the control.
/// </summary>
public IDataTemplate ContentTemplate
public IDataTemplate? ContentTemplate
{
get { return GetValue(ContentTemplateProperty); }
set { SetValue(ContentTemplateProperty, value); }
@ -66,7 +66,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets the presenter from the control's template.
/// </summary>
public IContentPresenter Presenter
public IContentPresenter? Presenter
{
get;
private set;

14
src/Avalonia.Controls/ContextMenu.cs

@ -14,8 +14,6 @@ using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Styling;
#nullable enable
namespace Avalonia.Controls
{
/// <summary>
@ -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)

2
src/Avalonia.Controls/ContextRequestedEventArgs.cs

@ -1,8 +1,6 @@
using Avalonia.Input;
using Avalonia.Interactivity;
#nullable enable
namespace Avalonia.Controls
{
/// <summary>

4
src/Avalonia.Controls/Control.cs

@ -11,8 +11,6 @@ using Avalonia.Rendering;
using Avalonia.Styling;
using Avalonia.VisualTree;
#nullable enable
namespace Avalonia.Controls
{
/// <summary>
@ -129,7 +127,7 @@ namespace Avalonia.Controls
/// <summary>
/// Occurs when the user has completed a context input gesture, such as a right-click.
/// </summary>
public event EventHandler<ContextRequestedEventArgs> ContextRequested
public event EventHandler<ContextRequestedEventArgs>? ContextRequested
{
add => AddHandler(ContextRequestedEvent, value);
remove => RemoveHandler(ContextRequestedEvent, value);

35
src/Avalonia.Controls/ControlExtensions.cs

@ -17,7 +17,7 @@ namespace Avalonia.Controls
/// <param name="control">The control.</param>
public static void BringIntoView(this IControl control)
{
Contract.Requires<ArgumentNullException>(control != null);
_ = control ?? throw new ArgumentNullException(nameof(control));
control.BringIntoView(new Rect(control.Bounds.Size));
}
@ -29,7 +29,7 @@ namespace Avalonia.Controls
/// <param name="rect">The area of the control to being into view.</param>
public static void BringIntoView(this IControl control, Rect rect)
{
Contract.Requires<ArgumentNullException>(control != null);
_ = control ?? throw new ArgumentNullException(nameof(control));
if (control.IsEffectivelyVisible)
{
@ -51,10 +51,10 @@ namespace Avalonia.Controls
/// <param name="control">The control to look in.</param>
/// <param name="name">The name of the control to find.</param>
/// <returns>The control or null if not found.</returns>
public static T FindControl<T>(this IControl control, string name) where T : class, IControl
public static T? FindControl<T>(this IControl control, string name) where T : class, IControl
{
Contract.Requires<ArgumentNullException>(control != null);
Contract.Requires<ArgumentNullException>(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<T>(name);
}
/// <summary>
/// Finds the named control in the scope of the specified control and throws if not found.
/// </summary>
/// <typeparam name="T">The type of the control to find.</typeparam>
/// <param name="control">The control to look in.</param>
/// <param name="name">The name of the control to find.</param>
/// <returns>The control.</returns>
public static T GetControl<T>(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<T>(name) ??
throw new ArgumentException($"Could not find control named '{name}'.");
}
/// <summary>
/// Sets a pseudoclass depending on an observable trigger.
/// </summary>
@ -75,7 +98,7 @@ namespace Avalonia.Controls
/// <returns>A disposable used to cancel the subscription.</returns>
public static IDisposable Set(this IPseudoClasses classes, string name, IObservable<bool> trigger)
{
Contract.Requires<ArgumentNullException>(classes != null);
_ = classes ?? throw new ArgumentNullException(nameof(classes));
return trigger.Subscribe(x => classes.Set(name, x));
}

3
src/Avalonia.Controls/Converters/CornerRadiusFilterConverter.cs

@ -1,5 +1,4 @@
#nullable enable
using System;
using System;
using System.Globalization;
using Avalonia.Data.Converters;

4
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();
}

2
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<object> values, Type targetType, object parameter, CultureInfo culture)
public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
{
if (parameter == null ||
values == null ||

4
src/Avalonia.Controls/Converters/PlatformKeyGestureConverter.cs

@ -13,7 +13,7 @@ namespace Avalonia.Controls.Converters
/// </summary>
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();
}

29
src/Avalonia.Controls/DataValidationErrors.cs

@ -21,8 +21,8 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the DataValidationErrors.Errors attached property.
/// </summary>
public static readonly AttachedProperty<IEnumerable<object>> ErrorsProperty =
AvaloniaProperty.RegisterAttached<DataValidationErrors, Control, IEnumerable<object>>("Errors");
public static readonly AttachedProperty<IEnumerable<object>?> ErrorsProperty =
AvaloniaProperty.RegisterAttached<DataValidationErrors, Control, IEnumerable<object>?>("Errors");
/// <summary>
/// Defines the DataValidationErrors.HasErrors attached property.
@ -34,15 +34,15 @@ namespace Avalonia.Controls
AvaloniaProperty.Register<DataValidationErrors, IDataTemplate>(nameof(ErrorTemplate));
private Control _owner;
private Control? _owner;
public static readonly DirectProperty<DataValidationErrors, Control> OwnerProperty =
AvaloniaProperty.RegisterDirect<DataValidationErrors, Control>(
public static readonly DirectProperty<DataValidationErrors, Control?> OwnerProperty =
AvaloniaProperty.RegisterDirect<DataValidationErrors, Control?>(
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<object>)e.NewValue;
var errors = (IEnumerable<object>?)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<object> GetErrors(Control control)
public static IEnumerable<object>? GetErrors(Control control)
{
return control.GetValue(ErrorsProperty);
}
public static void SetErrors(Control control, IEnumerable<object> errors)
public static void SetErrors(Control control, IEnumerable<object>? 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<object> UnpackException(Exception exception)
private static IEnumerable<object>? 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;
}

60
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
/// <summary>
/// Raised when the <see cref="SelectedDate"/> changes
/// </summary>
public event EventHandler<DatePickerSelectedValueChangedEventArgs> SelectedDateChanged;
public event EventHandler<DatePickerSelectedValueChangedEventArgs>? 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);
}

103
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);
}
}
}

28
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)
{

6
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;
}
}

56
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
/// <summary>
/// Raised when the <see cref="SelectedTime"/> property changes
/// </summary>
public event EventHandler<TimePickerSelectedValueChangedEventArgs> SelectedTimeChanged;
public event EventHandler<TimePickerSelectedValueChangedEventArgs>? 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;
}
}
}

75
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);
}
}
}

10
src/Avalonia.Controls/Decorator.cs

@ -11,8 +11,8 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="Child"/> property.
/// </summary>
public static readonly StyledProperty<IControl> ChildProperty =
AvaloniaProperty.Register<Decorator, IControl>(nameof(Child));
public static readonly StyledProperty<IControl?> ChildProperty =
AvaloniaProperty.Register<Decorator, IControl?>(nameof(Child));
/// <summary>
/// Defines the <see cref="Padding"/> property.
@ -33,7 +33,7 @@ namespace Avalonia.Controls
/// Gets or sets the decorated control.
/// </summary>
[Content]
public IControl Child
public IControl? Child
{
get { return GetValue(ChildProperty); }
set { SetValue(ChildProperty, value); }
@ -66,8 +66,8 @@ namespace Avalonia.Controls
/// <param name="e">The event args.</param>
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)
{

40
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
/// </remarks>
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
/// </summary>
internal abstract double UserMaxSizeValueCache { get; }
internal Grid Parent { get; set; }
internal Grid? Parent { get; set; }
/// <summary>
/// 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
/// <summary>
/// Private getter of shared state collection dynamic property.
/// </summary>
private SharedSizeScope PrivateSharedSizeScope
private SharedSizeScope? PrivateSharedSizeScope
{
get { return (SharedSizeScope)GetValue(PrivateSharedSizeScopeProperty); }
get { return (SharedSizeScope?)GetValue(PrivateSharedSizeScopeProperty); }
}
/// <summary>
@ -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.
/// </summary>
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.
/// <see cref="OnIsSharedSizeScopePropertyChanged"/>
/// </summary>
internal static readonly AttachedProperty<SharedSizeScope> PrivateSharedSizeScopeProperty =
AvaloniaProperty.RegisterAttached<DefinitionBase, Control, SharedSizeScope>(
internal static readonly AttachedProperty<SharedSizeScope?> PrivateSharedSizeScopeProperty =
AvaloniaProperty.RegisterAttached<DefinitionBase, Control, SharedSizeScope?>(
"PrivateSharedSizeScope",
defaultValue: null,
inherits: true);

6
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<T> : AvaloniaList<T> 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)
{

2
src/Avalonia.Controls/Diagnostics/IPopupHostProvider.cs

@ -1,8 +1,6 @@
using System;
using Avalonia.Controls.Primitives;
#nullable enable
namespace Avalonia.Controls.Diagnostics
{
/// <summary>

4
src/Avalonia.Controls/Diagnostics/ToolTipDiagnostics.cs

@ -1,6 +1,4 @@
#nullable enable
namespace Avalonia.Controls.Diagnostics
namespace Avalonia.Controls.Diagnostics
{
/// <summary>
/// Helper class to provide diagnostics information for <see cref="ToolTip"/>.

20
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<RawInputEventArgs> Input { get; set; }
public Action<Rect> Paint { get; set; }
public Action<Size, PlatformResizeReason> Resized { get; set; }
public Action<double> ScalingChanged { get; set; }
public Action<RawInputEventArgs>? Input { get; set; }
public Action<Rect>? Paint { get; set; }
public Action<Size, PlatformResizeReason>? Resized { get; set; }
public Action<double>? ScalingChanged { get; set; }
public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; }
public Action<WindowTransparencyLevel>? TransparencyLevelChanged { get; set; }
/// <inheritdoc/>
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;
}
}

3
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
{
/// <summary>

7
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:

2
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

20
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);
}
/// <summary>
@ -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)

8
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
/// <summary>
/// Defines the <see cref="Items"/> property
/// </summary>
public static readonly DirectProperty<MenuFlyout, IEnumerable> ItemsProperty =
public static readonly DirectProperty<MenuFlyout, IEnumerable?> ItemsProperty =
ItemsControl.ItemsProperty.AddOwner<MenuFlyout>(x => x.Items,
(x, v) => x.Items = v);
@ -35,7 +33,7 @@ namespace Avalonia.Controls
/// Gets or sets the items of the MenuFlyout
/// </summary>
[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()

12
src/Avalonia.Controls/Generators/IItemContainerGenerator.cs

@ -17,27 +17,27 @@ namespace Avalonia.Controls.Generators
/// <summary>
/// Gets or sets the data template used to display the items in the control.
/// </summary>
IDataTemplate ItemTemplate { get; set; }
IDataTemplate? ItemTemplate { get; set; }
/// <summary>
/// Gets the ContainerType, or null if its an untyped ContainerGenerator.
/// </summary>
Type ContainerType { get; }
Type? ContainerType { get; }
/// <summary>
/// Signaled whenever new containers are materialized.
/// </summary>
event EventHandler<ItemContainerEventArgs> Materialized;
event EventHandler<ItemContainerEventArgs>? Materialized;
/// <summary>
/// Event raised whenever containers are dematerialized.
/// </summary>
event EventHandler<ItemContainerEventArgs> Dematerialized;
event EventHandler<ItemContainerEventArgs>? Dematerialized;
/// <summary>
/// Event raised whenever containers are recycled.
/// </summary>
event EventHandler<ItemContainerEventArgs> Recycled;
event EventHandler<ItemContainerEventArgs>? Recycled;
/// <summary>
/// Creates a container control for an item.
@ -90,7 +90,7 @@ namespace Avalonia.Controls.Generators
/// </summary>
/// <param name="index">The index.</param>
/// <returns>The container, or null if no container created.</returns>
IControl ContainerFromIndex(int index);
IControl? ContainerFromIndex(int index);
/// <summary>
/// Gets the index of the specified container control.

2
src/Avalonia.Controls/Generators/ITreeItemContainerGenerator.cs

@ -8,7 +8,7 @@ namespace Avalonia.Controls.Generators
/// <summary>
/// Gets the container index for the tree.
/// </summary>
TreeContainerIndex Index { get; }
TreeContainerIndex? Index { get; }
/// <summary>
/// Updates the index based on the parent <see cref="TreeView"/>.

26
src/Avalonia.Controls/Generators/ItemContainerGenerator.cs

@ -20,27 +20,25 @@ namespace Avalonia.Controls.Generators
/// <param name="owner">The owner control.</param>
public ItemContainerGenerator(IControl owner)
{
Contract.Requires<ArgumentNullException>(owner != null);
Owner = owner;
Owner = owner ?? throw new ArgumentNullException(nameof(owner));
}
/// <inheritdoc/>
public IEnumerable<ItemContainerInfo> Containers => _containers.Values;
/// <inheritdoc/>
public event EventHandler<ItemContainerEventArgs> Materialized;
public event EventHandler<ItemContainerEventArgs>? Materialized;
/// <inheritdoc/>
public event EventHandler<ItemContainerEventArgs> Dematerialized;
public event EventHandler<ItemContainerEventArgs>? Dematerialized;
/// <inheritdoc/>
public event EventHandler<ItemContainerEventArgs> Recycled;
public event EventHandler<ItemContainerEventArgs>? Recycled;
/// <summary>
/// Gets or sets the data template used to display the items in the control.
/// </summary>
public IDataTemplate ItemTemplate { get; set; }
public IDataTemplate? ItemTemplate { get; set; }
/// <summary>
/// Gets the owner control.
@ -48,12 +46,12 @@ namespace Avalonia.Controls.Generators
public IControl Owner { get; }
/// <inheritdoc/>
public virtual Type ContainerType => null;
public virtual Type? ContainerType => null;
/// <inheritdoc/>
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
}
/// <inheritdoc/>
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
/// </summary>
/// <param name="item">The item.</param>
/// <returns>The created container control.</returns>
protected virtual IControl CreateContainer(object item)
protected virtual IControl? CreateContainer(object item)
{
var result = item as IControl;

11
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<ArgumentNullException>(owner != null);
Contract.Requires<ArgumentNullException>(contentProperty != null);
ContentProperty = contentProperty;
ContentProperty = contentProperty ?? throw new ArgumentNullException(nameof(contentProperty));
ContentTemplateProperty = contentTemplateProperty;
}
@ -40,10 +37,10 @@ namespace Avalonia.Controls.Generators
/// <summary>
/// Gets the container's ContentTemplate property.
/// </summary>
protected AvaloniaProperty ContentTemplateProperty { get; }
protected AvaloniaProperty? ContentTemplateProperty { get; }
/// <inheritdoc/>
protected override IControl CreateContainer(object item)
protected override IControl? CreateContainer(object item)
{
var container = item as T;

2
src/Avalonia.Controls/Generators/MenuItemContainerGenerator.cs

@ -12,7 +12,7 @@
}
/// <inheritdoc/>
protected override IControl CreateContainer(object item)
protected override IControl? CreateContainer(object item)
{
var separator = item as Separator;
return separator != null ? separator : base.CreateContainer(item);

12
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<Dock>(
tabItem,
@ -28,7 +28,7 @@ namespace Avalonia.Controls.Generators
if (tabItem.HeaderTemplate == null)
{
tabItem.Bind(TabItem.HeaderTemplateProperty, new OwnerBinding<IDataTemplate>(
tabItem.Bind(TabItem.HeaderTemplateProperty, new OwnerBinding<IDataTemplate?>(
tabItem,
TabControl.ItemTemplateProperty));
}
@ -50,7 +50,7 @@ namespace Avalonia.Controls.Generators
if (!(tabItem.Content is IControl))
{
tabItem.Bind(TabItem.ContentTemplateProperty, new OwnerBinding<IDataTemplate>(
tabItem.Bind(TabItem.ContentTemplateProperty, new OwnerBinding<IDataTemplate?>(
tabItem,
TabControl.ContentTemplateProperty));
}
@ -62,8 +62,8 @@ namespace Avalonia.Controls.Generators
{
private readonly TabItem _item;
private readonly StyledProperty<T> _ownerProperty;
private IDisposable _ownerSubscription;
private IDisposable _propertySubscription;
private IDisposable? _ownerSubscription;
private IDisposable? _propertySubscription;
public OwnerBinding(TabItem item, StyledProperty<T> 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;

8
src/Avalonia.Controls/Generators/TreeContainerIndex.cs

@ -21,12 +21,12 @@ namespace Avalonia.Controls.Generators
/// <summary>
/// Signaled whenever new containers are materialized.
/// </summary>
public event EventHandler<ItemContainerEventArgs> Materialized;
public event EventHandler<ItemContainerEventArgs>? Materialized;
/// <summary>
/// Event raised whenever containers are dematerialized.
/// </summary>
public event EventHandler<ItemContainerEventArgs> Dematerialized;
public event EventHandler<ItemContainerEventArgs>? Dematerialized;
/// <summary>
/// Gets the currently materialized containers.
@ -92,7 +92,7 @@ namespace Avalonia.Controls.Generators
/// </summary>
/// <param name="item">The item.</param>
/// <returns>The container, or null of not found.</returns>
public IControl ContainerFromItem(object item)
public IControl? ContainerFromItem(object item)
{
if (item != null)
{
@ -108,7 +108,7 @@ namespace Avalonia.Controls.Generators
/// </summary>
/// <param name="container">The container.</param>
/// <returns>The item, or null of not found.</returns>
public object ItemFromContainer(IControl container)
public object? ItemFromContainer(IControl? container)
{
if (container != null)
{

23
src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs

@ -14,7 +14,7 @@ namespace Avalonia.Controls.Generators
public class TreeItemContainerGenerator<T> : ItemContainerGenerator<T>, ITreeItemContainerGenerator
where T : class, IControl, new()
{
private TreeView _treeView;
private TreeView? _treeView;
/// <summary>
/// Initializes a new instance of the <see cref="TreeItemContainerGenerator{T}"/> class.
@ -32,20 +32,15 @@ namespace Avalonia.Controls.Generators
AvaloniaProperty isExpandedProperty)
: base(owner, contentProperty, contentTemplateProperty)
{
Contract.Requires<ArgumentNullException>(owner != null);
Contract.Requires<ArgumentNullException>(contentProperty != null);
Contract.Requires<ArgumentNullException>(itemsProperty != null);
Contract.Requires<ArgumentNullException>(isExpandedProperty != null);
ItemsProperty = itemsProperty;
IsExpandedProperty = isExpandedProperty;
ItemsProperty = itemsProperty ?? throw new ArgumentNullException(nameof(itemsProperty));
IsExpandedProperty = isExpandedProperty ?? throw new ArgumentNullException(nameof(isExpandedProperty));
UpdateIndex();
}
/// <summary>
/// Gets the container index for the tree.
/// </summary>
public TreeContainerIndex Index { get; private set; }
public TreeContainerIndex? Index { get; private set; }
/// <summary>
/// Gets the item container's Items property.
@ -58,7 +53,7 @@ namespace Avalonia.Controls.Generators
protected AvaloniaProperty IsExpandedProperty { get; }
/// <inheritdoc/>
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);

165
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
/// <param name="value">Column property value.</param>
public static void SetColumn(Control element, int value)
{
Contract.Requires<ArgumentNullException>(element != null);
_ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(ColumnProperty, value);
}
@ -59,7 +60,7 @@ namespace Avalonia.Controls
/// <returns>Column property value.</returns>
public static int GetColumn(Control element)
{
Contract.Requires<ArgumentNullException>(element != null);
_ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(ColumnProperty);
}
@ -70,7 +71,7 @@ namespace Avalonia.Controls
/// <param name="value">Row property value.</param>
public static void SetRow(Control element, int value)
{
Contract.Requires<ArgumentNullException>(element != null);
_ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(RowProperty, value);
}
@ -81,7 +82,7 @@ namespace Avalonia.Controls
/// <returns>Row property value.</returns>
public static int GetRow(Control element)
{
Contract.Requires<ArgumentNullException>(element != null);
_ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(RowProperty);
}
@ -92,7 +93,7 @@ namespace Avalonia.Controls
/// <param name="value">ColumnSpan property value.</param>
public static void SetColumnSpan(Control element, int value)
{
Contract.Requires<ArgumentNullException>(element != null);
_ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(ColumnSpanProperty, value);
}
@ -103,7 +104,7 @@ namespace Avalonia.Controls
/// <returns>ColumnSpan property value.</returns>
public static int GetColumnSpan(Control element)
{
Contract.Requires<ArgumentNullException>(element != null);
_ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(ColumnSpanProperty);
}
@ -114,7 +115,7 @@ namespace Avalonia.Controls
/// <param name="value">RowSpan property value.</param>
public static void SetRowSpan(Control element, int value)
{
Contract.Requires<ArgumentNullException>(element != null);
_ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(RowSpanProperty, value);
}
@ -125,7 +126,7 @@ namespace Avalonia.Controls
/// <returns>RowSpan property value.</returns>
public static int GetRowSpan(Control element)
{
Contract.Requires<ArgumentNullException>(element != null);
_ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(RowSpanProperty);
}
@ -136,7 +137,7 @@ namespace Avalonia.Controls
/// <param name="value">IsSharedSizeScope property value.</param>
public static void SetIsSharedSizeScope(Control element, bool value)
{
Contract.Requires<ArgumentNullException>(element != null);
_ = element ?? throw new ArgumentNullException(nameof(element));
element.SetValue(IsSharedSizeScopeProperty, value);
}
@ -147,7 +148,7 @@ namespace Avalonia.Controls
/// <returns>IsSharedSizeScope property value.</returns>
public static bool GetIsSharedSizeScope(Control element)
{
Contract.Requires<ArgumentNullException>(element != null);
_ = element ?? throw new ArgumentNullException(nameof(element));
return element.GetValue(IsSharedSizeScopeProperty);
}
@ -573,7 +574,7 @@ namespace Avalonia.Controls
/// <summary>
/// <see cref="Panel.ChildrenChanged"/>
/// </summary>
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<NullReferenceException>(_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<NullReferenceException>(_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
/// <param name="u"><c>true</c> if this is a column span. <c>false</c> if this is a row span.</param>
/// <param name="value">Value to store. If an entry already exists the biggest value is stored.</param>
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.
/// </summary>
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? grid = child.GetVisualParent<Grid>();
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.
/// </returns>
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
/// </summary>
private IReadOnlyList<DefinitionBase> DefinitionsU
{
get { return (ExtData.DefinitionsU); }
get { return (ExtData.DefinitionsU!); }
}
/// <summary>
@ -2434,7 +2435,7 @@ namespace Avalonia.Controls
/// </summary>
private IReadOnlyList<DefinitionBase> DefinitionsV
{
get { return (ExtData.DefinitionsV); }
get { return (ExtData.DefinitionsV!); }
}
/// <summary>
@ -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
/// </summary>
private CellCache[] PrivateCells
{
get { return (ExtData.CellCachesCollection); }
get { return (ExtData.CellCachesCollection!); }
}
/// <summary>
@ -2586,7 +2587,7 @@ namespace Avalonia.Controls
/// </summary>
private ExtendedData ExtData
{
get { return (_data); }
get { return (_data!); }
}
/// <summary>
@ -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
/// </summary>
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<DefinitionBase> DefinitionsU; // collection of column definitions used during calc
internal IReadOnlyList<DefinitionBase> 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<DefinitionBase>? DefinitionsU; // collection of column definitions used during calc
internal IReadOnlyList<DefinitionBase>? 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
/// <summary>
/// <see cref="object.Equals(object)"/>
/// </summary>
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
/// </summary>
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
/// </summary>
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<DefinitionBase> definitions)
{
Contract.Requires<NullReferenceException>(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<DefinitionBase> definitions)
{
Contract.Requires<NullReferenceException>(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<NullReferenceException>(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
/// </summary>
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
/// </summary>
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
/// </summary>
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<DefinitionBase> definitions)
{
Contract.Requires<NullReferenceException>(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<DefinitionBase> definitions)
{
Contract.Requires<NullReferenceException>(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<DefinitionBase> definitions)
{
Contract.Requires<NullReferenceException>(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)
{

2
src/Avalonia.Controls/GridLength.cs

@ -135,7 +135,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="o">The object with which to test equality.</param>
/// <returns>True if the objects are equal, otherwise false.</returns>
public override bool Equals(object o)
public override bool Equals(object? o)
{
if (o == null)
{

62
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;
/// <summary>
/// Indicates whether the Splitter resizes the Columns, Rows, or Both.
@ -197,9 +197,9 @@ namespace Avalonia.Controls
/// </summary>
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
/// </summary>
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
/// </summary>
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
/// </summary>
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<DefinitionBase>)_resizeData.Grid.ColumnDefinitions :
(IAvaloniaReadOnlyList<DefinitionBase>)_resizeData.Grid.RowDefinitions;
(IAvaloniaReadOnlyList<DefinitionBase>)_resizeData.Grid!.ColumnDefinitions :
(IAvaloniaReadOnlyList<DefinitionBase>)_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;

40
src/Avalonia.Controls/HotkeyManager.cs

@ -7,29 +7,29 @@ namespace Avalonia.Controls
{
public class HotKeyManager
{
public static readonly AttachedProperty<KeyGesture> HotKeyProperty
= AvaloniaProperty.RegisterAttached<Control, KeyGesture>("HotKey", typeof(HotKeyManager));
public static readonly AttachedProperty<KeyGesture?> HotKeyProperty
= AvaloniaProperty.RegisterAttached<Control, KeyGesture?>("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<TopLevel>(_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);
}
}

6
src/Avalonia.Controls/IContentControl.cs

@ -12,12 +12,12 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the content to display.
/// </summary>
object Content { get; set; }
object? Content { get; set; }
/// <summary>
/// Gets or sets the data template used to display the content of the control.
/// </summary>
IDataTemplate ContentTemplate { get; set; }
IDataTemplate? ContentTemplate { get; set; }
/// <summary>
/// Gets or sets the horizontal alignment of the content within the control.
@ -29,4 +29,4 @@ namespace Avalonia.Controls
/// </summary>
VerticalAlignment VerticalContentAlignment { get; set; }
}
}
}

2
src/Avalonia.Controls/IControl.cs

@ -3,8 +3,6 @@ using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.VisualTree;
#nullable enable
namespace Avalonia.Controls
{
/// <summary>

2
src/Avalonia.Controls/IHeadered.cs

@ -8,6 +8,6 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or set the header.
/// </summary>
object Header { get; set; }
object? Header { get; set; }
}
}

2
src/Avalonia.Controls/IMenuElement.cs

@ -1,8 +1,6 @@
using System.Collections.Generic;
using Avalonia.Input;
#nullable enable
namespace Avalonia.Controls
{
/// <summary>

4
src/Avalonia.Controls/IMenuItem.cs

@ -1,6 +1,4 @@
#nullable enable
namespace Avalonia.Controls
namespace Avalonia.Controls
{
/// <summary>
/// Represents a <see cref="MenuItem"/>.

4
src/Avalonia.Controls/IScrollAnchorProvider.cs

@ -1,6 +1,4 @@
#nullable enable
namespace Avalonia.Controls
namespace Avalonia.Controls
{
/// <summary>
/// Specifies a contract for a scrolling control that supports scroll anchoring.

2
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.
/// </remarks>
IVirtualizingController Controller { get; set; }
IVirtualizingController? Controller { get; set; }
/// <summary>
/// Gets a value indicating whether the panel is full.

56
src/Avalonia.Controls/ItemsControl.cs

@ -32,8 +32,8 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="Items"/> property.
/// </summary>
public static readonly DirectProperty<ItemsControl, IEnumerable> ItemsProperty =
AvaloniaProperty.RegisterDirect<ItemsControl, IEnumerable>(nameof(Items), o => o.Items, (o, v) => o.Items = v);
public static readonly DirectProperty<ItemsControl, IEnumerable?> ItemsProperty =
AvaloniaProperty.RegisterDirect<ItemsControl, IEnumerable?>(nameof(Items), o => o.Items, (o, v) => o.Items = v);
/// <summary>
/// Defines the <see cref="ItemCount"/> property.
@ -50,13 +50,13 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="ItemTemplate"/> property.
/// </summary>
public static readonly StyledProperty<IDataTemplate> ItemTemplateProperty =
AvaloniaProperty.Register<ItemsControl, IDataTemplate>(nameof(ItemTemplate));
public static readonly StyledProperty<IDataTemplate?> ItemTemplateProperty =
AvaloniaProperty.Register<ItemsControl, IDataTemplate?>(nameof(ItemTemplate));
private IEnumerable _items = new AvaloniaList<object>();
private IEnumerable? _items = new AvaloniaList<object>();
private int _itemCount;
private IItemContainerGenerator _itemContainerGenerator;
private EventHandler<ChildIndexChangedEventArgs> _childIndexChanged;
private IItemContainerGenerator? _itemContainerGenerator;
private EventHandler<ChildIndexChangedEventArgs>? _childIndexChanged;
/// <summary>
/// Initializes static members of the <see cref="ItemsControl"/> class.
@ -79,7 +79,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets the <see cref="IItemContainerGenerator"/> for the control.
/// </summary>
public IItemContainerGenerator ItemContainerGenerator
public IItemContainerGenerator? ItemContainerGenerator
{
get
{
@ -104,7 +104,7 @@ namespace Avalonia.Controls
/// Gets or sets the items to display.
/// </summary>
[Content]
public IEnumerable Items
public IEnumerable? Items
{
get { return _items; }
set { SetAndRaise(ItemsProperty, ref _items, value); }
@ -131,7 +131,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the data template used to display the items in the control.
/// </summary>
public IDataTemplate ItemTemplate
public IDataTemplate? ItemTemplate
{
get { return GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
@ -140,13 +140,13 @@ namespace Avalonia.Controls
/// <summary>
/// Gets the items presenter control.
/// </summary>
public IItemsPresenter Presenter
public IItemsPresenter? Presenter
{
get;
protected set;
}
event EventHandler<ChildIndexChangedEventArgs> IChildIndexProvider.ChildIndexChanged
event EventHandler<ChildIndexChangedEventArgs>? IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
@ -161,7 +161,7 @@ namespace Avalonia.Controls
}
Presenter = presenter;
ItemContainerGenerator.Clear();
ItemContainerGenerator?.Clear();
if (Presenter is IChildIndexProvider innerProvider)
{
@ -189,11 +189,11 @@ namespace Avalonia.Controls
/// <param name="items">The collection.</param>
/// <param name="index">The index.</param>
/// <returns>The item at the given index or null if the index is out of bounds.</returns>
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 +207,7 @@ namespace Avalonia.Controls
/// <param name="items">The collection.</param>
/// <param name="item">The item.</param>
/// <returns>The index of the item or -1 if the item was not found.</returns>
protected static int IndexOf(IEnumerable items, object item)
protected static int IndexOf(IEnumerable? items, object item)
{
if (items != null && item != null)
{
@ -282,7 +282,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 +311,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, false);
if (next != null)
{
@ -406,7 +406,7 @@ namespace Avalonia.Controls
/// Given a collection of items, adds those that are controls to the logical children.
/// </summary>
/// <param name="items">The items.</param>
private void AddControlItemsToLogicalChildren(IEnumerable items)
private void AddControlItemsToLogicalChildren(IEnumerable? items)
{
var toAdd = new List<ILogical>();
@ -430,7 +430,7 @@ namespace Avalonia.Controls
/// Given a collection of items, removes those that are controls to from logical children.
/// </summary>
/// <param name="items">The items.</param>
private void RemoveControlItemsFromLogicalChildren(IEnumerable items)
private void RemoveControlItemsFromLogicalChildren(IEnumerable? items)
{
var toRemove = new List<ILogical>();
@ -454,7 +454,7 @@ namespace Avalonia.Controls
/// Subscribes to an <see cref="Items"/> collection.
/// </summary>
/// <param name="items">The items collection.</param>
private void SubscribeToItems(IEnumerable items)
private void SubscribeToItems(IEnumerable? items)
{
if (items is INotifyCollectionChanged incc)
{
@ -470,7 +470,7 @@ namespace Avalonia.Controls
{
if (_itemContainerGenerator != null)
{
_itemContainerGenerator.ItemTemplate = (IDataTemplate)e.NewValue;
_itemContainerGenerator.ItemTemplate = (IDataTemplate?)e.NewValue;
// TODO: Rebuild the item containers.
}
}
@ -497,13 +497,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 +525,7 @@ namespace Avalonia.Controls
return null;
}
private void PresenterChildIndexChanged(object sender, ChildIndexChangedEventArgs e)
private void PresenterChildIndexChanged(object? sender, ChildIndexChangedEventArgs e)
{
_childIndexChanged?.Invoke(this, e);
}

8
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
{
/// <summary>
@ -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
/// </summary>
/// <param name="index">The index.</param>
/// <returns>The item.</returns>
[return: MaybeNull]
public new T GetAt(int index) => (T)Inner[index];
public new T GetAt(int index) => (T)Inner[index]!;
public IEnumerator<T> GetEnumerator() => Inner.Cast<T>().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => Inner.GetEnumerator();

8
src/Avalonia.Controls/Label.cs

@ -18,19 +18,19 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="Target"/> Direct property
/// </summary>
public static readonly DirectProperty<Label, IInputElement> TargetProperty =
AvaloniaProperty.RegisterDirect<Label, IInputElement>(nameof(Target), lbl => lbl.Target, (lbl, inp) => lbl.Target = inp);
public static readonly DirectProperty<Label, IInputElement?> TargetProperty =
AvaloniaProperty.RegisterDirect<Label, IInputElement?>(nameof(Target), lbl => lbl.Target, (lbl, inp) => lbl.Target = inp);
/// <summary>
/// Label focus target storage field
/// </summary>
private IInputElement _target;
private IInputElement? _target;
/// <summary>
/// Label focus Target
/// </summary>
[ResolveByName]
public IInputElement Target
public IInputElement? Target
{
get => _target;
set => SetAndRaise(TargetProperty, ref _target, value);

14
src/Avalonia.Controls/LayoutTransformControl.cs

@ -14,8 +14,8 @@ namespace Avalonia.Controls
/// </summary>
public class LayoutTransformControl : Decorator
{
public static readonly StyledProperty<ITransform> LayoutTransformProperty =
AvaloniaProperty.Register<LayoutTransformControl, ITransform>(nameof(LayoutTransform));
public static readonly StyledProperty<ITransform?> LayoutTransformProperty =
AvaloniaProperty.Register<LayoutTransformControl, ITransform?>(nameof(LayoutTransform));
public static readonly StyledProperty<bool> UseRenderTransformProperty =
AvaloniaProperty.Register<LayoutTransformControl, bool>(nameof(UseRenderTransform));
@ -37,7 +37,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets a graphics transformation that should apply to this element when layout is performed.
/// </summary>
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;
/// <summary>
/// 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.
/// </summary>
private Matrix _transformation;
private IDisposable _transformChangedEvent = null;
private IDisposable? _transformChangedEvent = null;
/// <summary>
/// Returns true if Size a is smaller than Size b in either dimension.

12
src/Avalonia.Controls/ListBox.cs

@ -23,13 +23,13 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="Scroll"/> property.
/// </summary>
public static readonly DirectProperty<ListBox, IScrollable> ScrollProperty =
AvaloniaProperty.RegisterDirect<ListBox, IScrollable>(nameof(Scroll), o => o.Scroll);
public static readonly DirectProperty<ListBox, IScrollable?> ScrollProperty =
AvaloniaProperty.RegisterDirect<ListBox, IScrollable?>(nameof(Scroll), o => o.Scroll);
/// <summary>
/// Defines the <see cref="SelectedItems"/> property.
/// </summary>
public static readonly new DirectProperty<SelectingItemsControl, IList> SelectedItemsProperty =
public static readonly new DirectProperty<SelectingItemsControl, IList?> SelectedItemsProperty =
SelectingItemsControl.SelectedItemsProperty;
/// <summary>
@ -50,7 +50,7 @@ namespace Avalonia.Controls
public static readonly StyledProperty<ItemVirtualizationMode> VirtualizationModeProperty =
ItemsPresenter.VirtualizationModeProperty.AddOwner<ListBox>();
private IScrollable _scroll;
private IScrollable? _scroll;
/// <summary>
/// Initializes static members of the <see cref="ItemsControl"/> class.
@ -64,14 +64,14 @@ namespace Avalonia.Controls
/// <summary>
/// Gets the scroll information for the <see cref="ListBox"/>.
/// </summary>
public IScrollable Scroll
public IScrollable? Scroll
{
get { return _scroll; }
private set { SetAndRaise(ScrollProperty, ref _scroll, value); }
}
/// <inheritdoc/>
public new IList SelectedItems
public new IList? SelectedItems
{
get => base.SelectedItems;
set => base.SelectedItems = value;

10
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++;
}

2
src/Avalonia.Controls/Menu.cs

@ -5,8 +5,6 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
#nullable enable
namespace Avalonia.Controls
{
/// <summary>

13
src/Avalonia.Controls/MenuBase.cs

@ -8,8 +8,6 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
#nullable enable
namespace Avalonia.Controls
{
/// <summary>
@ -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;
}
}
@ -97,7 +96,7 @@ namespace Avalonia.Controls
{
get
{
return ItemContainerGenerator.Containers
return ItemContainerGenerator!.Containers
.Select(x => x.ContainerControl)
.OfType<IMenuItem>();
}
@ -111,7 +110,7 @@ namespace Avalonia.Controls
/// <summary>
/// Occurs when a <see cref="Menu"/> is opened.
/// </summary>
public event EventHandler<RoutedEventArgs> MenuOpened
public event EventHandler<RoutedEventArgs>? MenuOpened
{
add { AddHandler(MenuOpenedEvent, value); }
remove { RemoveHandler(MenuOpenedEvent, value); }
@ -120,7 +119,7 @@ namespace Avalonia.Controls
/// <summary>
/// Occurs when a <see cref="Menu"/> is closed.
/// </summary>
public event EventHandler<RoutedEventArgs> MenuClosed
public event EventHandler<RoutedEventArgs>? MenuClosed
{
add { AddHandler(MenuClosedEvent, value); }
remove { RemoveHandler(MenuClosedEvent, value); }

44
src/Avalonia.Controls/MenuItem.cs

@ -14,8 +14,6 @@ using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.VisualTree;
#nullable enable
namespace Avalonia.Controls
{
/// <summary>
@ -42,20 +40,20 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="CommandParameter"/> property.
/// </summary>
public static readonly StyledProperty<object> CommandParameterProperty =
public static readonly StyledProperty<object?> CommandParameterProperty =
Button.CommandParameterProperty.AddOwner<MenuItem>();
/// <summary>
/// Defines the <see cref="Icon"/> property.
/// </summary>
public static readonly StyledProperty<object> IconProperty =
AvaloniaProperty.Register<MenuItem, object>(nameof(Icon));
public static readonly StyledProperty<object?> IconProperty =
AvaloniaProperty.Register<MenuItem, object?>(nameof(Icon));
/// <summary>
/// Defines the <see cref="InputGesture"/> property.
/// </summary>
public static readonly StyledProperty<KeyGesture> InputGestureProperty =
AvaloniaProperty.Register<MenuItem, KeyGesture>(nameof(InputGesture));
public static readonly StyledProperty<KeyGesture?> InputGestureProperty =
AvaloniaProperty.Register<MenuItem, KeyGesture?>(nameof(InputGesture));
/// <summary>
/// Defines the <see cref="IsSelected"/> property.
@ -164,7 +162,7 @@ namespace Avalonia.Controls
/// <summary>
/// Occurs when a <see cref="MenuItem"/> without a submenu is clicked.
/// </summary>
public event EventHandler<RoutedEventArgs> Click
public event EventHandler<RoutedEventArgs>? Click
{
add { AddHandler(ClickEvent, value); }
remove { RemoveHandler(ClickEvent, value); }
@ -176,7 +174,7 @@ namespace Avalonia.Controls
/// <remarks>
/// A bubbling version of the <see cref="InputElement.PointerEnter"/> event for menu items.
/// </remarks>
public event EventHandler<PointerEventArgs> PointerEnterItem
public event EventHandler<PointerEventArgs>? PointerEnterItem
{
add { AddHandler(PointerEnterItemEvent, value); }
remove { RemoveHandler(PointerEnterItemEvent, value); }
@ -188,7 +186,7 @@ namespace Avalonia.Controls
/// <remarks>
/// A bubbling version of the <see cref="InputElement.PointerLeave"/> event for menu items.
/// </remarks>
public event EventHandler<PointerEventArgs> PointerLeaveItem
public event EventHandler<PointerEventArgs>? PointerLeaveItem
{
add { AddHandler(PointerLeaveItemEvent, value); }
remove { RemoveHandler(PointerLeaveItemEvent, value); }
@ -197,7 +195,7 @@ namespace Avalonia.Controls
/// <summary>
/// Occurs when a <see cref="MenuItem"/>'s submenu is opened.
/// </summary>
public event EventHandler<RoutedEventArgs> SubmenuOpened
public event EventHandler<RoutedEventArgs>? 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 <see cref="Command"/> property of a
/// <see cref="MenuItem"/>.
/// </summary>
public object CommandParameter
public object? CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
@ -234,7 +232,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the icon that appears in a <see cref="MenuItem"/>.
/// </summary>
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.
/// </remarks>
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;
}
}
@ -324,7 +322,7 @@ namespace Avalonia.Controls
{
get
{
return ItemContainerGenerator.Containers
return ItemContainerGenerator!.Containers
.Select(x => x.ContainerControl)
.OfType<IMenuItem>();
}
@ -390,7 +388,7 @@ namespace Avalonia.Controls
parent = parent.Parent;
}
_isEmbeddedInMenu = parent.FindLogicalAncestorOfType<IMenu>(true) != null;
_isEmbeddedInMenu = parent?.FindLogicalAncestorOfType<IMenu>(true) != null;
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
@ -561,7 +559,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
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<MenuItem>())
foreach (var item in Items!.OfType<MenuItem>())
{
item.TryUpdateCanExecute();
}
@ -677,13 +675,13 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
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
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
private void PopupClosed(object sender, EventArgs e)
private void PopupClosed(object? sender, EventArgs e)
{
SelectedItem = null;
}

8
src/Avalonia.Controls/MenuItemAccessKeyHandler.cs

@ -19,7 +19,7 @@ namespace Avalonia.Controls
/// <summary>
/// The window to which the handler belongs.
/// </summary>
private IInputRoot _owner;
private IInputRoot? _owner;
/// <summary>
/// Gets or sets the window's main menu.
@ -27,7 +27,7 @@ namespace Avalonia.Controls
/// <remarks>
/// This property is ignored as a menu item cannot have a main menu.
/// </remarks>
public IMainMenu MainMenu { get; set; }
public IMainMenu? MainMenu { get; set; }
/// <summary>
/// Sets the owner of the access key handler.
@ -38,7 +38,7 @@ namespace Avalonia.Controls
/// </remarks>
public void SetOwner(IInputRoot owner)
{
Contract.Requires<ArgumentNullException>(owner != null);
_ = owner ?? throw new ArgumentNullException(nameof(owner));
if (_owner != null)
{
@ -84,7 +84,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
protected virtual void OnTextInput(object sender, TextInputEventArgs e)
protected virtual void OnTextInput(object? sender, TextInputEventArgs e)
{
if (!string.IsNullOrWhiteSpace(e.Text))
{

2
src/Avalonia.Controls/Mixins/SelectableMixin.cs

@ -40,7 +40,7 @@ namespace Avalonia.Controls.Mixins
public static void Attach<TControl>(AvaloniaProperty<bool> isSelected)
where TControl : class, IControl
{
Contract.Requires<ArgumentNullException>(isSelected != null);
_ = isSelected ?? throw new ArgumentNullException(nameof(isSelected));
isSelected.Changed.Subscribe(x =>
{

19
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<Visual> _propertyChangedSubscriptions = new List<Visual>();
@ -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;

2
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)
{

16
src/Avalonia.Controls/NativeMenu.cs

@ -11,7 +11,7 @@ namespace Avalonia.Controls
{
private readonly AvaloniaList<NativeMenuItemBase> _items =
new AvaloniaList<NativeMenuItemBase> { ResetBehavior = ResetBehavior.Remove };
private NativeMenuItem _parent;
private NativeMenuItem? _parent;
[Content]
public IList<NativeMenuItemBase> 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.
/// </remarks>
public event EventHandler<EventArgs> NeedsUpdate;
public event EventHandler<EventArgs>? NeedsUpdate;
/// <summary>
/// Raised before the menu is opened.
@ -31,7 +31,7 @@ namespace Avalonia.Controls
/// <remarks>
/// Do not update the menu in this event; use <see cref="NeedsUpdate"/>.
/// </remarks>
public event EventHandler<EventArgs> Opening;
public event EventHandler<EventArgs>? Opening;
/// <summary>
/// Raised after the menu is closed.
@ -39,7 +39,7 @@ namespace Avalonia.Controls
/// <remarks>
/// Do not update the menu in this event; use <see cref="NeedsUpdate"/>.
/// </remarks>
public event EventHandler<EventArgs> Closed;
public event EventHandler<EventArgs>? 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<NativeMenu, NativeMenuItem> ParentProperty =
AvaloniaProperty.RegisterDirect<NativeMenu, NativeMenuItem>("Parent", o => o.Parent, (o, v) => o.Parent = v);
public static readonly DirectProperty<NativeMenu, NativeMenuItem?> ParentProperty =
AvaloniaProperty.RegisterDirect<NativeMenu, NativeMenuItem?>("Parent", o => o.Parent, (o, v) => o.Parent = v);
public NativeMenuItem Parent
public NativeMenuItem? Parent
{
get => _parent;
set => SetAndRaise(ParentProperty, ref _parent, value);

4
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();
}
}
}

48
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<NativeMenuItem, NativeMenu> MenuProperty =
AvaloniaProperty.RegisterDirect<NativeMenuItem, NativeMenu>(nameof(Menu), o => o.Menu, (o, v) => o.Menu = v);
public static readonly DirectProperty<NativeMenuItem, NativeMenu?> MenuProperty =
AvaloniaProperty.RegisterDirect<NativeMenuItem, NativeMenu?>(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<NativeMenuItem, IBitmap> IconProperty =
AvaloniaProperty.RegisterDirect<NativeMenuItem, IBitmap>(nameof(Icon), o => o.Icon, (o, v) => o.Icon = v);
public static readonly DirectProperty<NativeMenuItem, IBitmap?> IconProperty =
AvaloniaProperty.RegisterDirect<NativeMenuItem, IBitmap?>(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<NativeMenuItem, string> HeaderProperty =
AvaloniaProperty.RegisterDirect<NativeMenuItem, string>(nameof(Header), o => o.Header, (o, v) => o.Header = v);
public static readonly DirectProperty<NativeMenuItem, string?> HeaderProperty =
AvaloniaProperty.RegisterDirect<NativeMenuItem, string?>(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<NativeMenuItem, KeyGesture> GestureProperty =
AvaloniaProperty.RegisterDirect<NativeMenuItem, KeyGesture>(nameof(Gesture), o => o.Gesture, (o, v) => o.Gesture = v);
public static readonly DirectProperty<NativeMenuItem, KeyGesture?> GestureProperty =
AvaloniaProperty.RegisterDirect<NativeMenuItem, KeyGesture?>(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<NativeMenuItem, ICommand> CommandProperty =
public static readonly DirectProperty<NativeMenuItem, ICommand?> CommandProperty =
Button.CommandProperty.AddOwner<NativeMenuItem>(
menuItem => menuItem.Command,
(menuItem, command) => menuItem.Command = command,
@ -135,7 +135,7 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="CommandParameter"/> property.
/// </summary>
public static readonly StyledProperty<object> CommandParameterProperty =
public static readonly StyledProperty<object?> CommandParameterProperty =
Button.CommandParameterProperty.AddOwner<MenuItem>();
public static readonly DirectProperty<NativeMenuItem, bool> 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 <see cref="Command"/> property of a
/// <see cref="NativeMenuItem"/>.
/// </summary>
public object CommandParameter
public object? CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
@ -184,7 +184,7 @@ namespace Avalonia.Controls
/// <summary>
/// Occurs when a <see cref="NativeMenuItem"/> is clicked.
/// </summary>
public event EventHandler Click;
public event EventHandler? Click;
[Obsolete("Use Click event.")]
public event EventHandler Clicked

8
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<NativeMenuItem, NativeMenu> ParentProperty =
AvaloniaProperty.RegisterDirect<NativeMenuItem, NativeMenu>("Parent", o => o.Parent, (o, v) => o.Parent = v);
public static readonly DirectProperty<NativeMenuItem, NativeMenu?> ParentProperty =
AvaloniaProperty.RegisterDirect<NativeMenuItem, NativeMenu?>("Parent", o => o.Parent, (o, v) => o.Parent = v);
public NativeMenu Parent
public NativeMenu? Parent
{
get => _parent;
set => SetAndRaise(ParentProperty, ref _parent, value);

8
src/Avalonia.Controls/Notifications/INotification.cs

@ -10,12 +10,12 @@ namespace Avalonia.Controls.Notifications
/// <summary>
/// Gets the Title of the notification.
/// </summary>
string Title { get; }
string? Title { get; }
/// <summary>
/// Gets the notification message.
/// </summary>
string Message { get; }
string? Message { get; }
/// <summary>
/// Gets the <see cref="NotificationType"/> of the notification.
@ -31,11 +31,11 @@ namespace Avalonia.Controls.Notifications
/// <summary>
/// Gets an Action to be run when the notification is clicked.
/// </summary>
Action OnClick { get; }
Action? OnClick { get; }
/// <summary>
/// Gets an Action to be run when the notification is closed.
/// </summary>
Action OnClose { get; }
Action? OnClose { get; }
}
}

16
src/Avalonia.Controls/Notifications/Notification.cs

@ -21,12 +21,12 @@ namespace Avalonia.Controls.Notifications
/// Use <see cref="TimeSpan.Zero"/> for notifications that will remain open.</param>
/// <param name="onClick">An Action to call when the notification is clicked.</param>
/// <param name="onClose">An Action to call when the notification is closed.</param>
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
}
/// <inheritdoc/>
public string Title { get; private set; }
public string? Title { get; private set; }
/// <inheritdoc/>
public string Message { get; private set; }
public string? Message { get; private set; }
/// <inheritdoc/>
public NotificationType Type { get; private set; }
@ -49,9 +49,9 @@ namespace Avalonia.Controls.Notifications
public TimeSpan Expiration { get; private set; }
/// <inheritdoc/>
public Action OnClick { get; private set; }
public Action? OnClick { get; private set; }
/// <inheritdoc/>
public Action OnClose { get; private set; }
public Action? OnClose { get; private set; }
}
}

15
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<Notification>()
#pragma warning restore CS8620
.Subscribe(x =>
{
switch (x.Type)
@ -102,7 +105,7 @@ namespace Avalonia.Controls.Notifications
/// <summary>
/// Raised when the <see cref="NotificationCard"/> has closed.
/// </summary>
public event EventHandler<RoutedEventArgs> NotificationClosed
public event EventHandler<RoutedEventArgs>? 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<ArgumentNullException>(obj != null);
_ = obj ?? throw new ArgumentNullException(nameof(obj));
return (bool)obj.GetValue(CloseOnClickProperty);
}
public static void SetCloseOnClick(Button obj, bool value)
{
Contract.Requires<ArgumentNullException>(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
/// <summary>
/// Called when a button inside the Notification is clicked.
/// </summary>
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<NotificationCard>().FirstOrDefault();
var notification = btn?.GetLogicalAncestors().OfType<NotificationCard>().FirstOrDefault();
notification?.Close();
}

8
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;
/// <summary>
/// Defines the <see cref="Position"/> 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<NotificationCard>().Count(i => !i.IsClosing) > MaxItems)
if (_items?.OfType<NotificationCard>().Count(i => !i.IsClosing) > MaxItems)
{
_items.OfType<NotificationCard>().First(i => !i.IsClosing).Close();
}

94
src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs

@ -46,15 +46,15 @@ namespace Avalonia.Controls
/// Defines the <see cref="CultureInfo"/> property.
/// </summary>
[Obsolete]
public static readonly DirectProperty<NumericUpDown, CultureInfo> CultureInfoProperty =
AvaloniaProperty.RegisterDirect<NumericUpDown, CultureInfo>(nameof(CultureInfo), o => o.CultureInfo,
public static readonly DirectProperty<NumericUpDown, CultureInfo?> CultureInfoProperty =
AvaloniaProperty.RegisterDirect<NumericUpDown, CultureInfo?>(nameof(CultureInfo), o => o.CultureInfo,
(o, v) => o.CultureInfo = v, CultureInfo.CurrentCulture);
/// <summary>
/// Defines the <see cref="NumberFormat"/> property.
/// </summary>
public static readonly DirectProperty<NumericUpDown, NumberFormatInfo> NumberFormatProperty =
AvaloniaProperty.RegisterDirect<NumericUpDown, NumberFormatInfo>(nameof(NumberFormat), o => o.NumberFormat,
public static readonly DirectProperty<NumericUpDown, NumberFormatInfo?> NumberFormatProperty =
AvaloniaProperty.RegisterDirect<NumericUpDown, NumberFormatInfo?>(nameof(NumberFormat), o => o.NumberFormat,
(o, v) => o.NumberFormat = v, NumberFormatInfo.CurrentInfo);
/// <summary>
@ -97,8 +97,8 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="Text"/> property.
/// </summary>
public static readonly DirectProperty<NumericUpDown, string> TextProperty =
AvaloniaProperty.RegisterDirect<NumericUpDown, string>(nameof(Text), o => o.Text, (o, v) => o.Text = v,
public static readonly DirectProperty<NumericUpDown, string?> TextProperty =
AvaloniaProperty.RegisterDirect<NumericUpDown, string?>(nameof(Text), o => o.Text, (o, v) => o.Text = v,
defaultBindingMode: BindingMode.TwoWay, enableDataValidation: true);
/// <summary>
@ -111,8 +111,8 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="Watermark"/> property.
/// </summary>
public static readonly StyledProperty<string> WatermarkProperty =
AvaloniaProperty.Register<NumericUpDown, string>(nameof(Watermark));
public static readonly StyledProperty<string?> WatermarkProperty =
AvaloniaProperty.Register<NumericUpDown, string?>(nameof(Watermark));
/// <summary>
/// Defines the <see cref="HorizontalContentAlignment"/> property.
@ -126,27 +126,27 @@ namespace Avalonia.Controls
public static readonly StyledProperty<VerticalAlignment> VerticalContentAlignmentProperty =
ContentControl.VerticalContentAlignmentProperty.AddOwner<NumericUpDown>();
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;
/// <summary>
/// Gets the Spinner template part.
/// </summary>
private Spinner Spinner { get; set; }
private Spinner? Spinner { get; set; }
/// <summary>
/// Gets the TextBox template part.
/// </summary>
private TextBox TextBox { get; set; }
private TextBox? TextBox { get; set; }
/// <summary>
/// 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.
/// </summary>
[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
/// <summary>
/// Gets or sets the current NumberFormatInfo
/// </summary>
public NumberFormatInfo NumberFormat
public NumberFormatInfo? NumberFormat
{
get { return _numberFormat; }
set { SetAndRaise(NumberFormatProperty, ref _numberFormat, value); }
@ -265,7 +265,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the formatted string representation of the value.
/// </summary>
public string Text
public string? Text
{
get { return _text; }
set { SetAndRaise(TextProperty, ref _text, value); }
@ -287,7 +287,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or sets the object to use as a watermark if the <see cref="Value"/> is null.
/// </summary>
public string Watermark
public string? Watermark
{
get { return GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
@ -414,7 +414,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="oldValue">The old value.</param>
/// <param name="newValue">The new value.</param>
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
/// </summary>
/// <param name="oldValue">The old value.</param>
/// <param name="newValue">The new value.</param>
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
/// </summary>
/// <param name="oldValue">The old value.</param>
/// <param name="newValue">The new value.</param>
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
/// </summary>
/// <param name="oldValue">The old value.</param>
/// <param name="newValue">The new value.</param>
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<SpinEventArgs> Spinned;
public event EventHandler<SpinEventArgs>? 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
/// <summary>
/// Raised when the <see cref="Value"/> changes.
/// </summary>
public event EventHandler<NumericUpDownValueChangedEventArgs> ValueChanged
public event EventHandler<NumericUpDownValueChangedEventArgs>? ValueChanged
{
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
@ -949,7 +949,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="updateValueFromText">If value should be updated from text.</param>
/// <param name="text">The text.</param>
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
/// <param name="updateValueFromText">If value should be updated from text.</param>
/// <param name="text">The text.</param>
/// <param name="forceTextUpdate">Force text update.</param>
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
/// </summary>
/// <param name="text">Text to parse.</param>
/// <param name="cultureInfo">The culture info.</param>
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);

24
src/Avalonia.Controls/Panel.cs

@ -21,7 +21,7 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="Background"/> property.
/// </summary>
public static readonly StyledProperty<IBrush> BackgroundProperty =
public static readonly StyledProperty<IBrush?> BackgroundProperty =
Border.BackgroundProperty.AddOwner<Panel>();
/// <summary>
@ -32,7 +32,7 @@ namespace Avalonia.Controls
AffectsRender<Panel>(BackgroundProperty);
}
private EventHandler<ChildIndexChangedEventArgs> _childIndexChanged;
private EventHandler<ChildIndexChangedEventArgs>? _childIndexChanged;
/// <summary>
/// Initializes a new instance of the <see cref="Panel"/> class.
@ -51,13 +51,13 @@ namespace Avalonia.Controls
/// <summary>
/// Gets or Sets Panel background brush.
/// </summary>
public IBrush Background
public IBrush? Background
{
get { return GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
}
event EventHandler<ChildIndexChangedEventArgs> IChildIndexProvider.ChildIndexChanged
event EventHandler<ChildIndexChangedEventArgs>? IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
@ -110,34 +110,34 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
protected virtual void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
protected virtual void ChildrenChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
List<Control> controls;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
controls = e.NewItems.OfType<Control>().ToList();
controls = e.NewItems!.OfType<Control>().ToList();
LogicalChildren.InsertRange(e.NewStartingIndex, controls);
VisualChildren.InsertRange(e.NewStartingIndex, e.NewItems.OfType<Visual>());
VisualChildren.InsertRange(e.NewStartingIndex, e.NewItems!.OfType<Visual>());
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<Control>().ToList();
controls = e.OldItems!.OfType<Control>().ToList();
LogicalChildren.RemoveAll(controls);
VisualChildren.RemoveAll(e.OldItems.OfType<Visual>());
VisualChildren.RemoveAll(e.OldItems!.OfType<Visual>());
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;
}

37
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
{
/// <summary>
@ -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();
}

4
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; }

6
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; }
}
}

2
src/Avalonia.Controls/Platform/ISystemDialogImpl.cs

@ -1,7 +1,5 @@
using System.Threading.Tasks;
#nullable enable
namespace Avalonia.Controls.Platform
{
/// <summary>

18
src/Avalonia.Controls/Platform/ITopLevelImpl.cs

@ -82,27 +82,27 @@ namespace Avalonia.Platform
/// <summary>
/// Gets or sets a method called when the toplevel receives input.
/// </summary>
Action<RawInputEventArgs> Input { get; set; }
Action<RawInputEventArgs>? Input { get; set; }
/// <summary>
/// Gets or sets a method called when the toplevel requires painting.
/// </summary>
Action<Rect> Paint { get; set; }
Action<Rect>? Paint { get; set; }
/// <summary>
/// Gets or sets a method called when the toplevel is resized.
/// </summary>
Action<Size, PlatformResizeReason> Resized { get; set; }
Action<Size, PlatformResizeReason>? Resized { get; set; }
/// <summary>
/// Gets or sets a method called when the toplevel's scaling changes.
/// </summary>
Action<double> ScalingChanged { get; set; }
Action<double>? ScalingChanged { get; set; }
/// <summary>
/// Gets or sets a method called when the toplevel's TransparencyLevel changes.
/// </summary>
Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; }
Action<WindowTransparencyLevel>? TransparencyLevelChanged { get; set; }
/// <summary>
/// Creates a new renderer for the toplevel.
@ -138,17 +138,17 @@ namespace Avalonia.Platform
/// Sets the cursor associated with the toplevel.
/// </summary>
/// <param name="cursor">The cursor. Use null for default cursor</param>
void SetCursor(ICursorImpl cursor);
void SetCursor(ICursorImpl? cursor);
/// <summary>
/// Gets or sets a method called when the underlying implementation is destroyed.
/// </summary>
Action Closed { get; set; }
Action? Closed { get; set; }
/// <summary>
/// Gets or sets a method called when the input focus is lost.
/// </summary>
Action LostFocus { get; set; }
Action? LostFocus { get; set; }
/// <summary>
/// Gets a mouse device associated with toplevel
@ -156,7 +156,7 @@ namespace Avalonia.Platform
[CanBeNull]
IMouseDevice MouseDevice { get; }
IPopupImpl CreatePopup();
IPopupImpl? CreatePopup();
/// <summary>
/// Sets the <see cref="WindowTransparencyLevel"/> hint of the TopLevel.

2
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; }
}
}

4
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; }
}
}

2
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

6
src/Avalonia.Controls/Platform/IWindowBaseImpl.cs

@ -29,7 +29,7 @@ namespace Avalonia.Platform
/// <summary>
/// Gets or sets a method called when the window's position changes.
/// </summary>
Action<PixelPoint> PositionChanged { get; set; }
Action<PixelPoint>? PositionChanged { get; set; }
/// <summary>
/// Activates the window.
@ -39,12 +39,12 @@ namespace Avalonia.Platform
/// <summary>
/// Gets or sets a method called when the window is deactivated (loses focus).
/// </summary>
Action Deactivated { get; set; }
Action? Deactivated { get; set; }
/// <summary>
/// Gets or sets a method called when the window is activated (receives focus).
/// </summary>
Action Activated { get; set; }
Action? Activated { get; set; }
/// <summary>
/// Gets the platform window handle.

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save