C# 如何使用Rx在一系列具有暂停和淡入淡出的字符串中进行迭代?

C# 如何使用Rx在一系列具有暂停和淡入淡出的字符串中进行迭代?,c#,xaml,mvvm,system.reactive,C#,Xaml,Mvvm,System.reactive,我的要求是从数组中提取一系列字符串,从第一个字符串开始,5秒后移动到下一个字符串,同时使用Xamarin中的Rx with XAML淡出并淡入下一个字符串。您可以假设这发生在具有“Message”属性和“MessageOpacity”属性的视图模型上,该属性采用文本和0到1之间的小数。您还可以假设我有一个后台调度程序和UiScheduler设置 我对Rx是相当陌生的,它将变得明显,并且到目前为止已经做到了: var messages = new[] {

我的要求是从数组中提取一系列字符串,从第一个字符串开始,5秒后移动到下一个字符串,同时使用Xamarin中的Rx with XAML淡出并淡入下一个字符串。您可以假设这发生在具有“Message”属性和“MessageOpacity”属性的视图模型上,该属性采用文本和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];
        });    
上面的方法不起作用,因为缓冲区没有按我预期的方式工作。相反,它每5秒快速连续触发4个字符串,而不是单步执行每个字符串

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


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

您可以使用Zip运算符和可观察的。间隔来提供所需的迭代字符串输出:

[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());
}
[事实]
public void应通过字符串每隔五秒钟()
{
TestScheduler scheduler=新的TestScheduler();
字符串[]消息=新建[]
{
“欢迎”,
“我们正在为你做准备”,
“第一次这样做可能需要一段时间”
};
预期风险值=新[]
{
ReactiveTest.OnNext(ReactiveTest.Subscribed+TimeSpan.FromSeconds(0)。勾选“欢迎”),
ReactiveTest.OnNext(ReactiveTest.Subscribed+TimeSpan.FromSeconds(5)。勾选“我们正在为您进行设置”),
ReactiveTest.OnNext(ReactiveTest.Subscribed+TimeSpan.FromSeconds(10)。勾选“第一次可能需要一点时间”),
ReactiveTest.OnCompleted(ReactiveTest.Subscribed+TimeSpan.FromSeconds(15).Ticks)
};
var-actual=scheduler.Start(
//解决方案
()=>observeable.Zip(
messages.ToObservable(),
可观察的时间间隔(时间跨度从秒(5),调度程序)。开始时间(0),
(文本,时间)=>文本),
时间跨度。从秒(20)。滴答声
);
Assert.Equal(应为,实际为.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());
}
[事实]
public void应通过字符串everyfiveseconds删除提供字符串和不透明度()
{
TestScheduler scheduler=新的TestScheduler();
字符串[]消息=新建[]
{
“欢迎”,
“我们正在为你做准备”,
“第一次这样做可能需要一段时间”
};
预期风险值=新[]
{
ReactiveTest.OnNext(ReactiveTest.Subscribed+TimeSpan.FromSeconds(0).Ticks,Tuple.Create(“欢迎”,0.0)),
ReactiveTest.OnNext(ReactiveTest.Subscribed+TimeSpan.FromSeconds(5).Ticks,Tuple.Create(“我们正在为您设置”,0.5)),
ReactiveTest.OnNext(ReactiveTest.Subscribed+TimeSpan.FromSeconds(10).Ticks,Tuple.Create(“这可能需要一点时间,第一次”,1.0)),
ReactiveTest.OnCompleted(ReactiveTest.Subscribed+TimeSpan.FromSeconds(15).Ticks)
};
var-actual=scheduler.Start(
//解决方案
()=>可观察
Zip先生(
messages.ToObservable(),
可观察的时间间隔(时间跨度从秒(5),调度程序)。开始时间(0),
(文本,时间)=>文本)
.Select((text,index)=>Tuple.Create(text,Convert.ToDouble(index)/Convert.ToDouble(messages.Length-1)),
时间跨度。从秒(20)。滴答声
);
Assert.Equal(应为,实际为.Messages.ToArray());
}
请注意,第一个元素的不透明度将为零,因此您不会看到它。您可能需要稍微更改数学(提供偏移)以将不透明度从非零值缩放为1


希望它有帮助:0)

您可以使用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());
}
[事实]
public void应通过字符串每隔五秒钟()
{
TestScheduler scheduler=新的TestScheduler();
字符串[]消息=新建[]
{
“欢迎”,
“我们正在为你做准备”,
“第一次这样做可能需要一段时间”
};
预期风险值=新[]
{
ReactiveTest.OnNext(ReactiveTest.Subscribed+TimeSpan.FromSeconds(0)。勾选“欢迎”),
ReactiveTest.OnNext(ReactiveTest.Subscribed+TimeSpan.FromSeconds(5)。勾选“我们正在为您进行设置”),
ReactiveTest.OnNext(ReactiveTest.Subscribed+TimeSpan.FromSeconds(10)。勾选“第一次可能需要一点时间”),
ReactiveTest.OnCompleted(ReactiveTest.Subscribed+TimeSpan.FromSeconds(15).Ticks)
};
var-actual=scheduler.Start(
//解决方案
()=>observeable.Zip(
messages.ToObservable(),
可观察的时间间隔(时间跨度从秒(5),调度程序)。开始时间(0),
(文本,时间)=>文本),
时间跨度。从秒(20)。滴答声
);
Assert.Equal(应为,实际为.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());
}
[事实]
public void应通过字符串everyfiveseconds删除提供字符串和不透明度()
{
TestScheduler scheduler=新的TestScheduler();
字符串[]消息=新建[]
{
“欢迎”,
“我们正在为你做准备”,
“第一次这样做可能需要一段时间”
};
预期风险值=新[]
{
ReactiveTest.OnNext(ReactiveTest.Subscribed+TimeSpan.FromSeconds(0).Ticks,Tuple.Crea