Search code examples
wpfcommandinteractioneventtrigger

Strange Interaction Trigger Behavior


I have two Datagrids. You can switch Items between it by Doubleclinking on one or more rows. The doubleclick event is handled by a command sending the list of selected items to the viewmodel.

So i have Datagrid 1 with Trigger:

<i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDoubleClick" SourceName="lstProducts">
                    <cmd:EventToCommand Command="{Binding Path=Add}" 
                                        CommandParameter="{Binding ElementName=lstProducts, Path=SelectedItems}" />
                </i:EventTrigger>
</i:Interaction.Triggers>

And Datagrid 2 Trigger:

<i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDoubleClick"  SourceName="dgProducts">
                    <cmd:EventToCommand Command="{Binding Path=Remove}"
                                    CommandParameter="{Binding ElementName=dgProducts,Path=SelectedItems}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>

Everytime I double Click on a Datagrid it calls the Add AND Remove Command. But when I set a debug Point inside both delegate Command Methods it only enters one. If I set it in only one, no matter which one, it will enter it.

For example having clicked in the first datagrid it should call the Add Command, so it stops at the breakpoint. But also when I set the breakpoint to remove, but not on both.

I tried to apply the SourceName and even the SourceObject but it wont help..

Maybe anyone knows how to fix this?


Solution

  • I think I have your scenario working properly:

    public partial class MainWindow : Window
    {
        public ObservableCollection<Product> Added { get; set; }
    
        public ObservableCollection<Product> Available { get; set; }
    
        public ICommand Add { get; set; }
    
        public ICommand Remove { get; set; }
    
        public MainWindow()
        {
            Added = new ObservableCollection<Product>();
            Available = new ObservableCollection<Product>();
            Available.Add(new Product { Id = 1 });
            Available.Add(new Product { Id = 2 });
            Available.Add(new Product { Id = 3 });
            Available.Add(new Product { Id = 4 });
            Available.Add(new Product { Id = 5 });
            InitializeComponent();
            DataContext = this;
    
            Add = new RelayCommand<IEnumerable>(x =>
            {
                foreach (Product item in x.Cast<Product>().ToArray())
                {
                    Added.Add(item);
                    Available.Remove(item);
                }
    
                Console.WriteLine("add");
            });
    
            Remove = new RelayCommand<IEnumerable>(x =>
            {
                foreach (Product item in x.Cast<Product>().ToArray())
                {
                    Added.Remove(item);
                    Available.Add(item);
                }
                Console.WriteLine("remove");
            });
        }
    }
    
    public class Product
    {
        public int Id { get; set; }
    }
    

    and xaml:

    <StackPanel >
    
        <DataGrid ItemsSource="{Binding Available}" SelectionUnit="FullRow" x:Name="lstProducts">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDoubleClick" SourceName="lstProducts">
                    <cmd:EventToCommand Command="{Binding Path=Add}"
                                        CommandParameter="{Binding ElementName=lstProducts, Path=SelectedItems}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
    
        </DataGrid>
    
        <DataGrid ItemsSource="{Binding Added}" SelectionUnit="FullRow" x:Name="lstProductsAdded" >
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseDoubleClick" SourceName="lstProductsAdded">
                    <cmd:EventToCommand Command="{Binding Path=Remove}"
                                        CommandParameter="{Binding ElementName=lstProductsAdded, Path=SelectedItems}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
    
        </DataGrid>
    
    </StackPanel>
    

    Is this what you did/wanted to do? In my sample just one command is executed. And you can see it in Output window.

    I figured out how to break this code to reproduce your behavior: in both i:EventTrigger tags you have the same SoruceName so you bind to single grid.