c# - 如何使用 Rx 遍历一系列带有停顿和淡入淡出的字符串?

标签 c# xaml mvvm system.reactive

我的要求是从数组中获取一系列字符串,从第一个开始,5 秒后移动到下一个字符串,同时使用 Xamarin 中的 Rx 和 XAML 淡出并淡出下一个字符串。您可以假设这是在具有“Message”属性和“MessageOpacity”属性的 View 模型上发生的,它们适用于文本和 0 到 1 之间的小数。您还可以假设我有后台调度程序和 UiScheduler 设置。

我对 Rx 相当陌生,这将变得很明显并且到目前为止已经达到了这个程度:

var messages = new[] { 
                       "Welcome", 
                       "We are settings things up for you", 
                       "This may take a little while first time" };

Observable.Interval(TimeSpan.FromSeconds(5), Scheduler.BackgroundScheduler)
                  .SelectMany((long arg) => messages)
                  .Buffer(1, 1)
                  .SubscribeOn(Scheduler.UiScheduler)
                  .Subscribe((obj) => 
        {
            Message = obj[0];
        });    

上面的方法不起作用,因为 Buffer 没有按照我的预期工作。相反,它每 5 秒快速连续地发射 4 根弦,而不是逐步穿过每根弦。

我不明白的是如何以正确的“Rx”方式按每“x 秒”的顺序遍历每个字符串,以及(作为对我的奖励!)如何随后触发另一个可观察的每个新消息在每次更改时将不透明度从 0 增加和减少到 1。

目标是在发生重大更新或用户等待长时间操作完成时实现“windows 10”风格的屏幕。

最佳答案

您可以使用 Zip 运算符和 Observable.Interval 来提供您想要的迭代字符串输出:

[Fact]
public void ShouldIterateThroughStringsEveryFiveSeconds()
{
    TestScheduler scheduler = new TestScheduler();

    string[] messages = new[]
    {
                "Welcome",
                "We are settings things up for you",
                "This may take a little while first time"
    };

    var expected = new[]
    {
        ReactiveTest.OnNext(ReactiveTest.Subscribed + TimeSpan.FromSeconds(0).Ticks, "Welcome"),
        ReactiveTest.OnNext(ReactiveTest.Subscribed + TimeSpan.FromSeconds(5).Ticks, "We are settings things up for you"),
        ReactiveTest.OnNext(ReactiveTest.Subscribed + TimeSpan.FromSeconds(10).Ticks, "This may take a little while first time"),
        ReactiveTest.OnCompleted<string>(ReactiveTest.Subscribed + TimeSpan.FromSeconds(15).Ticks)
    };

    var actual = scheduler.Start(
        // Solution
        () => Observable.Zip(
            messages.ToObservable(),
            Observable.Interval(TimeSpan.FromSeconds(5), scheduler).StartWith(0),
            (text, time) => text),
        TimeSpan.FromSeconds(20).Ticks
    );

    Assert.Equal(expected, actual.Messages.ToArray());
}

编辑:您可以像这样组合它们,而不是第二个可观察的不透明度:

[Fact]
public void ShouldIterateThroughStringsEveryFiveSecondsProvidingStringAndOpacity()
{
    TestScheduler scheduler = new TestScheduler();

    string[] messages = new[]
    {
                "Welcome",
                "We are settings things up for you",
                "This may take a little while first time"
    };

    var expected = new[]
    {
        ReactiveTest.OnNext(ReactiveTest.Subscribed + TimeSpan.FromSeconds(0).Ticks, Tuple.Create("Welcome", 0.0)),
        ReactiveTest.OnNext(ReactiveTest.Subscribed + TimeSpan.FromSeconds(5).Ticks, Tuple.Create("We are settings things up for you", 0.5)),
        ReactiveTest.OnNext(ReactiveTest.Subscribed + TimeSpan.FromSeconds(10).Ticks, Tuple.Create("This may take a little while first time", 1.0)),
        ReactiveTest.OnCompleted<Tuple<string, double>>(ReactiveTest.Subscribed + TimeSpan.FromSeconds(15).Ticks)
    };

    var actual = scheduler.Start(
        // Solution
        () => Observable
            .Zip(
                messages.ToObservable(), 
                Observable.Interval(TimeSpan.FromSeconds(5), scheduler).StartWith(0),
                (text, time) => text)
            .Select((text, index) => Tuple.Create(text, Convert.ToDouble(index) / Convert.ToDouble(messages.Length - 1))),
        TimeSpan.FromSeconds(20).Ticks
    );

    Assert.Equal(expected, actual.Messages.ToArray());
}

请注意,第一个元素的不透明度将为零,因此您看不到它。您可能希望稍微更改数学(提供偏移量)以将不透明度从非零值缩放为一。

希望对你有帮助:0)

关于c# - 如何使用 Rx 遍历一系列带有停顿和淡入淡出的字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40262437/

相关文章:

c# - 以异步方式以编程方式将 UIElement 添加到 View

c# - 使用 T4 和 C# 在运行时编译动态代码

c# - 重新使用继承的 FK 关系?

wpf - ComboBox 的自定义模板忽略 DisplayMemberPath 的使用

xaml - 在 xamarin.forms 中设计图片库

wpf - 使用相同的 DataContext 设置 DataGrid 和 ContextMenu

c# - 我在可移植类库上使用 HttpClient 得到 403

c# - 如何使用 C#/WPF 录制音频?

c# - 在 WPF ListView 中逐项滚动

c# - Prism 5 模块化 : how to add RegionName in DataTemplate of TabControl in ItemsControl