Home > Net >  Is it possible to use invoke a command using an Microsoft.Xaml.Behaviors.EventTrigger with attached
Is it possible to use invoke a command using an Microsoft.Xaml.Behaviors.EventTrigger with attached

Time:10-27

I am trying to use an attached event to invoke an ICommand.

I am using the Microsoft.Toolkit.Mvvm NuGet package, along with the Microsoft.Xaml.Behaviors.Wpf Nuget package.

I have had success starting a Storyboard using the <BeginStoryBoardAction /> within the <FOO.Triggers /> by defining an <EventTrigger /> and setting the RoutedEvent equal to the name of the attached event in question.

However, to my knowledge, there exists no way to invoke an ICommand using anything provided within the <EventTrigger />. By which I mean, there is nothing that I can use within the body of the <EventTriggers.Actions /> block (similar to <Behaviors.InvokeCommandAction />) which will result in the ICommand being invoked.

In compliance with the Minimal, Complete and Verifiable example, to demonstrate what I am trying to achieve, you can reference the project on GitHub - https://github.com/AbbottWC/MCVE_AttachedEventFailure.

Or

  • Open Visual Studio. Create a WPF Application (Targeting .Net Core 3.1)

  • Tools -> NuGet Package Manager -> Manage Packages for this solution

  • Add the Microsoft.Toolkit.Mvvm (for the RelayCommand class) and the Microsoft.Xaml.Behaviors.Wpf packages.

  • In the App.Xaml.cs

     private RelayCommand testCommand = new RelayCommand(( ) => MessageBox.Show("Event Captured!", "Success!"));
     public RelayCommand TestCommand => testCommand;
    
  • In the MainWindow.xaml

  • Define the namespace xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

  • Rename local to l

  • Add the following to the body of the XAML before the closing </Window> tag:

<i:Interaction.Triggers>
    <!--This will work, and is present only to prove the problem lies not with the Command or how it is being accessed.-->
    <i:EventTrigger EventName="MouseEnter">
        <i:EventTrigger.Actions>
            <i:InvokeCommandAction Command="{Binding TestCommand, Source={x:Static l:App.Current}}" />
        </i:EventTrigger.Actions>
    </i:EventTrigger>
    <!--This will not work, and is meant to provide an example of the problem.-->
    <i:EventTrigger EventName="Mouse.MouseEnter">
        <i:EventTrigger.Actions>
            <i:InvokeCommandAction Command="{Binding TestCommand, Source={x:Static l:App.Current}}" />
        </i:EventTrigger.Actions>
    </i:EventTrigger>
</i:Interaction.Triggers>

So to restate my question, is what I am trying to achieve here possible? Is it just not possible to use an attached event in this way?

Thanks.

CodePudding user response:

From what I understand, the EventTrigger can only listen to events that the source object "owns". So to answer your question, this is not possible using the EventTrigger class.

If you look at the source, when you pass Mouse.MouseEnter, it tries to get that event from the target type. Also, since you did not specify the target, it defaults to the AssociatedObject, which is Window in your case.

Type targetType = obj.GetType();
EventInfo eventInfo = targetType.GetEvent(eventName);

Now the problem I find, is if it cannot find the event, it only throws an exception when the source object is not null, and in your case you haven't specified one, so it silently fails. Not sure why the designers made it this way.

Now, I did find this blog post, which describes exactly how you can workaround this problem: https://sergecalderara.wordpress.com/2012/08/23/how-to-attached-an-mvvm-eventtocommand-to-an-attached-event/

Basically, you inherit from EventTriggerBase<T> and in the OnAttached method you need to call AddHandler on your AssociatedObject to add the event.

  • Related