This repository was archived by the owner on May 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 459
Implement a generic version of the EventToCommandBehavior #1010
Merged
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
7c598f7
created ECBGeneric
pictos 52ed976
Added Generic implemention to the EventToCommandBehavior
pictos 6a628f1
make EventToCommandBehavior<TType> sealed
pictos 50c713e
Fixed for value types
pictos 1e3c0b5
added nullable notations
pictos d4945b6
update the comment
pictos 143ee79
fixed unit test
pictos 203c3ee
Merge branch 'develop' into pj/generic-event2command-behavior
pictos aae8474
Merge branch 'develop' into pj/generic-event2command-behavior
jfversluis 8fe1d6f
Merge branch 'develop' into pj/generic-event2command-behavior
jfversluis 608b165
Merge branch 'develop' into pj/generic-event2command-behavior
jfversluis 6105301
Migrate Unit Tests to NUnit
TheCodeTraveler ea23c2c
Merge branch 'develop' into pj/generic-event2command-behavior
TheCodeTraveler 0d4ccf7
Fixed unitTest
pictos 818bbdd
changed to use C#9 features
pictos 694706b
removed Convert method
pictos b484698
Add Inheritance Test
TheCodeTraveler File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
170 changes: 170 additions & 0 deletions
170
...olkit/Xamarin.CommunityToolkit.UnitTests/Behaviors/EventToCommandBehaviorGeneric_Tests.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
using System; | ||
using System.Reflection; | ||
using Xamarin.CommunityToolkit.Behaviors; | ||
using Xamarin.CommunityToolkit.Converters; | ||
using Xamarin.CommunityToolkit.UnitTests.Mocks; | ||
using Xamarin.Forms; | ||
using NUnit.Framework; | ||
|
||
namespace Xamarin.CommunityToolkit.UnitTests.Behaviors | ||
{ | ||
public class EventToCommandBehaviorGeneric_Tests | ||
{ | ||
[SetUp] | ||
public void Setup() => Device.PlatformServices = new MockPlatformServices(); | ||
|
||
[Test] | ||
public void ArgumentExceptionIfSpecifiedEventDoesNotExist() | ||
{ | ||
var listView = new ListView(); | ||
var behavior = new EventToCommandBehavior<Coffee> | ||
{ | ||
EventName = "Wrong Event Name" | ||
}; | ||
Assert.Throws<ArgumentException>(() => listView.Behaviors.Add(behavior)); | ||
} | ||
|
||
[Test] | ||
public void NoExceptionIfSpecifiedEventExists() | ||
{ | ||
var listView = new ListView(); | ||
var behavior = new EventToCommandBehavior<Coffee> | ||
{ | ||
EventName = nameof(ListView.ItemTapped) | ||
}; | ||
listView.Behaviors.Add(behavior); | ||
} | ||
|
||
[Test] | ||
public void NoExceptionIfAttachedToPage() | ||
{ | ||
var page = new ContentPage(); | ||
var behavior = new EventToCommandBehavior<Coffee> | ||
{ | ||
EventName = nameof(Page.Appearing) | ||
}; | ||
page.Behaviors.Add(behavior); | ||
} | ||
|
||
[Test] | ||
public void NoExceptionWhenTheEventArgsAreNotNull() | ||
{ | ||
var vm = new ViewModelCoffe(); | ||
var behavior = new EventToCommandBehavior<Coffee> | ||
{ | ||
EventName = nameof(ListView.ItemTapped), | ||
EventArgsConverter = new ItemSelectedEventArgsConverter(), | ||
Command = vm.SelectedCommand | ||
}; | ||
|
||
Assert.Null(vm.CoffeeName); | ||
var coffe = new Coffee { Id = 1, Name = "Café" }; | ||
var eventArgs = new SelectedItemChangedEventArgs(coffe, 1); | ||
|
||
var notNullArgs = new object?[] { null, eventArgs }; | ||
|
||
TriggerEventToCommandBehavior(behavior, notNullArgs); | ||
|
||
Assert.AreEqual(coffe.Name, vm.CoffeeName); | ||
} | ||
|
||
[Test] | ||
public void NoExceptionWhenTheEventArgsAreNotNull_InheritedType() | ||
{ | ||
var vm = new ViewModelCoffe(); | ||
var behavior = new EventToCommandBehavior<Coffee> | ||
{ | ||
EventName = nameof(ListView.ItemTapped), | ||
EventArgsConverter = new ItemSelectedEventArgsConverter(), | ||
Command = vm.SelectedCommand | ||
}; | ||
|
||
Assert.Null(vm.CoffeeName); | ||
var coffe = new Starbucks { Id = 1, Name = "Latte" }; | ||
var eventArgs = new SelectedItemChangedEventArgs(coffe, 1); | ||
|
||
var notNullArgs = new object?[] { null, eventArgs }; | ||
|
||
TriggerEventToCommandBehavior(behavior, notNullArgs); | ||
|
||
Assert.AreEqual(coffe.Name, vm.CoffeeName); | ||
} | ||
|
||
[Test] | ||
public void ParameterOfTypeInt() | ||
{ | ||
var vm = new ViewModelCoffe(); | ||
var behavior = new EventToCommandBehavior<int> | ||
{ | ||
EventName = nameof(ListView.ItemTapped), | ||
Command = vm.SelectedCommand, | ||
CommandParameter = 2 | ||
}; | ||
|
||
var nullArgs = new object?[] { null, null }; | ||
|
||
TriggerEventToCommandBehavior(behavior, nullArgs); | ||
} | ||
|
||
[Test] | ||
public void NoExceptionWhenTheSelectedItemIsNull() | ||
{ | ||
var vm = new ViewModelCoffe(); | ||
var behavior = new EventToCommandBehavior<Coffee> | ||
{ | ||
EventName = nameof(ListView.ItemTapped), | ||
EventArgsConverter = new ItemSelectedEventArgsConverter(), | ||
Command = vm.SelectedCommand | ||
}; | ||
|
||
Assert.Null(vm.CoffeeName); | ||
var coffeNull = default(Coffee); | ||
var notNullArgs = new object?[] { null, new SelectedItemChangedEventArgs(coffeNull, -1) }; | ||
|
||
TriggerEventToCommandBehavior(behavior, notNullArgs); | ||
|
||
Assert.Null(vm.CoffeeName); | ||
} | ||
|
||
static void TriggerEventToCommandBehavior<T>(EventToCommandBehavior<T> eventToCommand, object?[] args) | ||
{ | ||
var method = eventToCommand.GetType().GetMethod("OnTriggerHandled", BindingFlags.Instance | BindingFlags.NonPublic); | ||
method?.Invoke(eventToCommand, args); | ||
} | ||
|
||
class Starbucks : Coffee | ||
{ | ||
} | ||
|
||
class Coffee | ||
{ | ||
public int Id { get; set; } | ||
|
||
public string Roaster { get; set; } = string.Empty; | ||
|
||
public string? Name { get; set; } | ||
|
||
public string Image { get; set; } = string.Empty; | ||
} | ||
|
||
class ViewModelCoffe | ||
{ | ||
public Command<Coffee> SelectedCommand { get; set; } | ||
|
||
public string? CoffeeName { get; set; } | ||
|
||
public ViewModelCoffe() | ||
{ | ||
SelectedCommand = new Command<Coffee>(Selected); | ||
} | ||
|
||
void Selected(Coffee coffee) | ||
{ | ||
if (coffee == null) | ||
return; | ||
|
||
CoffeeName = coffee?.Name; | ||
} | ||
} | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
...mmunityToolkit/Xamarin.CommunityToolkit/Behaviors/EventToCommandBehaviorGeneric.shared.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System; | ||
|
||
namespace Xamarin.CommunityToolkit.Behaviors | ||
{ | ||
/// <summary> | ||
/// This <see cref="EventToCommandBehavior"/> cast the sender object to a specific type defined by the user. | ||
/// </summary> | ||
/// <typeparam name="TType">The type that you want to receive in your <see cref="Xamarin.Forms.Command"/> </typeparam> | ||
public sealed class EventToCommandBehavior<TType> : EventToCommandBehavior | ||
{ | ||
protected override void OnTriggerHandled(object? sender = null, object? eventArgs = null) | ||
{ | ||
var parameter = CommandParameter | ||
?? EventArgsConverter?.Convert(eventArgs, typeof(object), null, null) | ||
?? eventArgs; | ||
|
||
if (parameter is not TType) | ||
{ | ||
// changing it to the default value to avoid a cast exception | ||
parameter = default(TType); | ||
} | ||
|
||
var command = Command; | ||
if (command?.CanExecute(parameter) ?? false) | ||
command.Execute(parameter); | ||
} | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.