WPF DataGrid行MouseOver事件实现:行内按钮仅悬停显示问题咨询
在WPF DataGrid中实现行悬停时显示按钮
当然可以实现这个需求!而且不用费劲写后台的MouseOver事件处理逻辑——WPF的样式触发器(Trigger)天生就是干这个的,用声明式的XAML就能搞定,比后台代码优雅多了。
核心思路是:
- 让按钮默认处于隐藏状态(
Visibility="Collapsed") - 绑定按钮的可见性到所在行的
IsMouseOver属性,当行被鼠标悬停时切换按钮为显示状态
下面给你两种可行的实现方案,你可以根据自己的场景选择:
方案一:轻量版(推荐)
直接在按钮所在的CellTemplate里添加触发器,绑定到父级DataGridRow的IsMouseOver属性,不需要修改行的整体模板:
<DataGrid x:Name="MyDataGrid" AutoGenerateColumns="False"> <DataGrid.Columns> <!-- 其他数据列 --> <DataGridTextColumn Header="姓名" Binding="{Binding Name}" /> <DataGridTextColumn Header="年龄" Binding="{Binding Age}" /> <!-- 带悬停显示按钮的操作列 --> <DataGridTemplateColumn Header="操作"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Button x:Name="EditBtn" Content="编辑" Margin="2,0"/> <Button x:Name="DeleteBtn" Content="删除" Margin="2,0"/> </StackPanel> <DataTemplate.Triggers> <!-- 当行未被悬停时隐藏按钮 --> <DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=DataGridRow}}" Value="False"> <Setter TargetName="EditBtn" Property="Visibility" Value="Collapsed"/> <Setter TargetName="DeleteBtn" Property="Visibility" Value="Collapsed"/> </DataTrigger> </DataTemplate.Triggers> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
方案二:自定义行模板版
如果你需要同时修改行的其他视觉状态(比如悬停时的背景色),可以重写DataGridRow的模板,在模板内添加触发器控制按钮显示:
<DataGrid x:Name="MyDataGrid" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="姓名" Binding="{Binding Name}" /> <DataGridTextColumn Header="年龄" Binding="{Binding Age}" /> <DataGridTemplateColumn Header="操作"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Button x:Name="EditBtn" Content="编辑" Margin="2,0" Visibility="Collapsed"/> <Button x:Name="DeleteBtn" Content="删除" Margin="2,0" Visibility="Collapsed"/> </StackPanel> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> <DataGrid.RowStyle> <Style TargetType="DataGridRow"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="DataGridRow"> <Border x:Name="RowBorder" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <SelectiveScrollingGrid> <DataGridCellsPresenter Grid.Column="1" /> <DataGridRowHeader Grid.RowSpan="2" /> </SelectiveScrollingGrid> </Border> <ControlTemplate.Triggers> <!-- 鼠标悬停时显示按钮并高亮行背景 --> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="RowBorder" Property="Background" Value="#FFE5F3FF"/> <Setter TargetName="EditBtn" Property="Visibility" Value="Visible"/> <Setter TargetName="DeleteBtn" Property="Visibility" Value="Visible"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </DataGrid.RowStyle> </DataGrid>
至于你之前尝试的后台MouseOver事件没生效,大概率是因为DataGrid默认开启了行虚拟化,直接绑定事件会因为行的复用机制出现异常——而用XAML触发器就完全避开了这个问题,它是跟着行的视觉状态自动同步的,稳定性更高。
内容的提问来源于stack exchange,提问作者Marcos Brinner pikatoons
相关产品推荐
相关产品推荐

