Свяжите пользовательский метод с параметрами в ViewModel - PullRequest
0 голосов
/ 29 октября 2018

Я создаю приложение UWP MVVM. Я создал ViewModel и View, я делаю его DataContext, и все отлично работает с привязками.

Мне удалось вызвать метод без параметров. Это мой код XAML в представлении:

<Button VerticalAlignment="Top" HorizontalAlignment="Right" Margin="50" Width="50" Height="50" Background="Transparent" BorderBrush="Transparent" Content="OK" FontSize="32" FontWeight="Bold" Foreground="White" Click="{x:Bind Path=ViewModel.ButtonMainClick, Mode=OneWay}"/> 

В ViewModel у меня так:

public void ButtonMainClick()
{
    // TO DO
}

И это прекрасно работает.

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

Есть идеи?

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

Обработчики событий, использующие x:Bind, не могут принимать произвольные аргументы.

Одно простое решение - просто предоставить другой метод, который сделает вызов за вас. У метода, привязанного к событию Click, нет параметров, но он просто вызывает метод, который нужно выполнить.

[Редактировать] Если вам нужно передать контекст из элемента управления, который сгенерировал событие, вы можете сделать это, добавив подпись события и получив доступ к sender s DataContext и приведя ваш тип ViewModel.

void FuncThatDoesSomething(T1 arg1, T2 arg2,...)
{
  // do it
}

// function has to match the event handler signature 
void FuncThatIsBoundInXaml(object sender, RoutedEventArgs e)
{
  var vm = sender.DataContext as YourViewModelType;
  // call method with required args
  FuncThatDoesSomething(vm.SomeProperty, 42);
}
0 голосов
/ 29 октября 2018

Предполагая, что привязка UWP и WPF работает одинаково, вы должны привязать свои кнопки к свойствам типа ICommand в вашем ViewModel. Обычная реализация ICommand - это RelayCommand, которая может выглядеть следующим образом:

 public class RelayCommand : ICommand
    {
        private readonly Action _targetExecuteMethod;
        private readonly Func<bool> _targetCanExecuteMethod;
        public RelayCommand(Action executeMethod) => _targetExecuteMethod = executeMethod;

        public RelayCommand(Action executeMethod, Func<bool> canExecuteMethod)
        {
            _targetExecuteMethod = executeMethod;
            _targetCanExecuteMethod = canExecuteMethod;
        }
        public void RaiseCanExecuteChanged() => CanExecuteChanged(this, EventArgs.Empty);
        bool ICommand.CanExecute(object parameter) => _targetCanExecuteMethod?.Invoke() ?? _targetExecuteMethod != null;
        public event EventHandler CanExecuteChanged = delegate { };
        void ICommand.Execute(object parameter) => _targetExecuteMethod?.Invoke();
    }
    public class RelayCommand<T> : ICommand
    {
        private readonly Action<T> _targetExecuteMethod;
        private readonly Func<T, bool> _targetCanExecuteMethod;
        public RelayCommand(Action<T> executeMethod) => _targetExecuteMethod = executeMethod;
        public RelayCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
        {
            _targetExecuteMethod = executeMethod;
            _targetCanExecuteMethod = canExecuteMethod;
        }
        public void RaiseCanExecuteChanged() => CanExecuteChanged(this, EventArgs.Empty);
        bool ICommand.CanExecute(object parameter)
        {
            if (_targetCanExecuteMethod != null)
            {
                var tparm = (T)parameter;
                return _targetCanExecuteMethod(tparm);
            }
            return _targetExecuteMethod != null;
        }
        public event EventHandler CanExecuteChanged = delegate { };
        void ICommand.Execute(object parameter) => _targetExecuteMethod?.Invoke((T)parameter);
    }

Для View и ViewModel взгляните на этот пример: https://stackoverflow.com/a/53045098/9889260

Если вы хотите использовать параметры. Вы просто используете универсальный RelayCommand<T>, где T - это тип, который вы хотите передать в качестве параметра, а также укажите в качестве параметра свои Excecute и CanExcecute (если есть) методы T.

С уважением, MIS

...