72

我正在使用 Microsoft Expression Blend 4
我有一个浏览器 ..,

[XAML] ConnectionView“后面的空代码”

        <WebBrowser local:AttachedProperties.BrowserSource="{Binding Source}">
            <i:Interaction.Triggers>
                <i:EventTrigger>
                    <i:InvokeCommandAction Command="{Binding LoadedEvent}"/>
                </i:EventTrigger>
                <i:EventTrigger EventName="Navigated">
                    <i:InvokeCommandAction Command="{Binding NavigatedEvent}" CommandParameter="??????"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </WebBrowser>  

[C#] AttachedProperties 类

public static class AttachedProperties
    {
        public static readonly DependencyProperty BrowserSourceProperty = DependencyProperty . RegisterAttached ( "BrowserSource" , typeof ( string ) , typeof ( AttachedProperties ) , new UIPropertyMetadata ( null , BrowserSourcePropertyChanged ) );

        public static string GetBrowserSource ( DependencyObject _DependencyObject )
        {
            return ( string ) _DependencyObject . GetValue ( BrowserSourceProperty );
        }

        public static void SetBrowserSource ( DependencyObject _DependencyObject , string Value )
        {
            _DependencyObject . SetValue ( BrowserSourceProperty , Value );
        }

        public static void BrowserSourcePropertyChanged ( DependencyObject _DependencyObject , DependencyPropertyChangedEventArgs _DependencyPropertyChangedEventArgs )
        {
            WebBrowser _WebBrowser = _DependencyObject as WebBrowser;
            if ( _WebBrowser != null )
            {
                string URL = _DependencyPropertyChangedEventArgs . NewValue as string;
                _WebBrowser . Source = URL != null ? new Uri ( URL ) : null;
            }
        }
    }

[C#] 连接视图模型类

public class ConnectionViewModel : ViewModelBase
    {
            public string Source
            {
                get { return Get<string> ( "Source" ); }
                set { Set ( "Source" , value ); }
            }

            public void Execute_ExitCommand ( )
            {
                Application . Current . Shutdown ( );
            }

            public void Execute_LoadedEvent ( )
            {
                MessageBox . Show ( "___Execute_LoadedEvent___" );
                Source = ...... ;
            }

            public void Execute_NavigatedEvent ( )
            {
                MessageBox . Show ( "___Execute_NavigatedEvent___" );
            }
    }

[C#] ViewModelBase 类 在这里

最后:
使用命令绑定效果很好,并显示了 MessageBox


我的问题:发生导航事件时
如何将NavigationEventArgs作为命令参数传递?

4

13 回答 13

74

它不容易得到支持。这是一篇文章,其中包含有关如何将 EventArgs 作为命令参数传递的说明。

您可能想考虑使用MVVMLight - 它直接在命令中支持 EventArgs;你的情况看起来像这样:

 <i:Interaction.Triggers>
    <i:EventTrigger EventName="Navigated">
        <cmd:EventToCommand Command="{Binding NavigatedEvent}"
            PassEventArgsToCommand="True" />
    </i:EventTrigger>
 </i:Interaction.Triggers>
于 2011-06-01T18:01:07.630 回答
50

我试图将我的依赖项保持在最低限度,所以我自己实现了这个,而不是使用 MVVMLight 的 EventToCommand。到目前为止对我有用,但欢迎提供反馈。

xml:

<i:Interaction.Behaviors>
    <beh:EventToCommandBehavior Command="{Binding DropCommand}" Event="Drop" PassArguments="True" />
</i:Interaction.Behaviors>

视图模型:

public ActionCommand<DragEventArgs> DropCommand { get; private set; }

this.DropCommand = new ActionCommand<DragEventArgs>(OnDrop);

private void OnDrop(DragEventArgs e)
{
    // ...
}

事件到命令行为:

/// <summary>
/// Behavior that will connect an UI event to a viewmodel Command,
/// allowing the event arguments to be passed as the CommandParameter.
/// </summary>
public class EventToCommandBehavior : Behavior<FrameworkElement>
{
    private Delegate _handler;
    private EventInfo _oldEvent;

    // Event
    public string Event { get { return (string)GetValue(EventProperty); } set { SetValue(EventProperty, value); } }
    public static readonly DependencyProperty EventProperty = DependencyProperty.Register("Event", typeof(string), typeof(EventToCommandBehavior), new PropertyMetadata(null, OnEventChanged));

    // Command
    public ICommand Command { get { return (ICommand)GetValue(CommandProperty); } set { SetValue(CommandProperty, value); } }
    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(EventToCommandBehavior), new PropertyMetadata(null));

    // PassArguments (default: false)
    public bool PassArguments { get { return (bool)GetValue(PassArgumentsProperty); } set { SetValue(PassArgumentsProperty, value); } }
    public static readonly DependencyProperty PassArgumentsProperty = DependencyProperty.Register("PassArguments", typeof(bool), typeof(EventToCommandBehavior), new PropertyMetadata(false));


    private static void OnEventChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var beh = (EventToCommandBehavior)d;

        if (beh.AssociatedObject != null) // is not yet attached at initial load
            beh.AttachHandler((string)e.NewValue);
    }

    protected override void OnAttached()
    {
        AttachHandler(this.Event); // initial set
    }

    /// <summary>
    /// Attaches the handler to the event
    /// </summary>
    private void AttachHandler(string eventName)
    {
        // detach old event
        if (_oldEvent != null)
            _oldEvent.RemoveEventHandler(this.AssociatedObject, _handler);

        // attach new event
        if (!string.IsNullOrEmpty(eventName))
        {
            EventInfo ei = this.AssociatedObject.GetType().GetEvent(eventName);
            if (ei != null)
            {
                MethodInfo mi = this.GetType().GetMethod("ExecuteCommand", BindingFlags.Instance | BindingFlags.NonPublic);
                _handler = Delegate.CreateDelegate(ei.EventHandlerType, this, mi);
                ei.AddEventHandler(this.AssociatedObject, _handler);
                _oldEvent = ei; // store to detach in case the Event property changes
            }
            else
                throw new ArgumentException(string.Format("The event '{0}' was not found on type '{1}'", eventName, this.AssociatedObject.GetType().Name));
        }
    }

    /// <summary>
    /// Executes the Command
    /// </summary>
    private void ExecuteCommand(object sender, EventArgs e)
    {
        object parameter = this.PassArguments ? e : null;
        if (this.Command != null)
        {
            if (this.Command.CanExecute(parameter))
                this.Command.Execute(parameter);
        }
    }
}

动作命令:

public class ActionCommand<T> : ICommand
{
    public event EventHandler CanExecuteChanged;
    private Action<T> _action;

    public ActionCommand(Action<T> action)
    {
        _action = action;
    }

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

    public void Execute(object parameter)
    {
        if (_action != null)
        {
            var castParameter = (T)Convert.ChangeType(parameter, typeof(T));
            _action(castParameter);
        }
    }
}
于 2013-05-01T12:23:24.450 回答
20

我总是回来这里寻求答案,所以我想做一个简短的简单的答案。

有多种方法可以做到这一点:

1. 使用 WPF 工具。最简单的。

添加命名空间:

  • System.Windows.Interactivitiy
  • Microsoft.Expression.Interactions

XAML:

使用EventName调用您想要的事件,然后在 中指定您的Method姓名MethodName

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

    <wi:Interaction.Triggers>
        <wi:EventTrigger EventName="SelectionChanged">
            <ei:CallMethodAction
                TargetObject="{Binding}"
                MethodName="ShowCustomer"/>
        </wi:EventTrigger>
    </wi:Interaction.Triggers>
</Window>

代码:

public void ShowCustomer()
{
    // Do something.
}

2. 使用 MVVMLight。最难的。

安装 GalaSoft NuGet 包。

在此处输入图像描述

获取命名空间:

  • System.Windows.Interactivity
  • GalaSoft.MvvmLight.Platform

XAML:

使用EventName调用您想要的事件,然后Command在绑定中指定您的姓名。如果要传递方法的参数,请标记PassEventArgsToCommand为 true。

<Window>
    xmlns:wi="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:cmd="http://www.galasoft.ch/mvvmlight">

    <wi:Interaction.Triggers>
       <wi:EventTrigger EventName="Navigated">
           <cmd:EventToCommand Command="{Binding CommandNameHere}"
               PassEventArgsToCommand="True" />
       </wi:EventTrigger>
    </wi:Interaction.Triggers>
</Window>

代码实现委托:来源

您必须为此获取 Prism MVVM NuGet 包。

在此处输入图像描述

using Microsoft.Practices.Prism.Commands;

// With params.
public DelegateCommand<string> CommandOne { get; set; }
// Without params.
public DelegateCommand CommandTwo { get; set; }

public MainWindow()
{
    InitializeComponent();

    // Must initialize the DelegateCommands here.
    CommandOne = new DelegateCommand<string>(executeCommandOne);
    CommandTwo = new DelegateCommand(executeCommandTwo);
}

private void executeCommandOne(string param)
{
    // Do something here.
}

private void executeCommandTwo()
{
    // Do something here.
}

没有代码DelegateCommand

using GalaSoft.MvvmLight.CommandWpf

public MainWindow()
{
    InitializeComponent();

    CommandOne = new RelayCommand<string>(executeCommandOne);
    CommandTwo = new RelayCommand(executeCommandTwo);
}

public RelayCommand<string> CommandOne { get; set; }

public RelayCommand CommandTwo { get; set; }

private void executeCommandOne(string param)
{
    // Do something here.
}

private void executeCommandTwo()
{
    // Do something here.
}

3. 使用Telerik EventToCommandBehavior。这是一个选择。

您必须下载它的NuGet Package

XAML

<i:Interaction.Behaviors>
    <telerek:EventToCommandBehavior
         Command="{Binding DropCommand}"
         Event="Drop"
         PassArguments="True" />
</i:Interaction.Behaviors>

代码:

public ActionCommand<DragEventArgs> DropCommand { get; private set; }

this.DropCommand = new ActionCommand<DragEventArgs>(OnDrop);

private void OnDrop(DragEventArgs e)
{
    // Do Something
}
于 2015-02-09T13:21:42.500 回答
15

对于刚刚找到这篇文章的人,您应该知道在较新的版本中(不确定确切的版本,因为官方文档对此主题很薄弱),如果未指定 CommandParameter,则 InvokeCommandAction 的默认行为是传递它作为 CommandParameter 附加到的事件。所以原始海报的 XAML 可以简单地写成:

<i:Interaction.Triggers>
  <i:EventTrigger EventName="Navigated">
    <i:InvokeCommandAction Command="{Binding NavigatedEvent}"/>
  </i:EventTrigger>
</i:Interaction.Triggers>

然后在您的命令中,您可以接受类型的参数NavigationEventArgs(或任何适当的事件参数类型),它将自动提供。

于 2015-08-24T12:39:53.007 回答
12

我知道这是一个相当老的问题,但是我今天遇到了同样的问题,并且对引用所有 MVVMLight 并不太感兴趣,只是为了可以将事件触发器与事件参数一起使用。我过去使用过 MVVMLight,它是一个很棒的框架,但我只是不想再将它用于我的项目。

我为解决这个问题所做的工作是创建一个ULTRA最小、适应性极强的自定义触发器操作,它允许我绑定到命令并提供事件参数转换器以将参数传递给命令的 CanExecute 和 Execute 函数。您不想逐字传递事件参数,因为这会导致视图层类型被发送到视图模型层(这在 MVVM 中绝不应该发生)。

这是我想出的EventCommandExecuter类:

public class EventCommandExecuter : TriggerAction<DependencyObject>
{
    #region Constructors

    public EventCommandExecuter()
        : this(CultureInfo.CurrentCulture)
    {
    }

    public EventCommandExecuter(CultureInfo culture)
    {
        Culture = culture;
    }

    #endregion

    #region Properties

    #region Command

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof(ICommand), typeof(EventCommandExecuter), new PropertyMetadata(null));

    #endregion

    #region EventArgsConverterParameter

    public object EventArgsConverterParameter
    {
        get { return (object)GetValue(EventArgsConverterParameterProperty); }
        set { SetValue(EventArgsConverterParameterProperty, value); }
    }

    public static readonly DependencyProperty EventArgsConverterParameterProperty =
        DependencyProperty.Register("EventArgsConverterParameter", typeof(object), typeof(EventCommandExecuter), new PropertyMetadata(null));

    #endregion

    public IValueConverter EventArgsConverter { get; set; }

    public CultureInfo Culture { get; set; }

    #endregion

    protected override void Invoke(object parameter)
    {
        var cmd = Command;

        if (cmd != null)
        {
            var param = parameter;

            if (EventArgsConverter != null)
            {
                param = EventArgsConverter.Convert(parameter, typeof(object), EventArgsConverterParameter, CultureInfo.InvariantCulture);
            }

            if (cmd.CanExecute(param))
            {
                cmd.Execute(param);
            }
        }
    }
}

此类有两个依赖属性,一个允许绑定到视图模型的命令,另一个允许您在事件参数转换期间需要它时绑定事件源。如果需要,您还可以提供文化设置(它们默认为当前的 UI 文化)。

此类允许您调整事件参数,以便它们可以被您的视图模型的命令逻辑使用。但是,如果您只想逐字传递事件参数,只需不要指定事件参数转换器。

XAML 中此触发器操作的最简单用法如下:

<i:Interaction.Triggers>
    <i:EventTrigger EventName="NameChanged">
        <cmd:EventCommandExecuter Command="{Binding Path=Update, Mode=OneTime}" EventArgsConverter="{x:Static c:NameChangedArgsToStringConverter.Default}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

如果您需要访问事件源,您将绑定到事件的所有者

<i:Interaction.Triggers>
    <i:EventTrigger EventName="NameChanged">
        <cmd:EventCommandExecuter 
            Command="{Binding Path=Update, Mode=OneTime}" 
            EventArgsConverter="{x:Static c:NameChangedArgsToStringConverter.Default}"
            EventArgsConverterParameter="{Binding ElementName=SomeEventSource, Mode=OneTime}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

(这假定您将触发器附加到的 XAML 节点已分配x:Name="SomeEventSource"

此 XAML 依赖于导入一些必需的命名空间

xmlns:cmd="clr-namespace:MyProject.WPF.Commands"
xmlns:c="clr-namespace:MyProject.WPF.Converters"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

并创建一个IValueConverterNameChangedArgsToStringConverter在这种情况下称为)来处理实际的转换逻辑。对于基本转换器,我通常会创建一个默认static readonly转换器实例,然后我可以像上面所做的那样直接在 XAML 中引用它。

这个解决方案的好处是你真的只需要向任何项目添加一个类就可以使用交互框架,就像你使用InvokeCommandAction. 添加单个类(大约 75 行)应该比整个库更可取,以实现相同的结果。

笔记

这有点类似于@adabyron 的答案,但它使用事件触发器而不是行为。该解决方案还提供了事件参数转换能力,并不是@adabyron 的解决方案也无法做到这一点。我真的没有任何充分的理由为什么我更喜欢触发器而不是行为,这只是个人选择。IMO 任何一种策略都是合理的选择。

于 2014-10-07T23:03:46.080 回答
5

添加到 joshb 已经说过的内容 - 这对我来说很好。确保添加对 Microsoft.Expression.Interactions.dll 和 System.Windows.Interactivity.dll 的引用,并在您的 xaml 中执行以下操作:

    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

我最终使用了这样的东西来满足我的需要。这表明您还可以传递自定义参数:

<i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">

                <i:InvokeCommandAction Command="{Binding Path=DataContext.RowSelectedItem, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" 
                                       CommandParameter="{Binding Path=SelectedItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
            </i:EventTrigger>
</i:Interaction.Triggers>
于 2016-01-08T02:25:17.373 回答
3

我不认为你可以很容易地做到这一点- 我会从 MVVMLight 或类似InvokeCommandAction的地方看看。EventToCommand

于 2011-06-01T18:02:15.830 回答
3

如果未设置, PrismInvokeCommandAction将默认传递事件 args 。CommandParameter

https://docs.microsoft.com/en-us/previous-versions/msp-np/gg405494(v=pandp.40)#passing-eventargs-parameters-to-the-command

这是一个例子。注意使用prism:InvokeCommandAction代替i:InvokeCommandAction

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Sorting">
        <prism:InvokeCommandAction Command="{Binding SortingCommand}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

视图模型

    private DelegateCommand<EventArgs> _sortingCommand;

    public DelegateCommand<EventArgs> SortingCommand => _sortingCommand ?? (_sortingCommand = new DelegateCommand<EventArgs>(OnSortingCommand));

    private void OnSortingCommand(EventArgs obj)
    {
        //do stuff
    }

有一个新版本的Prismlibrary 文档

于 2019-04-09T13:05:21.887 回答
1

通过 Blend for Visual Studio 2013 中的行为和操作,您可以使用 InvokeCommandAction。我尝试使用 Drop 事件进行此操作,尽管 XAML 中没有指定 CommandParameter,但令我惊讶的是,Execute Action 参数包含 DragEventArgs。我认为其他事件也会发生这种情况,但尚未对其进行测试。

于 2014-03-25T03:58:12.207 回答
1

我知道这有点晚了,但是微软已经将他们的 Xaml.Behaviors 开源了,现在只需一个命名空间就可以更容易地使用交互性。

  1. 首先将 Microsoft.Xaml.Behaviors.Wpf Nuget 包添加到您的项目中。
    https://www.nuget.org/packages/Microsoft.Xaml.Behaviors.Wpf/
  2. 将 xmlns:behaviours="http://schemas.microsoft.com/xaml/behaviors" 命名空间添加到您的 xaml。

然后像这样使用它,

<Button Width="150" Style="{DynamicResource MaterialDesignRaisedDarkButton}">
   <behaviours:Interaction.Triggers>
       <behaviours:EventTrigger EventName="Click">
           <behaviours:InvokeCommandAction Command="{Binding OpenCommand}" PassEventArgsToCommand="True"/>
       </behaviours:EventTrigger>
    </behaviours:Interaction.Triggers>
    Open
</Button>

PassEventArgsToCommand="True" 应该设置为 True 并且您实现的 RelayCommand 可以将 RoutedEventArgs 或对象作为模板。如果您使用 object 作为参数类型,只需将其转换为适当的事件类型。

该命令将如下所示,

OpenCommand = new RelayCommand<object>(OnOpenClicked, (o) => { return true; });

命令方法看起来像这样,

private void OnOpenClicked(object parameter)
{
    Logger.Info(parameter?.GetType().Name);
}

“参数”将是 Routed 事件对象。

还有日志以防你好奇,

2020-12-15 11:40:36.3600|信息|MyApplication.ViewModels.MainWindowViewModel|RoutedEventArgs

如您所见,记录的 TypeName 是 RoutedEventArgs

RelayCommand 执行可以在这里找到。

为什么选择 RelayCommand

PS:您可以绑定到任何控件的任何事件。像 Window 的 Closing 事件,你会得到相应的事件。

于 2020-12-15T07:26:03.180 回答
0

我所做的是使用 InvokeCommandAction 将控件加载事件绑定到视图模型中的命令,在 Xaml 中提供控件 ax:Name 并作为 CommandParameter 传递,然后在所述加载的命令钩子视图模型处理程序中直到我需要的事件获取事件参数。

于 2013-04-17T21:47:29.837 回答
0

这是@adabyron's answer的一个版本,可以防止泄漏EventArgs抽象。

首先,修改后的EventToCommandBehavior类(现在是通用抽象类,并使用 ReSharper 代码清理进行格式化)。请注意新的GetCommandParameter虚拟方法及其默认实现:

public abstract class EventToCommandBehavior<TEventArgs> : Behavior<FrameworkElement>
    where TEventArgs : EventArgs
{
    public static readonly DependencyProperty EventProperty = DependencyProperty.Register("Event", typeof(string), typeof(EventToCommandBehavior<TEventArgs>), new PropertyMetadata(null, OnEventChanged));
    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(EventToCommandBehavior<TEventArgs>), new PropertyMetadata(null));
    public static readonly DependencyProperty PassArgumentsProperty = DependencyProperty.Register("PassArguments", typeof(bool), typeof(EventToCommandBehavior<TEventArgs>), new PropertyMetadata(false));
    private Delegate _handler;
    private EventInfo _oldEvent;

    public string Event
    {
        get { return (string)GetValue(EventProperty); }
        set { SetValue(EventProperty, value); }
    }

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public bool PassArguments
    {
        get { return (bool)GetValue(PassArgumentsProperty); }
        set { SetValue(PassArgumentsProperty, value); }
    }

    protected override void OnAttached()
    {
        AttachHandler(Event);
    }

    protected virtual object GetCommandParameter(TEventArgs e)
    {
        return e;
    }

    private void AttachHandler(string eventName)
    {
        _oldEvent?.RemoveEventHandler(AssociatedObject, _handler);

        if (string.IsNullOrEmpty(eventName))
        {
            return;
        }

        EventInfo eventInfo = AssociatedObject.GetType().GetEvent(eventName);

        if (eventInfo != null)
        {
            MethodInfo methodInfo = typeof(EventToCommandBehavior<TEventArgs>).GetMethod("ExecuteCommand", BindingFlags.Instance | BindingFlags.NonPublic);

            _handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo);
            eventInfo.AddEventHandler(AssociatedObject, _handler);
            _oldEvent = eventInfo;
        }
        else
        {
            throw new ArgumentException($"The event '{eventName}' was not found on type '{AssociatedObject.GetType().FullName}'.");
        }
    }

    private static void OnEventChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var behavior = (EventToCommandBehavior<TEventArgs>)d;

        if (behavior.AssociatedObject != null)
        {
            behavior.AttachHandler((string)e.NewValue);
        }
    }

    // ReSharper disable once UnusedMember.Local
    // ReSharper disable once UnusedParameter.Local
    private void ExecuteCommand(object sender, TEventArgs e)
    {
        object parameter = PassArguments ? GetCommandParameter(e) : null;

        if (Command?.CanExecute(parameter) == true)
        {
            Command.Execute(parameter);
        }
    }
}

接下来是一个隐藏的示例派生类DragCompletedEventArgs。一些人表示担心将EventArgs抽象泄漏到他们的视图模型程序集中。为了防止这种情况,我创建了一个代表我们关心的价值观的界面。接口可以存在于视图模型程序集中,私有实现在 UI 程序集中:

// UI assembly
public class DragCompletedBehavior : EventToCommandBehavior<DragCompletedEventArgs>
{
    protected override object GetCommandParameter(DragCompletedEventArgs e)
    {
        return new DragCompletedArgs(e);
    }

    private class DragCompletedArgs : IDragCompletedArgs
    {
        public DragCompletedArgs(DragCompletedEventArgs e)
        {
            Canceled = e.Canceled;
            HorizontalChange = e.HorizontalChange;
            VerticalChange = e.VerticalChange;
        }

        public bool Canceled { get; }
        public double HorizontalChange { get; }
        public double VerticalChange { get; }
    }
}

// View model assembly
public interface IDragCompletedArgs
{
    bool Canceled { get; }
    double HorizontalChange { get; }
    double VerticalChange { get; }
}

将命令参数转换为IDragCompletedArgs,类似于@adabyron 的答案。

于 2016-06-21T04:03:57.380 回答
0

作为@Mike Fuchs 答案的改编,这里有一个更小的解决方案。我正在使用Fody.AutoDependencyPropertyMarker来减少一些样板。

班上

public class EventCommand : TriggerAction<DependencyObject>
{
    [AutoDependencyProperty]
    public ICommand Command { get; set; }

    protected override void Invoke(object parameter)
    {
        if (Command != null)
        {
            if (Command.CanExecute(parameter))
            {
                Command.Execute(parameter);
            }
        }
    }
}

事件参数

public class VisibleBoundsArgs : EventArgs
{
    public Rect VisibleVounds { get; }

    public VisibleBoundsArgs(Rect visibleBounds)
    {
        VisibleVounds = visibleBounds;
    }
}

XAML

<local:ZoomableImage>
   <i:Interaction.Triggers>
      <i:EventTrigger EventName="VisibleBoundsChanged" >
         <local:EventCommand Command="{Binding VisibleBoundsChanged}" />
      </i:EventTrigger>
   </i:Interaction.Triggers>
</local:ZoomableImage>

视图模型

public ICommand VisibleBoundsChanged => _visibleBoundsChanged ??
                                        (_visibleBoundsChanged = new RelayCommand(obj => SetVisibleBounds(((VisibleBoundsArgs)obj).VisibleVounds)));
于 2018-03-22T11:26:10.530 回答