【问题标题】:Combining Multiple Events in RX在 RX 中组合多个事件
【发布时间】:2010-03-11 12:06:42
【问题描述】:

我在 Silverlight 应用程序中启用了 2 点触控画布。我需要做的是当一个人同时按住(按住并按住)两个画布时,屏幕上的值会增加一次。这应该发生在每个“双重”持有上。我可以使用正常事件很好地做到这一点,但尝试使用 RX 编写相同的东西,但我卡住了。

目前我的代码看起来与单独事件方法相同(使用全局变量和全局方法),但我认为必须有更好的方法来组合它。任何人都可以提出更好的方法吗?

        var leftHold = Observable.FromEvent<TCanvas.HoldHandler, GestureHoldEventArgs>(
                h => new TCanvas.HoldHandler(h),
                h => HoldLeft.Hold += h,
                h => HoldLeft.Hold += h
            );

        var rightHold = Observable.FromEvent<TCanvas.HoldHandler, GestureHoldEventArgs>(
                h => new TCanvas.HoldHandler(h),
                h => HoldRight.Hold += h,
                h => HoldRight.Hold += h
            );

        var rightRelease = Observable.FromEvent<TCanvas.ReleaseHandler, EventArgs>(
                h => new TCanvas.ReleaseHandler(e => { }),
                h => HoldRight.Release += h,
                h => HoldRight.Release += h
            );


        var leftRelease = Observable.FromEvent<TCanvas.ReleaseHandler, EventArgs>(
                h => new TCanvas.ReleaseHandler(e => { }),
                h => HoldLeft.Release += h,
                h => HoldLeft.Release += h
            );

        leftHold.Subscribe(e =>
        {
            _leftHeld = true;
            DoCheck();
        });

        rightHold.Subscribe(e =>
            {
                _rightHeld = true;
                DoCheck();
            });

        rightRelease.Subscribe(e =>
        {
            _rightHeld = false;
            DoCheck();
        });


        leftRelease.Subscribe(e =>
        {
            _leftHeld = false;
            DoCheck();
        });

非常基本的 DoCheck 函数看起来像这样......

    private void DoCheck()
    {
        if (_rightHeld && _leftHeld)
        {
            MyTextBox.Text = (Convert.ToInt32(MyTextBox.Text) + 1).ToString() ;
        }
    }

希望你能看到我想要做什么。每个画布都有一个保持和释放事件,因此当 HoldLeft 和 HoldRight 都被保持时,会做一些事情,直到 HoldRight 或 HoldLeft 被释放。

任何帮助将不胜感激。

【问题讨论】:

    标签: silverlight system.reactive


    【解决方案1】:

    我相信我已经解决了自己的问题。

    而不是多次订阅我去这个。

            leftHold.Zip(rightHold, (a,b) => true)
                .TakeUntil(leftRelease.Amb(rightRelease))
                .Subscribe(_ => TextOutput.Text = (Convert.ToInt32(TextOutput.Text) + 1).ToString());
    

    它似乎可以满足我的要求,但我愿意接受进一步的建议/改进。

    【讨论】:

    • 这和我要推荐的很接近,真的很简单很好。
    • 这似乎不是正确的解决方案。 Zip 将事件配对,因此需要我在再次握住它们之前释放左右。如果我正确释放并再次按住它,则此可观察对象将不会再次触发。我也认为保持事件只触发一次,所以不需要TakeUntil 调用?你是如何让这对新的持有人重新开火的?
    【解决方案2】:

    我遇到了这个答案,并认为它没有意义:

        leftHold.Zip(rightHold, (a,b) => true)
            .TakeUntil(leftRelease.Amb(rightRelease))
            .Subscribe(_ => TextOutput.Text =
                (Convert.ToInt32(TextOutput.Text) + 1).ToString());
    
    • Zip 将事件配对 要求我释放左边和 再次持有它们之前的权利。 如果我正确释放并持有它 再次,这个 observable 不会触发 再次。
    • 我也认为持有 事件只触发一次,所以有 应该不需要 TakeUntil 来电。
    • 我也看不出这个答案会如何 重新开火-似乎只有一个 价值。

    这里有一个替代方案:

    var left = leftHold.Select(x => true).Merge(leftRelease.Select(x => false));
    var right = rightHold.Select(x => true).Merge(rightRelease.Select(x => false));
    
    var bothHold =
        left.CombineLatest(right, (l, r) => l && r)
            .Where(lr => lr == true)
            .Select(lr => (Convert.ToInt32(MyTextBox.Text) + 1).ToString());
    
    bothHold.Subscribe(t => MyTextBox.Text = t);
    

    我知道这个问题已经有一年了,但我很想知道我是否遗漏了什么或者这个答案是否有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-30
      • 1970-01-01
      • 2020-10-14
      相关资源
      最近更新 更多