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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With