WPF ICommand"事件绑定" - 获取EventArgs

时间:2017-10-27 13:07:55

标签: c# wpf mvvm

问题:我有一个WPF项目,我想使用MVVM-pattern。我想使用ICommand来抽象事件。但问题是我无法恢复我的EventArgs,因为它是"背后"命令(例如OnDrop路径)。

信息: ICommand用于抽象事件,因为命令可以多次使用。命令更集中于背后的逻辑(MVVM-Pattern)。

我正在使用System.Windows.Interactivity和中继命令。

RelayCommand.cs

public class RelayCommand : ICommand
{
    private readonly Predicate<object> _canExecute;
    private readonly Action<object> _execute;

    public RelayCommand(Predicate<object> canExecute, Action<object> execute)
    {
        _canExecute = canExecute;
        _execute = execute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add => CommandManager.RequerySuggested += value;
        remove => CommandManager.RequerySuggested -= value;
    }
}

我尝试了以下解决方案:

1。具有依赖对象的行为

https://gayotfow.wordpress.com/2014/04/27/to-implement-drag-and-drop-in-mvvm-without-much-experience-in-wpf-you-can-refer-to-5-steps-i-will-outline-these/

我无法取回我的Event Args。

2。具有关联对象和OnAttached的行为

https://wpftutorial.net/Behaviors.html

我遇到了同样的问题,无法取回我的EventArgs。

3。方法绑定

MainView.xaml

 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
 xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"

 <i:EventTrigger EventName="Drop">
    <ei:CallMethodAction TargetObject="{Binding}" MethodName="OnRectangleDrop"/>
 </i:EventTrigger>

这对我有用,但是这里的问题是,在XAML或代码中,WPF不会更改名称,方法名称已更改。

问题: 如何在不使用框架或库的情况下以有效的方式让我的 EventArgs 退出我的命令?

2 个答案:

答案 0 :(得分:1)

从事件开始。一旦获得了与事件一起使用的代码,它通常可以重构为可重用的附加行为。

E.g。这是一个分配命令,它接收来自拖放项目的传递字符串。

public static partial class Behaviors
{
    public static ICommand GetDrop(DependencyObject obj) => (ICommand)obj.GetValue(DropProperty);
    public static void SetDrop(DependencyObject obj, ICommand value) => obj.SetValue(DropProperty, value);

    public static readonly DependencyProperty DropProperty =
        DependencyProperty.RegisterAttached("Drop", typeof(ICommand), typeof(Behaviors), new PropertyMetadata(null, (d, e) =>
        {
            var element = d as UIElement;
            element.Drop += (s, a) =>
            {
                if (a.Data.GetDataPresent(DataFormats.StringFormat))
                {
                    var command = (ICommand)e.NewValue;
                    var data = (string)a.Data.GetData(DataFormats.StringFormat);
                    if (command.CanExecute(data))
                        command.Execute(data);
                }
            };
        }));
}

我想它会与您的文件路径一起使用,只需在绑定中使用它:

<SomeUIElement AllowDrop="True"
               Background="Transparent"
               local:Behaviors.Drop="{Binding SomeCommand}" />

,其中

SomeCommand = new RelayCommand(o => true, o => MessageBox.Show($"File {o}"));

另一点是开始拖动。您还可以使用附加行为,例如传递文本的一个(可以是绑定):

public static partial class Behaviors
{
    public static string GetDrag(DependencyObject obj) => (string)obj.GetValue(DragProperty);
    public static void SetDrag(DependencyObject obj, string value) => obj.SetValue(DragProperty, value);

    public static readonly DependencyProperty DragProperty =
        DependencyProperty.RegisterAttached("Drag", typeof(string), typeof(Behaviors), new PropertyMetadata(null, (d, e) =>
        {
            var element = d as UIElement;
            element.MouseMove += (s, a) =>
            {
                if (a.LeftButton == MouseButtonState.Pressed)
                    DragDrop.DoDragDrop(element, e.NewValue, DragDropEffects.Copy);
            };
        }));
}

用法是:

<Something local:Behaviors.Drag="text" ... />

答案 1 :(得分:0)

  

如何在不使用框架或库的情况下以有效的方式让我的EventArgs退出我的命令?

System.Windows.Interactivity.dllMicrosoft.Expressions.Interactions.dll中没有类将EventArgs作为命令参数传递给命令。

MvvmLight中有一个EventToCommand课程,您可以使用http://blog.galasoft.ch/posts/2014/01/using-the-eventargsconverter-in-mvvm-light-and-why-is-there-no-eventtocommand-in-the-windows-8-1-version/

另一种选择是实现自己的自定义TriggerAction<FrameworkElement>。您可以查看MvvmLight实现:https://github.com/paulcbetts/mvvmlight/blob/dce4e748c538ed4e5f5a0ebbfee0f54856f52dc6/V3/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Extras%20(NET35)/Command/EventToCommand.cs

或者您可以在视图的代码隐藏中处理Drop事件,只需按照@Evk的建议从事件处理程序调用命令:

private void OnDrop(object sender, DragEventArgs e)
{
    var viewModel = DataContext as YourViewModelType;
    if (viewModel != null)
        viewModel.OnRectangleDrop.Execute(e);
}

当然,您可以从DragEventArgs中提取任何值,并将此值传递给命令。