Program Club

MVVM이 EventArgs를 명령 매개 변수로 전달

proclub 2020. 12. 6. 22:14
반응형

MVVM이 EventArgs를 명령 매개 변수로 전달


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 #] ConnectionViewModel 클래스

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가 표시됩니다.


내 질문 : Navigated Event가 발생할 때 NavigationEventArgs 를 명령 매개 변수
로 전달하는 방법 은 무엇입니까?


쉽게 지원되지 않습니다. 다음은 EventArgs를 명령 매개 변수로 전달하는 방법에 대한 지침 이 포함 된 문서 입니다.

MVVMLight 사용을 살펴보고 싶을 수도 있습니다. 명령에서 EventArgs를 직접 지원합니다. 귀하의 상황은 다음과 같습니다.

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

나는 내 의존성을 최소한으로 유지하려고 노력하므로 MVVMLight의 EventToCommand를 사용하는 대신 이것을 직접 구현했습니다. 지금까지 저에게 효과적이지만 피드백을 환영합니다.

Xaml :

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

ViewModel :

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

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

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

EventToCommandBehavior :

/// <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);
        }
    }
}

ActionCommand :

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);
        }
    }
}

나는 항상 대답을 위해 여기로 돌아 왔기 때문에 짧고 간단한 것을 만들고 싶었습니다.

이를 수행하는 방법에는 여러 가지가 있습니다.

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바인딩에서 이름 을 지정하십시오 . 메소드의 인수를 전달하려면 PassEventArgsToCommandtrue로 표시하십시오 .

<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
}

나는 이것이 상당히 오래된 질문이라는 것을 알고 있지만 오늘 같은 문제가 발생했으며 이벤트 인수와 함께 이벤트 트리거를 사용할 수 있도록 모든 MVVMLight를 참조하는 데별로 관심이 없었습니다. 나는 과거에 MVVMLight를 사용했고 그것은 훌륭한 프레임 워크이지만, 더 이상 내 프로젝트에 사용하고 싶지 않습니다.

내가이 문제를 해결하려면 한 것은 생성했다 ULTRA 최소한의, 극단적으로 나 명령에 결합 인수는 명령의 CanExecute에 인수를 전달하고 기능을 실행하기 위해 컨버터 이벤트를 제공 할 수 있도록 할 적응할 수있는 사용자 정의 트리거 동작을. 이벤트 인수를 그대로 전달하지 않으려면 뷰 레이어 유형이 뷰 모델 레이어로 전송됩니다 (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"

그리고 실제 변환 논리를 처리하기 위해 (이 경우 IValueConverter호출 됨) 생성 NameChangedArgsToStringConverter. 기본 변환기의 경우 일반적으로 기본 static readonly변환기 인스턴스를 만듭니다. 그런 다음 위에서 한 것처럼 XAML에서 직접 참조 할 수 있습니다.

이 솔루션의 이점은 .NET에서 사용하는 것과 동일한 방식으로 상호 작용 프레임 워크를 사용하기 위해 모든 프로젝트에 단일 클래스 만 추가하면된다는 것입니다 InvokeCommandAction. 동일한 결과를 얻으려면 전체 라이브러리보다 단일 클래스 (약 75 줄)를 추가하는 것이 훨씬 더 좋습니다.

노트

이것은 @adabyron의 답변과 다소 유사하지만 동작 대신 이벤트 트리거를 사용합니다. 이 솔루션은 또한 이벤트 인수 변환 기능을 제공하지만 @adabyron의 솔루션이이를 수행 할 수도 없습니다. 나는 행동보다 방아쇠를 선호하는 이유가 정말로 없다. 단지 개인적인 선택 일 뿐이다. IMO 어느 쪽의 전략이든 합리적인 선택입니다.


이 게시물을 찾는 사람들에게는 최신 버전에서 (이 주제에 대한 공식 문서가 슬림하기 때문에 정확한 버전은 확실하지 않음) InvokeCommandAction의 기본 동작은 CommandParameter가 지정되지 않은 경우 다음의 인수를 전달하는 것임을 알아야합니다. CommandParameter로 첨부 된 이벤트입니다. 따라서 원본 포스터의 XAML은 다음과 같이 간단하게 작성할 수 있습니다.

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

그런 다음 명령에서 유형의 매개 변수 NavigationEventArgs(또는 적절한 이벤트 인수 유형)를 수락 하면 자동으로 제공됩니다.


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>

나는 당신이 쉽게 할 수 있다고 생각하지 않습니다 InvokeCommandAction-나는 EventToCommandMVVMLight 또는 유사에서 살펴볼 것입니다.


Blend for Visual Studio 2013의 동작 및 작업을 사용하면 InvokeCommandAction을 사용할 수 있습니다. Drop 이벤트를 사용하여이 작업을 시도했지만 XAML에 CommandParameter가 지정되지 않았지만 놀랍게도 Execute Action 매개 변수에 DragEventArgs가 포함되었습니다. 나는 이것이 다른 이벤트에서 발생할 것이라고 생각하지만 테스트하지는 않았습니다.


가 설정되지 않은 InvokeCommandAction경우 Prism 은 기본적으로 이벤트 인수를 전달합니다 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>

내가하는 일은 InvokeCommandAction을 사용하여 컨트롤로드 이벤트를 뷰 모델의 명령에 바인딩하고 컨트롤 ax : Name을 Xaml에 제공하고 CommandParameter로 전달한 다음로드 된 명령 후크 뷰 모델 핸들러에서 필요한 이벤트까지 전달하는 것입니다. 이벤트 인수를 가져옵니다.


다음은 누출 된 EventArgs추상화 를 방지하는 @adabyron의 답변 버전입니다 .

첫째, 수정 된 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의 대답과 유사하게 명령 매개 변수를로 캐스팅하십시오 .


@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);
            }
        }
    }
}

EventArgs

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>

ViewModel

public ICommand VisibleBoundsChanged => _visibleBoundsChanged ??
                                        (_visibleBoundsChanged = new RelayCommand(obj => SetVisibleBounds(((VisibleBoundsArgs)obj).VisibleVounds)));

참고 URL : https://stackoverflow.com/questions/6205472/mvvm-passing-eventargs-as-command-parameter

반응형