Привязка команды mvvmcross touch в Android

Я ищу способ сделать привязку команды «Touch» между axml и ViewModel или что-то еще, например FocusChanged и т. Д.

Простая команда «Click» работает нормально, например: local:MvxBind="{'Touch':{'Path':'CameraButtonCommand'}}" />

    public IMvxCommand CameraButtonCommand
    {
        get
        {
            return new MvxRelayCommand(
                () =>
                {
                    RequestNavigate<AugRealityViewModel>(true);
                })
            ;
        }
    }

Однако я пробовал другие типы событий для элемента управления (в данном случае это ImageButton), и они не обрабатываются. Когда я проверил списки событий в классе просмотра, я вижу их:

    public event EventHandler Click;
    public event EventHandler<View.CreateContextMenuEventArgs> ContextMenuCreated;
    public event EventHandler<View.FocusChangeEventArgs> FocusChange;
    public event EventHandler<View.KeyEventArgs> KeyPress;
    public event EventHandler<View.LongClickEventArgs> LongClick;

Только событие Click имеет прикрепленный к нему общий EventHandler, в то время как другие имеют общие EventHandlers, и мне интересно, является ли это причиной, по которой оно не работает.

Я также попытался прикрепить метод к этим событиям в классе View, получая надлежащий контроль с помощью метода FindViewById, и на этот раз он работает, как и ожидалось. Но что-то не получается в аксмле через Команды.

Также еще одна вещь. Событие "Click" отправляет в качестве одного из параметров объект "EventArgs", а также ссылку на объект. Я легко вижу это, если делаю это поведение в View Class, но когда я делаю это с помощью привязки, я не вижу этих аргументов при обработке команды в ViewModel.


person Lucas    schedule 05.08.2012    source источник


Ответы (1)


Платформа может автоматически связывать любые события, для которых требуются типы EventHandler. Однако для любых событий, для которых требуется шаблонный EventHandler (с пользовательскими EventArgs), вы правы — вам нужно включить пользовательскую привязку.

Хорошей новостью является то, что пользовательские привязки легко писать и включать.

Например, для привязки:

public event EventHandler<View.LongClickEventArgs> LongClick;

вы можете включить что-то вроде:

public class LongPressEventBinding
    : MvxBaseAndroidTargetBinding
{
    private readonly View _view;
    private IMvxCommand _command;

    public LongPressEventBinding(View view)
    {
        _view = view;
        _view.LongClick += ViewOnLongClick;
    }

    private void ViewOnLongClick(object sender, View.LongClickEventArgs eventArgs)
    {
        if (_command != null)
        {
            _command.Execute();
        }
    }

    public override void SetValue(object value)
    {
        _command = (IMvxCommand)value;
    }

    protected override void Dispose(bool isDisposing)
    {
        if (isDisposing)
        {
            _view.Click -= ViewOnLongClick;
        }
        base.Dispose(isDisposing);
    }

    public override Type TargetType
    {
        get { return typeof(IMvxCommand); }
    }

    public override MvxBindingMode DefaultMode
    {
        get { return MvxBindingMode.OneWay; }
    }
}

Который можно настроить в настройках, используя что-то вроде:

    protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
    {
        base.FillTargetFactories(registry);

        registry.RegisterFactory(new MvxCustomBindingFactory<View>("LongPress", view => new LongPressEventBinding(view)));
    }

Обратите внимание, что вы не можете написать один класс, который привязывается ко всем различным типам событий, поскольку компилятор требует, чтобы вы включили правильный тип для EventArgs. Однако вы могли бы довольно легко изменить public class LongClickEventBinding на что-то вроде public class CustomEventBinding<TViewType, TEventArgsType>, если бы захотели.


Что касается того, какой аргумент вы должны передать в метод IMvxCommand Execute, я думаю, это немного зависит от рассматриваемого метода, а также от того, нужна ли вам ViewModel для поддержки нескольких платформ или только для Android.

person Stuart    schedule 06.08.2012
comment
Это все еще действует в MvvmCross 3? - person Steve; 25.11.2014
comment
Я сделал - и я попробовал этот код, но по какой-то причине MvxBaseAndroidTargetBinding не разрешился. - person Steve; 26.11.2014
comment
Код для N = 28: github.com/MvvmCross/NPlus1DaysOfMvvmCross/tree /master/, который можно найти, перейдя по ссылкам на N=28 в mvvmcross.blogspot. co.uk - person Stuart; 26.11.2014
comment
Итак, этот код отличается от этого примера. В примере для этого ответа вы используете MvxBaseAndroidTargetBinding, однако его нет в примере N = 28. Вместо этого он использует MvxAndroidTargetBinding (без базы). Итак, я предполагаю, что API действительно изменился с момента этого примера? - person Steve; 26.11.2014
comment
Только хочу добавить небольшую оговорку. При написании пользовательских привязок всегда используйте слабую подписку вместо подписки +=. например: var disposable = view.WeakSubscribe‹View, View.LongClickEventArgs›(nameof(view.LongClick), ViewOnLongClick); - person zafar; 30.10.2017