Вопрос

У меня есть Canvas с поддержкой 2 касаний в приложении Silverlight.Что мне нужно сделать, так это когда человек удерживает (нажимает и продолжает нажимать) оба полотна одновременно, увеличить значение на экране один раз.Это должно происходить при каждом "двойном" удержании.Я могу сделать это нормально, используя обычные события, но попытался написать то же самое с помощью 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() ;
        }
    }

Надеюсь, вы понимаете, что я пытаюсь сделать.У каждого canvas есть событие hold и release, поэтому, когда HoldLeft и HoldRight оба удерживаются, делайте что-нибудь до тех пор, пока не будут освобождены либо HoldRight, либо HoldLeft are.

Будем признательны за любую помощь.

Это было полезно?

Решение

Я считаю, что решил свою проблему.

Вместо нескольких подписок я пошел на это.

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

Кажется, он делает то, что я хочу, но я открыт для дальнейших предложений/улучшений.

Другие советы

Я наткнулся на этот ответ и подумал, что в нем нет смысла:

    leftHold.Zip(rightHold, (a,b) => true)
        .TakeUntil(leftRelease.Amb(rightRelease))
        .Subscribe(_ => TextOutput.Text =
            (Convert.ToInt32(TextOutput.Text) + 1).ToString());
  • Zip объединяет события таким образом, чтобы потребовалось, чтобы я отпустил левую и правую кнопки, прежде чем удерживать их снова.Если бы я отпустил вправо и удержал его снова, это наблюдаемое не сработало бы снова.
  • Я также подумал бы, что события hold запускаются только один раз, поэтому не должно быть никакой необходимости в 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);

Я знаю, что этому вопросу годичной давности, но я хотел бы знать, не пропустил ли я что-то или этот ответ работает.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top