1

I have a GroupBox within a parent GroupBox. Both of them have their own

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

When I press the inner GroupBox it fires its own Command and then the parent Command is also triggered.

How do I prevent that? How do I make the inner GroupBox swallow the event?

hyankov
  • 4,049
  • 1
  • 29
  • 46

1 Answers1

1

You could use another implementation of TriggerAction that supports passing the event args as a command parameter to the command, for example the EventToCommand class in the MvvmLight library:

<GroupBox Header="Outer" xmlns:mvvm="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Platform">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseLeftButtonDown">
            <i:InvokeCommandAction Command="{Binding OuterCommand}"  />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <TextBlock>...</TextBlock>
        <GroupBox Header="Inner" Grid.Row="1">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseLeftButtonDown">
                    <mvvm:EventToCommand Command="{Binding InnerCommand}" PassEventArgsToCommand="True"  />
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <TextBlock>inner...</TextBlock>
        </GroupBox>
    </Grid>
</GroupBox>

public class ViewModel
{
    public ViewModel()
    {

        OuterCommand = new RelayCommand(arg => true, (arg)=> { MessageBox.Show("outer"); });
        InnerCommand = new RelayCommand(arg => true, 
            (arg) => 
            {
                MessageBox.Show("inner");
                MouseButtonEventArgs mbea = arg as MouseButtonEventArgs;
                if (mbea != null)
                    mbea.Handled = true;
            });
    }

    public RelayCommand OuterCommand { get; }

    public RelayCommand InnerCommand { get; }
}

The ugly thing with this solution is that the view model has a dependency upon the view related MouseButtonEventArgs type though. If you don't like this you can implement your own behaviour as suggested by @adabyron here:

MVVM Passing EventArgs As Command Parameter

Then you could set the Handled property of the MouseButtonEventArgs directly in the behaviour instead of passing it along to the view model.

Community
  • 1
  • 1
mm8
  • 163,881
  • 10
  • 57
  • 88
  • that's the solution! – hyankov Jan 13 '17 at 21:05
  • If my command already looks like this `return new RelayCommand(this.OnInnerCommand);`, how would I also pass the `MouseButtonEventArgs`? Also, I think you meant to put `arg => true` in second position, if you are referring to the `CanExecute`. – hyankov Jan 13 '17 at 21:14
  • You can only pass a single command so then you would need to implement a custom behaviour or handle the MouseLeftButtonDown event of the inner GroupBox in the code-behind of the view and invoke the command of the view model from there after you have set the Handled property to true. – mm8 Jan 14 '17 at 13:39