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

Commit

Permalink
Enable Nullable (#1009)
Browse files Browse the repository at this point in the history
* 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 <pedrojesus.cefet@gmail.com>

* 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 <maximkoshevoi61@gmail.com>

* Update TranslateExtension.shared.cs

* Update src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.android.cs

Co-authored-by: Maksym Koshovyi <maximkoshevoi61@gmail.com>

* Update Logic

* Fix Failing ICommand Tests

* Update src/CommunityToolkit/Xamarin.CommunityToolkit/Views/Snackbar/SnackBar.tizen.cs

Co-authored-by: Maksym Koshovyi <maximkoshevoi61@gmail.com>

* 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 <pedrojesus.cefet@gmail.com>

* Update src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/StateToBooleanConverter.shared.cs

Co-authored-by: Pedro Jesus <pedrojesus.cefet@gmail.com>

* Update src/CommunityToolkit/Xamarin.CommunityToolkit/Converters/TextCaseConverter.shared.cs

Co-authored-by: Pedro Jesus <pedrojesus.cefet@gmail.com>

* Update IconTintColorEffectRouter.android.cs

* Update src/CommunityToolkit/Xamarin.CommunityToolkit/Effects/SelectAllText/SelectAllTextEffect.android.cs

Co-authored-by: Pedro Jesus <pedrojesus.cefet@gmail.com>

* 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 <pedrojesus.cefet@gmail.com>
Co-authored-by: Maksym Koshovyi <maximkoshevoi61@gmail.com>
  • Loading branch information
3 people committed Mar 9, 2021
1 parent 5acf5fd commit d74ab1d
Show file tree
Hide file tree
Showing 318 changed files with 3,993 additions and 3,110 deletions.
6 changes: 6 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,9 @@ csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true

# SA1011: Closing square brackets should be spaced correctly
dotnet_diagnostic.SA1011.severity = none

# CS4014: Because this call is not awaited, execution of the current method continues before the call is completed
dotnet_diagnostic.CS4014.severity = error
4 changes: 3 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>
<LangVersion>8.0</LangVersion>
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>
<WarningsAsErrors>nullable</WarningsAsErrors>
</PropertyGroup>


Expand Down
1 change: 0 additions & 1 deletion Xamarin.CommunityToolkit.ruleset
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
<Rule Id="SA1008" Action="Warning" />
<Rule Id="SA1009" Action="Warning" />
<Rule Id="SA1010" Action="Warning" />
<Rule Id="SA1011" Action="Warning" />
<Rule Id="SA1012" Action="Warning" />
<Rule Id="SA1013" Action="Warning" />
<Rule Id="SA1014" Action="Warning" />
Expand Down
54 changes: 35 additions & 19 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ variables:
#MONO_VERSION: 6_4_0
#XCODE_VERSION: 11.4
NETCORE_VERSION: '5.0.x'
NETCORE_TEST_VERSION: '5.0.x'
NETCORE_TEST_VERSION_3_1: '3.1.x'
NETCORE_TEST_VERSION_2_1: '2.1.x'
RunPoliCheck: 'false'
PathToCsproj: 'src/CommunityToolkit/Xamarin.CommunityToolkit/Xamarin.CommunityToolkit.csproj'
PathToMarkupCsproj: 'src/Markup/Xamarin.CommunityToolkit.Markup/Xamarin.CommunityToolkit.Markup.csproj'
PathToUnitTestCsproj: 'src/CommunityToolkit/Xamarin.CommunityToolkit.UnitTests/Xamarin.CommunityToolkit.UnitTests.csproj'
PathToSln: 'samples/XCT.Sample.sln'

resources:
Expand Down Expand Up @@ -68,6 +70,21 @@ jobs:
pool:
vmImage: windows-2019
steps:
- task: UseDotNet@2
displayName: 'Install .NET SDK'
inputs:
version: $(NETCORE_VERSION)
includePreviewVersions: false
- task: UseDotNet@2
displayName: 'Install .NET 3.1 Test SDK'
inputs:
version: $(NETCORE_TEST_VERSION_3_1)
includePreviewVersions: false
- task: UseDotNet@2
displayName: 'Install .NET 2.1 Test SDK'
inputs:
version: $(NETCORE_TEST_VERSION_2_1)
includePreviewVersions: false
# if this is a tagged build, then update the version number
- powershell: |
$buildSourceBranch = "$(Build.SourceBranch)"
Expand Down Expand Up @@ -112,12 +129,10 @@ jobs:
# command: 'custom'
# custom: 'nuget'
# arguments: 'push --source https://nuget.pkg.github.com/xamarin/index.json --api-key $(GitHub.NuGet.Token) "$(Build.ArtifactStagingDirectory)\nuget\*.nupkg"'
- task: DotNetCoreCLI@2
displayName: Run Tests
- task: CmdLine@2
displayName: 'Run Unit Tests'
inputs:
command: test
projects: '**/*.UnitTests.csproj'
arguments: '--configuration Release --collect "Code coverage"'
script: dotnet test $(PathToUnitTestCsproj) -c Release --collect "Code coverage" -p:BuildInParallel=false
# publish the packages
- task: PublishBuildArtifacts@1
displayName: 'Publish Unsigned NuGets'
Expand Down Expand Up @@ -161,27 +176,28 @@ jobs:
# displayName: Switch to the latest Xcode
# restore, build and pack the packages
- task: UseDotNet@2
displayName: 'Use .Net Core sdk'
displayName: 'Install .NET SDK'
inputs:
version: $(NETCORE_VERSION)
includePreviewVersions: false
- task: UseDotNet@2
displayName: 'Use .Net Core sdk'
displayName: 'Install .NET 3.1 Test SDK'
inputs:
version: $(NETCORE_TEST_VERSION)
version: $(NETCORE_TEST_VERSION_3_1)
includePreviewVersions: false
- task: MSBuild@1
displayName: Build Solution
- task: UseDotNet@2
displayName: 'Install .NET 2.1 Test SDK'
inputs:
solution: $(PathToCsproj)
configuration: Release
msbuildArguments: '/restore /t:Build /p:ContinuousIntegrationBuild=true /p:Deterministic=false'
- task: MSBuild@1
displayName: Pack NuGets
version: $(NETCORE_TEST_VERSION_2_1)
includePreviewVersions: false
- task: CmdLine@2
displayName: 'Build Solution'
inputs:
solution: $(PathToCsproj)
configuration: Release
msbuildArguments: '/t:Pack /p:PackageVersion=$(NugetPackageVersion) /p:PackageOutputPath="$(Build.ArtifactStagingDirectory)/nuget"'
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'
- task: CmdLine@2
displayName: 'Pack NuGets'
inputs:
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"'

- ${{ if eq(variables['System.TeamProject'], 'devdiv') }}:
- template: sign-artifacts/jobs/v2.yml@internal-templates
Expand Down
2 changes: 1 addition & 1 deletion samples/XCT.Sample.Android/SplashActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Xamarin.CommunityToolkit.Sample.Droid
[Activity(Label = "XamarinCommunityToolkitSample", Icon = "@mipmap/icon", Theme = "@style/SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class SplashActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
var intent = new Intent(this, typeof(MainActivity));
Expand Down
4 changes: 2 additions & 2 deletions samples/XCT.Sample.UWP/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ protected override void OnLaunched(LaunchActivatedEventArgs e)
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
void OnNavigationFailed(object? sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
Expand All @@ -97,7 +97,7 @@ void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
void OnSuspending(object sender, SuspendingEventArgs e)
void OnSuspending(object? sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();

Expand Down
7 changes: 5 additions & 2 deletions samples/XCT.Sample.iOS/Renderers/NoLineNavigationRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ public override void ViewWillAppear(bool animated)
// Newest iOS version fix - trycatch isn't optimal
try
{
NavigationBar.ScrollEdgeAppearance.ShadowImage = new UIKit.UIImage();
NavigationBar.ScrollEdgeAppearance.ShadowColor = null;
if (NavigationBar.ScrollEdgeAppearance != null)
{
NavigationBar.ScrollEdgeAppearance.ShadowImage = new UIKit.UIImage();
NavigationBar.ScrollEdgeAppearance.ShadowColor = null;
}
}
catch (Exception)
{
Expand Down
9 changes: 6 additions & 3 deletions samples/XCT.Sample.sln
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.CommunityToolkit.Sa
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F695F5E8-420F-475F-A4CF-F5BB3FA6E818}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
Directory.Build.props = Directory.Build.props
Xamarin.CommunityToolkit.ruleset = Xamarin.CommunityToolkit.ruleset
..\.editorconfig = ..\.editorconfig
..\Directory.Build.props = ..\Directory.Build.props
..\Xamarin.CommunityToolkit.ruleset = ..\Xamarin.CommunityToolkit.ruleset
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.CommunityToolkit.Sample.WPF", "XCT.Sample.WPF\Xamarin.CommunityToolkit.Sample.WPF.csproj", "{C4D6CD2D-8DF4-4D46-936C-1AB31C87B5EA}"
Expand Down Expand Up @@ -62,6 +62,7 @@ Global
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Debug|x86.Build.0 = Debug|Any CPU
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|Any CPU.Build.0 = Release|Any CPU
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|Any CPU.Deploy.0 = Release|Any CPU
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|ARM.ActiveCfg = Release|Any CPU
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|ARM.Build.0 = Release|Any CPU
{8B80BFA6-7B19-4DE7-BD97-7D84194AD0C2}.Release|iPhone.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -191,6 +192,8 @@ Global
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Debug|x86.Build.0 = Debug|x86
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Debug|x86.Deploy.0 = Debug|x86
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|Any CPU.ActiveCfg = Release|x86
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|Any CPU.Build.0 = Release|x86
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|Any CPU.Deploy.0 = Release|x86
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|ARM.ActiveCfg = Release|ARM
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|ARM.Build.0 = Release|ARM
{91C748B4-E9ED-4543-880A-26747B03DE3A}.Release|ARM.Deploy.0 = Release|ARM
Expand Down
4 changes: 3 additions & 1 deletion samples/XCT.Sample/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Xamarin.CommunityToolkit.Helpers;
using System.Globalization;
using Xamarin.CommunityToolkit.Helpers;
using Xamarin.CommunityToolkit.Sample.Pages;
using Xamarin.CommunityToolkit.Sample.Resx;
using Xamarin.Forms.PlatformConfiguration;
Expand All @@ -14,6 +15,7 @@ public App()

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

InitializeComponent();
MainPage = new BaseNavigationPage(new WelcomePage());
Expand Down
84 changes: 38 additions & 46 deletions samples/XCT.Sample/Helpers/RelayCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,21 @@ namespace Xamarin.CommunityToolkit.Sample
{
public class RelayCommand : ICommand
{
readonly Action execute;
readonly Func<Task> asyncExecute;
readonly Action? execute;
readonly Func<Task>? asyncExecute;
readonly Func<bool>? canExecute;

Func<bool> canExecute;
int executingCount;

public RelayCommand(Action execute, Func<bool> canExecute = null)
public RelayCommand(Action execute, Func<bool>? canExecute = null)
{
if (execute == null)
throw new ArgumentNullException(nameof(execute));
this.execute = execute;
this.execute = execute ?? throw new ArgumentNullException(nameof(execute));
this.canExecute = canExecute;
}

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
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
{
if (execute == null)
throw new ArgumentNullException(nameof(execute));
asyncExecute = execute;
asyncExecute = execute ?? throw new ArgumentNullException(nameof(execute));
this.canExecute = canExecute;
}

Expand All @@ -34,7 +30,7 @@ public RelayCommand(Action execute, Func<bool> canExecute = null)
/// </summary>
/// <param name="parameter">Ignored; this is the paremeterless command class</param>
/// <returns></returns>
public bool CanExecute(object parameter = null)
public bool CanExecute(object? parameter = null)
{
try
{
Expand All @@ -47,15 +43,12 @@ public bool CanExecute(object parameter = null)
}
}

public event EventHandler CanExecuteChanged;
public event EventHandler? CanExecuteChanged;

public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);

// Asynchronous command handling based on http://stackoverflow.com/a/31595509/6043538
public async void Execute(object parameter = null)
public async void Execute(object? parameter = null)
{
var couldExecuteBeforeExecute = CanExecute();
if (!couldExecuteBeforeExecute)
Expand All @@ -70,8 +63,10 @@ public async void Execute(object parameter = null)
{
if (execute != null)
execute();
else
else if (asyncExecute != null)
await asyncExecute();
else
throw new Exception("Execute is null");
}
catch (Exception ex)
{
Expand All @@ -89,31 +84,30 @@ public async void Execute(object parameter = null)

public class RelayCommandAsync : RelayCommand
{
public RelayCommandAsync(Func<Task> execute, Func<bool> canExecute = null)
: 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
public RelayCommandAsync(Func<Task> execute, Func<bool>? canExecute = null)
: 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
}
}

public class RelayCommand<TParameter> : ICommand
{
readonly Action<TParameter> execute;
readonly Func<TParameter, Task> asyncExecute;
readonly Action<TParameter>? execute;
readonly Func<TParameter, Task>? asyncExecute;
readonly Func<TParameter?, bool>? canExecute;

Func<TParameter, bool> canExecute;
int executingCount;

public RelayCommand(Action<TParameter> execute, Func<TParameter, bool> canExecute = null)
public RelayCommand(Action<TParameter> execute, Func<TParameter?, bool>? canExecute = null)
{
if (execute == null)
throw new ArgumentNullException(nameof(execute));
this.execute = execute;
this.execute = execute ?? throw new ArgumentNullException(nameof(execute));
this.canExecute = canExecute;
}

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
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
{
if (execute == null)
throw new ArgumentNullException(nameof(execute));
asyncExecute = execute;
asyncExecute = execute ?? throw new ArgumentNullException(nameof(execute));
this.canExecute = canExecute;
}

Expand All @@ -122,11 +116,11 @@ public RelayCommand(Action<TParameter> execute, Func<TParameter, bool> canExecut
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
public bool CanExecute(object parameter = null)
public bool CanExecute(object? parameter = null)
{
try
{
return canExecute != null ? canExecute((TParameter)parameter) : executingCount == 0;
return canExecute != null ? canExecute((TParameter?)parameter) : executingCount == 0;
}
catch (Exception ex)
{
Expand All @@ -135,12 +129,9 @@ public bool CanExecute(object parameter = null)
}
}

public event EventHandler CanExecuteChanged;
public event EventHandler? CanExecuteChanged;

public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);

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

if (execute != null)
{
execute(parameter);
}
else
{
else if (asyncExecute != null)
await asyncExecute(parameter);
}
else
throw new Exception("Execute is null");
}
catch (Exception ex)
{
Expand All @@ -183,7 +172,10 @@ public async void Execute(object parameterAsObject)

public class RelayCommandAsync<TParameter> : RelayCommand<TParameter>
{
public RelayCommandAsync(Func<TParameter, Task> execute, Func<TParameter, bool> canExecute = null)
: 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
public RelayCommandAsync(Func<TParameter, Task> execute, Func<TParameter?, bool>? canExecute = null)
: 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
}
}
}
Loading

0 comments on commit d74ab1d

Please sign in to comment.