【问题标题】:Bind custom method with parameters in ViewModel在 ViewModel 中将自定义方法与参数绑定
【发布时间】:2018-10-29 13:05:22
【问题描述】:

我正在创建一个 UWP MVVM 应用。我已经创建了 ViewModel 和 View,并将其设为 DataContext,并且使用绑定一切正常。

我能够调用没有参数的方法。这是我在 View 中的 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。但是我不确定如何使用它并传递一些参数。

有什么想法吗?

【问题讨论】:

  • 参数值是否始终相同,还是依赖于其他值/控件?
  • 参数来自我定义的枚举。
  • 但是你总是传递相同的值吗?
  • 是的,像这样:ButtonMainClickEvent?.Invoke(Model.ControlTypeEnum);

标签: c# mvvm parameters uwp routed-events


【解决方案1】:

假设 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&lt;T&gt;,其中T 是您要作为参数传递的类型,并且还给您的Excecute 和CanExcecute(如果有的话)方法T 作为您的参数。

亲切的问候, 误会

【讨论】:

    【解决方案2】:

    使用x:Bind 的事件处理程序不能接受任意参数。

    一个简单的解决方案就是公开另一种为您调用的方法。 Click事件绑定的方法没有参数,只是调用了你需要执行的方法。

    [编辑] 如果您需要从生成事件的控件传递上下文,您可以通过添加事件签名并访问 sender 的 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);
    }
    

    【讨论】:

    • 但是 ListView 中使用此事件的每个项目在该 Enum 中具有不同的值。
    • 因此上面的问题是关于它是否恒定:-)。控件有什么可以让您知道要传递哪个枚举值的吗?
    • 嗯,每个项目都有模型,并且在该模型中,EnumType 是根据其他一些参数计算的。每个项目的模型本身都有该信息。 :)
    • 按钮是否包含在您的 ListViewItem 中?也许,你发一个minimal reproducible example,那么,我们可以为你提供更多帮助。
    猜你喜欢
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-20
    • 2018-01-16
    • 2018-10-13
    • 2014-01-18
    相关资源
    最近更新 更多