Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Click Event not fired in WPF Datagrid in unselected row

I have a DataGrid (WPF 4) like this:

<DataGrid   Margin="0,0,0,5" VerticalAlignment="Top" Height="192" 
                            BorderBrush="#aaa" Background="White" 
                            HorizontalAlignment="Left" 
                            ItemsSource="{Binding Namen, Mode=OneWay}" 
                            ScrollViewer.VerticalScrollBarVisibility="Visible"
                            AutoGenerateColumns="False" 
                            ColumnHeaderHeight="24" 
                            SelectionChanged="DataGridAuslaendischeAlteNamen_SelectionChanged">
                    <DataGrid.Columns>
                        <DataGridTextColumn Width="*" Header="Namenseintrag" Binding="{Binding DisplayName, Mode=OneWay}" />
                        <DataGridTextColumn Width="75" Header="gültig von" Binding="{Binding GueltigAb, StringFormat=d, Mode=OneWay}" />
                        <DataGridTextColumn Width="75" Header="gültig bis" Binding="{Binding GueltigBis, StringFormat=d., Mode=OneWay}" />
                        <DataGridTemplateColumn Width="20" IsReadOnly="True">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <Button Style="{DynamicResource CaratRemoveButton}" 
                                            Click="Button_Click" CommandParameter="{Binding}" 
                                            PreviewMouseDown="Button_PreviewMouseDown" 
                                            />
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                </DataGrid.Columns>
                </DataGrid>

The issue I experience is, that a button of the DataGridTemplateColumn does not fire the click-event, if its row is not selected. So I have to click a button twice, one time to select its row and then to raise the click event. I read about similiar problems with checkbox-columns, but there the suggestion was obviously to use a template column. I tested to use the PreviewMouseDown-Event of the button, which works, but is not what I want, since then the button does not follow its usual grpahical click behaviour.

What am I missing here? How can I get that click event by just clicking once, regardless of whether the row was selected or not?

like image 788
Andreas H. Avatar asked Dec 08 '11 13:12

Andreas H.


1 Answers

basically, you have no solution except using a TemplateColumn and managing every single mouseEvent yourself.

Explanation :

click = mouseDown + MouseUp, right. so your button needs to be able to get the mouseDown + the MouseUp event.

BUT...

by default, wpf's DataGrid has its rows handling the MouseDown Event so as to select the one you do the mouseDown on (to confirm: mouseDown on a cell and hold the mouseButton down, you'll see that the row is selected BEFORE you release the button).

So basically, the MouseDownEvent is Handled before it reaches the button, preventing you to be able to use the Click event on the button

Microsoft tell us in their doc that in such cases, we should turn to the Preview kind of event, but this cannot apply to click event since there is no way you could have a previewClickEvent

So the only solution I can see for you is to listen to both PreviewMouseDown and PreviewMouseUp on your button and simulating a click from them yourself

something a bit like this :

Button myButton = new Button();
bool mouseLeftButtonDownOnMyButton;
myButton.PreviewMouseLeftButtonDown += (s, e) => { mouseLeftButtonDownOnMyButton = true; };
myButton.PreviewMouseLeftButtonUp += (s, e) => {
    if (mouseLeftButtonDownOnMyButton)
        myButton.RaiseEvent( new RoutedEventArgs(Button.ClickEvent,myButton));
        mouseLeftButtonDownOnMyButton = false;
    };
myButton.Click += myButtonCLickHandler;

(of course, you'd need to translate that in your xaml template)

NB: this is not complete, you should also take care of the cases when the user does a mouseDown on the button but moves the mouse out of the button before doing the mouseup (in wich case you should reset the mouseLeftButtonDownOnMyButton flag). The best way would probably be to reset the flag in a general mouseUpEvent (on the window level for instance) instead of in the button's one.

Edit: the above code lets you manage the Click event as well and have only one code for both the real and simulated click events (hence the use of the RaiseEvent method), but if you don't need this, you could directly put your code in the PreviewMouseUp section as well of course.

like image 66
David Avatar answered Oct 06 '22 15:10

David