Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

Commit d74ab1d

Browse files
TheCodeTravelerpictosmaxkoshevoi
authored
Enable Nullable (#1009)
* Enable Nullable on Unit Tests (#1008) * Enable Nullability on Xamarin.CommunityToolkit.Markup (#1013) * Enable Nullable on Unit Tests * Enable Nullable on Xamarin.CommunityToolkit.Markup * Enable Nullability on Xamarin.CommunityToolkit.Sample (#1014) * Enable Nullable on Unit Tests * Enable Nullable on Xamarin.CommunityToolkit.Markup * Enable Nullable on Xamarin.CommunityToolkit.Sample * Enable Nullability for Android, GTK, iOS, Tizen, UWP & WPF Sample Projects (#1015) * Enable Nullable on Unit Tests * Enable Nullable on Xamarin.CommunityToolkit.Markup * Enable Nullable on Xamarin.CommunityToolkit.Sample * Enable Nullable on Android, GTK, iOS and Tizen Samples * Enable Nullable for UWP & WPF Sample Projects * Enable Nullability on Xamarin.CommunityToolkit (#1016) * Enable Nullable on Unit Tests * Enable Nullable on Xamarin.CommunityToolkit.Markup * Enable Nullable on Xamarin.CommunityToolkit.Sample * Enable Nullable on Android, GTK, iOS and Tizen Samples * Enable Nullable for UWP & WPF Sample Projects * Add Nullability * Enable Nullable on XamarinCommunityToolkit (#1023) * Enable Nullable on Unit Tests * Enable Nullable on Xamarin.CommunityToolkit.Markup * Enable Nullable on Xamarin.CommunityToolkit.Sample * Enable Nullable on Android, GTK, iOS and Tizen Samples * Enable Nullable for UWP & WPF Sample Projects * Add Nullability * Resolve Possible Null References * Removed Possible Null References * Update AppResources.Designer.cs * Handle Nullability * Updated Nullabiltiy * Update Converters & Unit Tests * Resolve MediaSource Unit Tests * Fix Unit Tests (#1036) * Enable Nullable on Unit Tests * Enable Nullable on Xamarin.CommunityToolkit.Markup * Enable Nullable on Xamarin.CommunityToolkit.Sample * Enable Nullable on Android, GTK, iOS and Tizen Samples * Enable Nullable for UWP & WPF Sample Projects * Add Nullability * Resolve Possible Null References * Removed Possible Null References * Update AppResources.Designer.cs * Handle Nullability * Updated Nullabiltiy * Update Converters & Unit Tests * Resolve MediaSource Unit Tests * Fix VariableMultiValueConverter * Fixed ImpliedOrderGridBehavior * Update NumericValidationBehavior.shared.cs * Resolve Nullable in SideMenuView * Move <Nullable>enable</Nullable> to Directory.Build.props * Update Xamarin.CommunityToolkit.Sample.csproj * Revert Designer.cs * Update Xamarin.CommunityToolkit.Sample.csproj * Update ItemSelectedEventArgsConverter_Tests.cs * Update SearchViewModel.cs * Update ItemTappedEventArgsConverter_Tests.cs * Update Xamarin.CommunityToolkit.UnitTests.csproj * Add Nullability * Resolve Compiler Warnings * Ignore Closing square brackets should be spaced correctly With Nullable enabled, `byte[]?` is now valid, however SA1011 was still generating a warning * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Behaviors/ImpliedOrderGridBehavior.shared.cs Co-authored-by: Pedro Jesus <[email protected]> * Update CameraFragment.android.cs * Update CameraFragment.android.cs * Update ImpliedOrderGridBehavior.shared.cs * Update MaskedBehavior.shared.cs * Update PopupRenderer.uwp.cs * Use .NET 5.0 * Update azure-pipelines.yml * Update azure-pipelines.yml * Update azure-pipelines.yml * Add UWP to Release Build * Update Nullability * Update Nullablity * Update TabView.shared.cs * Update Nullability * Revert "Update Nullability" This reverts commit e391b9c. * Resolved Nullable * Update azure-pipelines.yml * Revert UWP Build Properties * Update azure-pipelines.yml * Update azure-pipelines.yml * Revert "Update azure-pipelines.yml" This reverts commit 0842280. * Update azure-pipelines.yml * Revert "Revert UWP Build Properties" This reverts commit 77226bf. * Update azure-pipelines.yml * Update azure-pipelines.yml * Update azure-pipelines.yml * Update azure-pipelines.yml * Update azure-pipelines.yml * Update azure-pipelines.yml * Revert "Update azure-pipelines.yml" This reverts commit 4eb36f4. * Update azure-pipelines.yml * Revert "Update azure-pipelines.yml" This reverts commit e41a477. * Fix ValidationBehavior.ForceValidate and ValidationBehavior.DefaultForceValidateCommand * Update SelectAllTextEffect.ios.cs * Remove Nullabilty from LocalizedString.generator * Update MediaElementRenderer.ios.cs * Update PopupRenderer.uwp.cs * Update PopupRenderer.ios.cs * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/Helpers/iOS/SnackbarViews/BaseSnackBarView.ios.cs Co-authored-by: Maksym Koshovyi <[email protected]> * Update TranslateExtension.shared.cs * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.android.cs Co-authored-by: Maksym Koshovyi <[email protected]> * Update Logic * Fix Failing ICommand Tests * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.tizen.cs Co-authored-by: Maksym Koshovyi <[email protected]> * Throw Faulted Task * Use Cast instead of Pattern Matching * Update RangeSlider.shared.cs * Fix missing semi-colons * Throw InvalidOperationException in LocalizationResourceManager * Make TranslateExtension.StringFormat nullable * Update UserStoppedTypingBehavior.shared.cs * Update SearchPage.logic.cs * Update TouchEffectCollectionViewPage.xaml.cs * Update AppResources.Designer.cs * Update AppResources.Designer.cs * Update EnumToBoolConverterViewModel.cs * Update EnumToBoolConverter_Tests.cs * Update IntToBoolConverter_Tests.cs * Update InvertedBoolConverter_Tests.cs * Update IsNotNullOrEmptyConverter_Tests.cs * Update MultiConverter_Tests.cs * Update NotEqualConverter_Tests.cs * Update TextCaseConverter_Tests.cs * Update MockPlatformServices.cs * Update MockPlatformServices.cs * Update Namespace_Tests.cs * Update ObservableRangeCollection_Tests.cs * Update ObservableRangeCollection_Tests.cs * Use `async Task` instead of `async void` * Update MultiValidationBehavior.shared.cs * Update EnumToBoolConverter.shared.cs * Update EnumToBoolConverter.shared.cs * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/NotEqualConverter.shared.cs Co-authored-by: Pedro Jesus <[email protected]> * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/StateToBooleanConverter.shared.cs Co-authored-by: Pedro Jesus <[email protected]> * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/TextCaseConverter.shared.cs Co-authored-by: Pedro Jesus <[email protected]> * Update IconTintColorEffectRouter.android.cs * Update src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/SelectAllText/SelectAllTextEffect.android.cs Co-authored-by: Pedro Jesus <[email protected]> * Update SelectAllTextEffect.android.cs * Update SelectAllTextEffect.ios.cs * Update PlatformTouchEffect.ios.cs * Update PlatformTouchEffect.uwp.cs * Update PlatformTouchEffect.uwp.cs * Update PlatformTouchEffect.macos.cs * Update PlatformTouchEffect.uwp.cs * Update PlatformTouchEffect.uwp.cs * Ensure nullable results from BindableProperties are still resolved * Update ImageResourceExtension.shared.cs * Update BaseCommand.android.cs * Use protected private constructor for BaseCommand * Update BadgeView.shared.cs * Update CameraFragment.android.cs * Fix Android Media Bugs * Update async/await * Update CameraView_Tests.cs * Update CameraView * Update UriTypeConverter.shared.cs * Update PopupRenderer.uwp.cs * Update PopoverArrowDirection.shared.cs * Update PopoverArrowDirection.shared.cs * Update TabView.shared.cs * Improve AsyncCommand Tests * Ensure Context is non nullable * Remove Missing Translations * Fix async/await in TouchEffect.shared.cs * Make Easing Nullable * Update Samples * Fix Null Exception * Resolve NullReferenceExceptions * Make IBadgeAnimation Nullable * Add ShutterCommandValueCreator null check * Add Timeout to prevent race conditions from stalling tests * Unsubscribe Event Handlers for AsyncCommand Tests * Update azure-pipelines.yml * For WPF, Use Cross-Platform Implementation for `BaseCommand.IsMainThread` and `BaseCommand.BeginInvokeOnMainThread` (#965) * Add Non-WPF Support to .NET Core 3.1 * Update comments * Merge .NET Standard and WPF Functionality * Fix Null Reference * Update ICommand_AsyncValueCommand_Tests.cs * Add volatile keyword * Update AsyncValueCommand_Tests.cs * Remove Timeouts * Fix Event Unsubscription * Add .ConfigureAwait(false); * Run dotnet test serially * Use SemaphoreSlim to prevent Race Conditions Co-authored-by: Pedro Jesus <[email protected]> Co-authored-by: Maksym Koshovyi <[email protected]>
1 parent 5acf5fd commit d74ab1d

File tree

318 files changed

+3993
-3110
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

318 files changed

+3993
-3110
lines changed

.editorconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,9 @@ csharp_new_line_before_catch = true
107107
csharp_new_line_before_finally = true
108108
csharp_new_line_before_members_in_object_initializers = true
109109
csharp_new_line_before_members_in_anonymous_types = true
110+
111+
# SA1011: Closing square brackets should be spaced correctly
112+
dotnet_diagnostic.SA1011.severity = none
113+
114+
# CS4014: Because this call is not awaited, execution of the current method continues before the call is completed
115+
dotnet_diagnostic.CS4014.severity = error

Directory.Build.props

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
33

44
<PropertyGroup>
5-
<LangVersion>8.0</LangVersion>
5+
<LangVersion>9.0</LangVersion>
6+
<Nullable>enable</Nullable>
7+
<WarningsAsErrors>nullable</WarningsAsErrors>
68
</PropertyGroup>
79

810

Xamarin.CommunityToolkit.ruleset

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
<Rule Id="SA1008" Action="Warning" />
1616
<Rule Id="SA1009" Action="Warning" />
1717
<Rule Id="SA1010" Action="Warning" />
18-
<Rule Id="SA1011" Action="Warning" />
1918
<Rule Id="SA1012" Action="Warning" />
2019
<Rule Id="SA1013" Action="Warning" />
2120
<Rule Id="SA1014" Action="Warning" />

azure-pipelines.yml

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ variables:
77
#MONO_VERSION: 6_4_0
88
#XCODE_VERSION: 11.4
99
NETCORE_VERSION: '5.0.x'
10-
NETCORE_TEST_VERSION: '5.0.x'
10+
NETCORE_TEST_VERSION_3_1: '3.1.x'
11+
NETCORE_TEST_VERSION_2_1: '2.1.x'
1112
RunPoliCheck: 'false'
1213
PathToCsproj: 'src/CommunityToolkit/Xamarin.CommunityToolkit/Xamarin.CommunityToolkit.csproj'
1314
PathToMarkupCsproj: 'src/Markup/Xamarin.CommunityToolkit.Markup/Xamarin.CommunityToolkit.Markup.csproj'
15+
PathToUnitTestCsproj: 'src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Xamarin.CommunityToolkit.UnitTests.csproj'
1416
PathToSln: 'samples/XCT.Sample.sln'
1517

1618
resources:
@@ -68,6 +70,21 @@ jobs:
6870
pool:
6971
vmImage: windows-2019
7072
steps:
73+
- task: UseDotNet@2
74+
displayName: 'Install .NET SDK'
75+
inputs:
76+
version: $(NETCORE_VERSION)
77+
includePreviewVersions: false
78+
- task: UseDotNet@2
79+
displayName: 'Install .NET 3.1 Test SDK'
80+
inputs:
81+
version: $(NETCORE_TEST_VERSION_3_1)
82+
includePreviewVersions: false
83+
- task: UseDotNet@2
84+
displayName: 'Install .NET 2.1 Test SDK'
85+
inputs:
86+
version: $(NETCORE_TEST_VERSION_2_1)
87+
includePreviewVersions: false
7188
# if this is a tagged build, then update the version number
7289
- powershell: |
7390
$buildSourceBranch = "$(Build.SourceBranch)"
@@ -112,12 +129,10 @@ jobs:
112129
# command: 'custom'
113130
# custom: 'nuget'
114131
# arguments: 'push --source https://nuget.pkg.github.com/xamarin/index.json --api-key $(GitHub.NuGet.Token) "$(Build.ArtifactStagingDirectory)\nuget\*.nupkg"'
115-
- task: DotNetCoreCLI@2
116-
displayName: Run Tests
132+
- task: CmdLine@2
133+
displayName: 'Run Unit Tests'
117134
inputs:
118-
command: test
119-
projects: '**/*.UnitTests.csproj'
120-
arguments: '--configuration Release --collect "Code coverage"'
135+
script: dotnet test $(PathToUnitTestCsproj) -c Release --collect "Code coverage" -p:BuildInParallel=false
121136
# publish the packages
122137
- task: PublishBuildArtifacts@1
123138
displayName: 'Publish Unsigned NuGets'
@@ -161,27 +176,28 @@ jobs:
161176
# displayName: Switch to the latest Xcode
162177
# restore, build and pack the packages
163178
- task: UseDotNet@2
164-
displayName: 'Use .Net Core sdk'
179+
displayName: 'Install .NET SDK'
165180
inputs:
166181
version: $(NETCORE_VERSION)
167182
includePreviewVersions: false
168183
- task: UseDotNet@2
169-
displayName: 'Use .Net Core sdk'
184+
displayName: 'Install .NET 3.1 Test SDK'
170185
inputs:
171-
version: $(NETCORE_TEST_VERSION)
186+
version: $(NETCORE_TEST_VERSION_3_1)
172187
includePreviewVersions: false
173-
- task: MSBuild@1
174-
displayName: Build Solution
188+
- task: UseDotNet@2
189+
displayName: 'Install .NET 2.1 Test SDK'
175190
inputs:
176-
solution: $(PathToCsproj)
177-
configuration: Release
178-
msbuildArguments: '/restore /t:Build /p:ContinuousIntegrationBuild=true /p:Deterministic=false'
179-
- task: MSBuild@1
180-
displayName: Pack NuGets
191+
version: $(NETCORE_TEST_VERSION_2_1)
192+
includePreviewVersions: false
193+
- task: CmdLine@2
194+
displayName: 'Build Solution'
181195
inputs:
182-
solution: $(PathToCsproj)
183-
configuration: Release
184-
msbuildArguments: '/t:Pack /p:PackageVersion=$(NugetPackageVersion) /p:PackageOutputPath="$(Build.ArtifactStagingDirectory)/nuget"'
196+
script: 'mono /Applications/Visual\ studio.app/Contents/Resources/lib/monodevelop/bin/MSBuild/Current/bin/MSBuild.dll $(PathToCsproj) /p:Configuration=Release /restore /t:Build /p:ContinuousIntegrationBuild=true /p:Deterministic=false'
197+
- task: CmdLine@2
198+
displayName: 'Pack NuGets'
199+
inputs:
200+
script: 'mono /Applications/Visual\ studio.app/Contents/Resources/lib/monodevelop/bin/MSBuild/Current/bin/MSBuild.dll $(PathToCsproj) /p:Configuration=Release /t:Pack /p:PackageVersion=$(NugetPackageVersion) /p:PackageOutputPath="$(Build.ArtifactStagingDirectory)/nuget"'
185201

186202
- ${{ if eq(variables['System.TeamProject'], 'devdiv') }}:
187203
- template: sign-artifacts/jobs/v2.yml@internal-templates

samples/XCT.Sample.Android/SplashActivity.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Xamarin.CommunityToolkit.Sample.Droid
99
[Activity(Label = "XamarinCommunityToolkitSample", Icon = "@mipmap/icon", Theme = "@style/SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
1010
public class SplashActivity : AppCompatActivity
1111
{
12-
protected override void OnCreate(Bundle savedInstanceState)
12+
protected override void OnCreate(Bundle? savedInstanceState)
1313
{
1414
base.OnCreate(savedInstanceState);
1515
var intent = new Intent(this, typeof(MainActivity));

samples/XCT.Sample.UWP/App.xaml.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ protected override void OnLaunched(LaunchActivatedEventArgs e)
8585
/// </summary>
8686
/// <param name="sender">The Frame which failed navigation</param>
8787
/// <param name="e">Details about the navigation failure</param>
88-
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
88+
void OnNavigationFailed(object? sender, NavigationFailedEventArgs e)
8989
{
9090
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
9191
}
@@ -97,7 +97,7 @@ void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
9797
/// </summary>
9898
/// <param name="sender">The source of the suspend request.</param>
9999
/// <param name="e">Details about the suspend request.</param>
100-
void OnSuspending(object sender, SuspendingEventArgs e)
100+
void OnSuspending(object? sender, SuspendingEventArgs e)
101101
{
102102
var deferral = e.SuspendingOperation.GetDeferral();
103103

samples/XCT.Sample.iOS/Renderers/NoLineNavigationRenderer.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ public override void ViewWillAppear(bool animated)
2525
// Newest iOS version fix - trycatch isn't optimal
2626
try
2727
{
28-
NavigationBar.ScrollEdgeAppearance.ShadowImage = new UIKit.UIImage();
29-
NavigationBar.ScrollEdgeAppearance.ShadowColor = null;
28+
if (NavigationBar.ScrollEdgeAppearance != null)
29+
{
30+
NavigationBar.ScrollEdgeAppearance.ShadowImage = new UIKit.UIImage();
31+
NavigationBar.ScrollEdgeAppearance.ShadowColor = null;
32+
}
3033
}
3134
catch (Exception)
3235
{

samples/XCT.Sample.sln

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.CommunityToolkit.Sa
1818
EndProject
1919
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F695F5E8-420F-475F-A4CF-F5BB3FA6E818}"
2020
ProjectSection(SolutionItems) = preProject
21-
.editorconfig = .editorconfig
22-
Directory.Build.props = Directory.Build.props
23-
Xamarin.CommunityToolkit.ruleset = Xamarin.CommunityToolkit.ruleset
21+
..\.editorconfig = ..\.editorconfig
22+
..\Directory.Build.props = ..\Directory.Build.props
23+
..\Xamarin.CommunityToolkit.ruleset = ..\Xamarin.CommunityToolkit.ruleset
2424
EndProjectSection
2525
EndProject
2626
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.CommunityToolkit.Sample.WPF", "XCT.Sample.WPF\Xamarin.CommunityToolkit.Sample.WPF.csproj", "{C4D6CD2D-8DF4-4D46-936C-1AB31C87B5EA}"
@@ -62,6 +62,7 @@ Global
6262
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Debug|x86.Build.0 = Debug|Any CPU
6363
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
6464
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|Any CPU.Build.0 = Release|Any CPU
65+
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|Any CPU.Deploy.0 = Release|Any CPU
6566
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|ARM.ActiveCfg = Release|Any CPU
6667
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|ARM.Build.0 = Release|Any CPU
6768
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|iPhone.ActiveCfg = Release|Any CPU
@@ -191,6 +192,8 @@ Global
191192
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Debug|x86.Build.0 = Debug|x86
192193
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Debug|x86.Deploy.0 = Debug|x86
193194
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|Any CPU.ActiveCfg = Release|x86
195+
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|Any CPU.Build.0 = Release|x86
196+
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|Any CPU.Deploy.0 = Release|x86
194197
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|ARM.ActiveCfg = Release|ARM
195198
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|ARM.Build.0 = Release|ARM
196199
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|ARM.Deploy.0 = Release|ARM

samples/XCT.Sample/App.xaml.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Xamarin.CommunityToolkit.Helpers;
1+
using System.Globalization;
2+
using Xamarin.CommunityToolkit.Helpers;
23
using Xamarin.CommunityToolkit.Sample.Pages;
34
using Xamarin.CommunityToolkit.Sample.Resx;
45
using Xamarin.Forms.PlatformConfiguration;
@@ -14,6 +15,7 @@ public App()
1415

1516
LocalizationResourceManager.Current.PropertyChanged += (sender, e) => AppResources.Culture = LocalizationResourceManager.Current.CurrentCulture;
1617
LocalizationResourceManager.Current.Init(AppResources.ResourceManager);
18+
LocalizationResourceManager.Current.CurrentCulture = new CultureInfo("en");
1719

1820
InitializeComponent();
1921
MainPage = new BaseNavigationPage(new WelcomePage());

samples/XCT.Sample/Helpers/RelayCommand.cs

Lines changed: 38 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,21 @@ namespace Xamarin.CommunityToolkit.Sample
77
{
88
public class RelayCommand : ICommand
99
{
10-
readonly Action execute;
11-
readonly Func<Task> asyncExecute;
10+
readonly Action? execute;
11+
readonly Func<Task>? asyncExecute;
12+
readonly Func<bool>? canExecute;
1213

13-
Func<bool> canExecute;
1414
int executingCount;
1515

16-
public RelayCommand(Action execute, Func<bool> canExecute = null)
16+
public RelayCommand(Action execute, Func<bool>? canExecute = null)
1717
{
18-
if (execute == null)
19-
throw new ArgumentNullException(nameof(execute));
20-
this.execute = execute;
18+
this.execute = execute ?? throw new ArgumentNullException(nameof(execute));
2119
this.canExecute = canExecute;
2220
}
2321

24-
protected RelayCommand(Func<Task> execute, Func<bool> canExecute = null) // This ctor is protected here and public in a derived class, to allow simple initialization like new RelayCommand(MyMethod) without errors due to ambiguity
22+
protected RelayCommand(Func<Task> execute, Func<bool>? canExecute = null) // This ctor is protected here and public in a derived class, to allow simple initialization like new RelayCommand(MyMethod) without errors due to ambiguity
2523
{
26-
if (execute == null)
27-
throw new ArgumentNullException(nameof(execute));
28-
asyncExecute = execute;
24+
asyncExecute = execute ?? throw new ArgumentNullException(nameof(execute));
2925
this.canExecute = canExecute;
3026
}
3127

@@ -34,7 +30,7 @@ public RelayCommand(Action execute, Func<bool> canExecute = null)
3430
/// </summary>
3531
/// <param name="parameter">Ignored; this is the paremeterless command class</param>
3632
/// <returns></returns>
37-
public bool CanExecute(object parameter = null)
33+
public bool CanExecute(object? parameter = null)
3834
{
3935
try
4036
{
@@ -47,15 +43,12 @@ public bool CanExecute(object parameter = null)
4743
}
4844
}
4945

50-
public event EventHandler CanExecuteChanged;
46+
public event EventHandler? CanExecuteChanged;
5147

52-
public void RaiseCanExecuteChanged()
53-
{
54-
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
55-
}
48+
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
5649

5750
// Asynchronous command handling based on http://stackoverflow.com/a/31595509/6043538
58-
public async void Execute(object parameter = null)
51+
public async void Execute(object? parameter = null)
5952
{
6053
var couldExecuteBeforeExecute = CanExecute();
6154
if (!couldExecuteBeforeExecute)
@@ -70,8 +63,10 @@ public async void Execute(object parameter = null)
7063
{
7164
if (execute != null)
7265
execute();
73-
else
66+
else if (asyncExecute != null)
7467
await asyncExecute();
68+
else
69+
throw new Exception("Execute is null");
7570
}
7671
catch (Exception ex)
7772
{
@@ -89,31 +84,30 @@ public async void Execute(object parameter = null)
8984

9085
public class RelayCommandAsync : RelayCommand
9186
{
92-
public RelayCommandAsync(Func<Task> execute, Func<bool> canExecute = null)
93-
: base(execute, canExecute) { } // This ctor is public here and protected in the base class, to allow simple initialization like new RelayCommandAsync(MyMethod) without errors due to ambiguity
87+
public RelayCommandAsync(Func<Task> execute, Func<bool>? canExecute = null)
88+
: base(execute, canExecute)
89+
{
90+
// This ctor is public here and protected in the base class, to allow simple initialization like new RelayCommandAsync(MyMethod) without errors due to ambiguity
91+
}
9492
}
9593

9694
public class RelayCommand<TParameter> : ICommand
9795
{
98-
readonly Action<TParameter> execute;
99-
readonly Func<TParameter, Task> asyncExecute;
96+
readonly Action<TParameter>? execute;
97+
readonly Func<TParameter, Task>? asyncExecute;
98+
readonly Func<TParameter?, bool>? canExecute;
10099

101-
Func<TParameter, bool> canExecute;
102100
int executingCount;
103101

104-
public RelayCommand(Action<TParameter> execute, Func<TParameter, bool> canExecute = null)
102+
public RelayCommand(Action<TParameter> execute, Func<TParameter?, bool>? canExecute = null)
105103
{
106-
if (execute == null)
107-
throw new ArgumentNullException(nameof(execute));
108-
this.execute = execute;
104+
this.execute = execute ?? throw new ArgumentNullException(nameof(execute));
109105
this.canExecute = canExecute;
110106
}
111107

112-
protected RelayCommand(Func<TParameter, Task> execute, Func<TParameter, bool> canExecute = null) // This ctor is protected here and public in a derived class, to allow simple initialization like new RelayCommand(MyMethod) without errors due to ambiguity
108+
protected RelayCommand(Func<TParameter, Task> execute, Func<TParameter?, bool>? canExecute = null) // This ctor is protected here and public in a derived class, to allow simple initialization like new RelayCommand(MyMethod) without errors due to ambiguity
113109
{
114-
if (execute == null)
115-
throw new ArgumentNullException(nameof(execute));
116-
asyncExecute = execute;
110+
asyncExecute = execute ?? throw new ArgumentNullException(nameof(execute));
117111
this.canExecute = canExecute;
118112
}
119113

@@ -122,11 +116,11 @@ public RelayCommand(Action<TParameter> execute, Func<TParameter, bool> canExecut
122116
/// </summary>
123117
/// <param name="parameter"></param>
124118
/// <returns></returns>
125-
public bool CanExecute(object parameter = null)
119+
public bool CanExecute(object? parameter = null)
126120
{
127121
try
128122
{
129-
return canExecute != null ? canExecute((TParameter)parameter) : executingCount == 0;
123+
return canExecute != null ? canExecute((TParameter?)parameter) : executingCount == 0;
130124
}
131125
catch (Exception ex)
132126
{
@@ -135,12 +129,9 @@ public bool CanExecute(object parameter = null)
135129
}
136130
}
137131

138-
public event EventHandler CanExecuteChanged;
132+
public event EventHandler? CanExecuteChanged;
139133

140-
public void RaiseCanExecuteChanged()
141-
{
142-
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
143-
}
134+
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
144135

145136
// Asynchronous command handling based on http://stackoverflow.com/a/31595509/6043538
146137
public async void Execute(object parameterAsObject)
@@ -159,13 +150,11 @@ public async void Execute(object parameterAsObject)
159150
var parameter = (TParameter)parameterAsObject;
160151

161152
if (execute != null)
162-
{
163153
execute(parameter);
164-
}
165-
else
166-
{
154+
else if (asyncExecute != null)
167155
await asyncExecute(parameter);
168-
}
156+
else
157+
throw new Exception("Execute is null");
169158
}
170159
catch (Exception ex)
171160
{
@@ -183,7 +172,10 @@ public async void Execute(object parameterAsObject)
183172

184173
public class RelayCommandAsync<TParameter> : RelayCommand<TParameter>
185174
{
186-
public RelayCommandAsync(Func<TParameter, Task> execute, Func<TParameter, bool> canExecute = null)
187-
: base(execute, canExecute) { } // This ctor is public here and protected in the base class, to allow simple initialization like new RelayCommandAsync(MyMethod) without errors due to ambiguity
175+
public RelayCommandAsync(Func<TParameter, Task> execute, Func<TParameter?, bool>? canExecute = null)
176+
: base(execute, canExecute)
177+
{
178+
// This ctor is public here and protected in the base class, to allow simple initialization like new RelayCommandAsync(MyMethod) without errors due to ambiguity
179+
}
188180
}
189181
}

0 commit comments

Comments
 (0)