C# 单击未选中行中WPF Datagrid中未激发的事件
我有一个数据网格(WPF 4),如下所示:C# 单击未选中行中WPF Datagrid中未激发的事件,c#,wpf,wpfdatagrid,C#,Wpf,Wpfdatagrid,我有一个数据网格(WPF 4),如下所示: <DataGrid Margin="0,0,0,5" VerticalAlignment="Top" Height="192" BorderBrush="#aaa" Background="White" HorizontalAlignment="Left" ItemsSo
<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>
我遇到的问题是,DataGridTemplateColumn
的按钮如果未选中其行,则不会触发click事件。因此,我必须单击按钮两次,一次选择其行,然后引发单击事件。
我读到了有关复选框列的类似问题,但显然建议使用模板列。
我测试了使用按钮的PreviewMouseDown事件,它可以工作,但不是我想要的,因为按钮没有遵循它通常的鼠标点击行为
我错过了什么?无论行是否被选中,我如何通过单击一次来获得单击事件?基本上,除了使用TemplateColumn和自己管理每个MouseeEvent之外,没有其他解决方案 说明: 单击鼠标向下+
MouseUp
,右键。
因此,您的按钮需要能够获得mouseDown+MouseUp事件
但是
默认情况下,wpf的DataGrid的行处理MouseDown
事件,以便选择执行MouseDown
操作的行(要在单元格上确认:MouseDown
并按住mouseButton,您将看到在释放按钮之前选中了该行)
因此,基本上,MouseDownEvent
在到达按钮之前被处理,从而阻止您使用按钮上的Click
事件
Microsoft在其文档中告诉我们,在这种情况下,我们应该使用预览类型的事件,但这不适用于click事件,因为您无法使用PreviewClick事件
因此,我能为您找到的唯一解决方案是在您的按钮上同时收听PreviewMouseDown
和PreviewMouseUp
,并模拟他们自己的点击
有点像这样:
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;
(当然,您需要在xaml模板中翻译)
NB:这是不完整的,您还应该注意当用户在按钮上执行鼠标下移操作,但在执行鼠标下移之前将鼠标移出按钮的情况(在这种情况下,您应该重置mouseLeftButtonDownOnMyButton
标志)。最好的方法可能是在普通mouseUpEvent(例如在窗口级别)中重置标志,而不是在按钮的按钮中重置标志
编辑:上述代码还允许您管理单击事件,并且对于真实和模拟的单击事件只有一个代码(因此使用RaiseEvent方法),但是如果您不需要此代码,当然,您也可以直接将代码放在PreviewMouseUp部分。我也遇到了同样的问题-我在模板列上使用了Image,在MouseDown上使用了event,但我必须单击两次。所以我调用了构造函数上的事件处理程序,它对我起了作用
您可以尝试以下方法:
constructor() {
datagridname.AddHandler(Button.ClickEvent, new RoutedEventHandler(Button_Click), true);
}
另一个解决方案是创建自己的按钮。这样做的一个优点是:您不必为每个按钮连接事件
public class FireOnPreviewButton : Button
{
#region Constructor
public FireOnPreviewButton()
{
PreviewMouseLeftButtonDown += OnLeftMouseButtonDownPreview;
}
#endregion
#region Event Handler
private void OnLeftMouseButtonDownPreview(object sender, MouseButtonEventArgs e)
{
// Prevent the event from going further
e.Handled = true;
// Invoke a click event on the button
var peer = new ButtonAutomationPeer(this);
var invokeProv = peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
if (invokeProv != null) invokeProv.Invoke();
}
#endregion
}
这可能不是您的选项,但将设置为IsReadonly=true为我解决了这个问题。我意识到这个问题很老,但我与WPF和XAML签订了10年的合同,我遇到了同样的问题,用户必须在datagrid中单击一行两次才能激活鼠标按钮按下事件。这是因为datagrid使用第一次单击来选择行,第二次单击来触发事件。我发现了一个适用于我的应用程序的简单得多的解决方案:
PreviewMouseLeftButtonDown="MainDataGrid_OnMouseLeftButtonDown"
这会在第一次单击时触发鼠标左键向下事件。这是它在datagrid设置中的外观:
<DataGrid Name="MainDataGrid" IsSynchronizedWithCurrentItem="True" SelectionMode="Extended" SelectionUnit="FullRow"
...removed other options for brevity
PreviewMouseLeftButtonDown="MainDataGrid_OnMouseLeftButtonDown"
...removed other options for brevity
RowHeight="30" BorderThickness="0" Background="#99F0F0F0" Grid.Column="{Binding GridColumn, Mode=TwoWay}" Grid.Row="1">
我用它代替了鼠标按钮。干杯。为时已晚,但对其他人来说不是
我一直面临着同样的问题,花了将近6个小时寻找解决办法。我不想再让别人浪费时间了。在看到所有可能的答案之后。我就是这样修复的:
我将一个方法绑定到main/parentDataGrid的Loaded事件。方法定义为:
private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e)
{
var grid = sender as DataGrid;
if (grid != null && grid.CurrentItem == null && grid.SelectedItem != null)
{
grid.CurrentItem = grid.SelectedItem;
}
else if (grid != null) //Fix when IsSynchronizedWithCurrentItem=True
{
var selectedItem = grid.SelectedItem;
grid.CurrentItem = null;
grid.SelectedItem = null;
grid.CurrentItem = selectedItem;
grid.SelectedItem = selectedItem;
}
}