72

私はMicrosoftExpressionBlend 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クラス

最後に:
コマンドとのバインドはうまく機能し、メッセージボックスが表示されます


私の質問:ナビゲートされたイベントが発生したときにコマンドパラメーターとしてNavigationEventArgs
を渡す方法は?

4

13 に答える 13

74

簡単にはサポートされません。これは、 EventArgsをコマンドパラメーターとして渡す方法についての説明が記載された記事です。

MVVMLightの使用を検討することをお勧めします。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を使用する代わりに、これを自分で実装しました。これまでのところうまくいきますが、フィードバックは大歓迎です。

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);
        }
    }
}
于 2013-05-01T12:23:24.450 に答える
20

私はいつも答えを求めてここに戻ってきたので、簡単な短いものを作りたかったのです。

これを行うには複数の方法があります。

1.WPFツールを使用します。最も簡単です。

名前空間の追加:

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

XAML:

を使用して目的のイベントを呼び出し、で名前をEventName指定します。MethodMethodName

<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を使用します。最も困難。

GalaSoftNuGetパッケージをインストールします。

ここに画像の説明を入力してください

名前空間を取得します。

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

コード実装デリゲート:ソース

このためには、PrismMVVMNuGetパッケージを入手する必要があります。

ここに画像の説明を入力してください

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.TelerikEventToCommandBehaviorを使用します。それはオプションです。

NuGetパッケージをダウンロードする必要があります。

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を使用しましたが、これは優れたフレームワークですが、プロジェクトで使用したくありません。

この問題を解決するために私が行ったのは、コマンドにバインドし、コマンドの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);
            }
        }
    }
}

このクラスには2つの依存関係プロパティがあります。1つはビューモデルのコマンドへのバインドを許可し、もう1つはイベント引数の変換中に必要な場合にイベントのソースをバインドできるようにします。必要に応じてカルチャ設定を提供することもできます(デフォルトでは現在の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で直接参照できます。

このソリューションの利点は、インタラクションフレームワークを使用する場合とほぼ同じ方法で、プロジェクトに1つのクラスを追加するだけでよいことです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

私はあなたがそれを簡単に行うことができるとは思いませんInvokeCommandAction-私はEventToCommandMVVMLightまたは同様のものから見ていきます。

于 2011-06-01T18:02:15.830 に答える
3

が設定されていない場合、 PrismInvokeCommandActionはデフォルトでイベント引数を渡します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>

ViewModel

    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が指定されていませんでしたが、驚いたことに、ExecuteActionパラメーターにDragEventArgsが含まれていました。これは他のイベントでも発生すると思いますが、テストはしていません。

于 2014-03-25T03:58:12.207 に答える
1

少し遅れていることは承知していますが、MicrosoftはXaml.Behaviorsをオープンソースにし、1つの名前空間だけで対話機能を使用するのがはるかに簡単になりました。

  1. まず、Microsoft.Xaml.Behaviors.WpfNugetパッケージをプロジェクトに追加します。
    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またはオブジェクトをテンプレートとして使用できます。パラメータタイプとしてオブジェクトを使用している場合は、適切なイベントタイプにキャストするだけです。

コマンドは次のようになります。

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

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

次に、を非表示にする派生クラスの例DragCompletedEventArgsEventArgs一部の人々は、抽象化をビューモデルアセンブリにリークすることに懸念を表明しました。これを防ぐために、気になる値を表すインターフェイスを作成しました。インターフェイスは、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);
            }
        }
    }
}

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)));
于 2018-03-22T11:26:10.530 に答える