diff --git a/src/Uno.Extensions.Reactive.UI.Tests/Generator/Given_VMWithCommands.cs b/src/Uno.Extensions.Reactive.UI.Tests/Generator/Given_VMWithCommands.cs new file mode 100644 index 0000000000..182dc9ae4f --- /dev/null +++ b/src/Uno.Extensions.Reactive.UI.Tests/Generator/Given_VMWithCommands.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Data; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Uno.Extensions.Reactive.UI; +using Uno.UI.RuntimeTests; +using Button = Microsoft.UI.Xaml.Controls.Button; + +namespace Uno.Extensions.Reactive.WinUI.Tests.Generator; + +[TestClass] +[RunsOnUIThread] +public partial class Given_VMWithCommands +{ + public partial class When_ParameterFeed_Then_SubscribedWithSameContext_ViewModel + { + public int FeedInvokeCount { get; private set; } + + public int CommandLastParameter { get; private set; } = -1; + + public IFeed MyFeed => Feed.Async(async ct => ++FeedInvokeCount); + + public void DoSomething(int myFeed, CancellationToken ct) + => CommandLastParameter = myFeed; + } + + [TestMethod] + public async Task When_ParameterFeed_Then_SubscribedWithSameContext() + { + var vm = new BindableWhen_ParameterFeed_Then_SubscribedWithSameContext_ViewModel(); + + await UIHelper.WaitFor(() => vm.MyFeed != 0, default); + + var current = vm.MyFeed; + vm.DoSomething.Execute(null); + + await UIHelper.WaitFor(() => vm.Model.CommandLastParameter != -1, default); + + Assert.AreEqual(1, vm.FeedInvokeCount); + Assert.AreEqual(current, vm.Model.CommandLastParameter); + } + + [TestMethod] + public async Task When_ParameterFeed_Then_SubscribedWithSameContext_UsingUI() + { + FeedView view; + Button doSomething; + var vm = new BindableWhen_ParameterFeed_Then_SubscribedWithSameContext_ViewModel(); + var ui = new StackPanel + { + DataContext = vm, + Children = + { + (view = new FeedView()), + (doSomething = new Button()) + } + }; + + view.SetBinding(FeedView.SourceProperty, new Binding { Path = new PropertyPath("MyFeed") }); + doSomething.SetBinding(Button.CommandProperty, new Binding { Path = new PropertyPath("DoSomething") }); + + await UIHelper.Load(ui, default); + + await UIHelper.WaitFor(() => vm.MyFeed is not 0, default); + + var current = vm.MyFeed; + doSomething.Command.Execute(null); + + await UIHelper.WaitFor(() => vm.Model.CommandLastParameter != -1, default); + + Assert.AreEqual(1, vm.FeedInvokeCount); + Assert.AreEqual(current, vm.Model.CommandLastParameter); + } +} diff --git a/src/Uno.Extensions.Reactive/Utils/FeedUIHelper.cs b/src/Uno.Extensions.Reactive/Utils/FeedUIHelper.cs index 216814d4a0..9e1a0423e3 100644 --- a/src/Uno.Extensions.Reactive/Utils/FeedUIHelper.cs +++ b/src/Uno.Extensions.Reactive/Utils/FeedUIHelper.cs @@ -48,7 +48,17 @@ public static async IAsyncEnumerable> GetSource(IFeed feed, Sou } } - private static async ValueTask> GetSourceEnumerator(ISignal signal, SourceContext context) + private static async ValueTask>> GetSourceEnumerator(IFeed signal, SourceContext context) + { + var ct = context.Token; + var src = DispatcherHelper.HasThreadAccess + ? await Task.Run(() => context.GetOrCreateSource(signal), ct).ConfigureAwait(false) + : context.GetOrCreateSource(signal); + + return src.GetAsyncEnumerator(ct); + } + + private static async ValueTask> GetSourceEnumerator(ISignal signal, SourceContext context) { var ct = context.Token; var src = DispatcherHelper.HasThreadAccess