如何禁用WPF DataGrid中点击单元格触发的水平滚动
解决WPF DataGrid点击视野外单元格自动水平滚动的问题
我的C# WPF项目里的DataGrid有个烦人的行为:点击视野范围外的单元格时,控件会自动水平滚动以显示整个单元格。我希望水平滚动仅通过拖动水平滚动条触发,不想让点击单元格时自动滚动。
复现代码
XAML代码
<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <DataGrid HorizontalAlignment="Stretch" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserResizeRows="False" CanUserSortColumns="True" x:Name="MyDataGrid_BusLog" IsReadOnly="True" SelectionMode="Extended" AutoGenerateColumns="False" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Auto" > </DataGrid> </Grid> </Window>
C#代码
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var column = new DataGridTextColumn(); column.Header = "Line"; column.Binding = new Binding("Line"); MyDataGrid_BusLog.Columns.Add(column); column = new DataGridTextColumn(); column.Header = "TelTyp"; column.Binding = new Binding("TelTyp"); MyDataGrid_BusLog.Columns.Add(column); column = new DataGridTextColumn(); column.Header = "State"; column.Binding = new Binding("State"); MyDataGrid_BusLog.Columns.Add(column); column = new DataGridTextColumn(); column.Header = "Timestamp_ms"; column.Binding = new Binding("Timestamp_ms"); MyDataGrid_BusLog.Columns.Add(column); column = new DataGridTextColumn(); column.Header = "EC"; column.Binding = new Binding("EC"); MyDataGrid_BusLog.Columns.Add(column); column = new DataGridTextColumn(); column.Header = "Date"; column.Binding = new Binding("Date"); MyDataGrid_BusLog.Columns.Add(column); column = new DataGridTextColumn(); column.Header = "Time"; column.Binding = new Binding("Time"); MyDataGrid_BusLog.Columns.Add(column); column = new DataGridTextColumn(); column.Header = "QQ"; column.Binding = new Binding("QQ"); MyDataGrid_BusLog.Columns.Add(column); column = new DataGridTextColumn(); column.Header = "ZZ"; column.Binding = new Binding("ZZ"); MyDataGrid_BusLog.Columns.Add(column); column = new DataGridTextColumn(); column.Header = "PBSB"; column.Binding = new Binding("PBSB"); MyDataGrid_BusLog.Columns.Add(column); column = new DataGridTextColumn(); column.Header = "NN"; column.Binding = new Binding("NN"); MyDataGrid_BusLog.Columns.Add(column); column = new DataGridTextColumn(); column.Header = "Data"; column.Binding = new Binding("Data"); MyDataGrid_BusLog.Columns.Add(column); MyDataGrid_BusLog.Items.Add(new DataItem { Line = "1", TelTyp = "MS", State = "OK", Timestamp_ms = "1111", EC = "0", Date = "2024-10-09",Time = "17:05:30.1234",QQ = "30",ZZ = "70",PBSB = "0704",NN = "0",Data = "50 10 20 70 90 34 65 A3 BD 3D 32 00" }); MyDataGrid_BusLog.Items.Add(new DataItem {Line = "1",TelTyp = "SYN",State = "OK",Timestamp_ms = "1200",EC = "0", Date = "2024-10-09",Time = "17:05:30.2000",QQ = "AA",ZZ = "AA",PBSB = "AAAA",NN = "AA", Data = "AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA" }); } }
解决方案
DataGrid的自动滚动由RequestBringIntoView事件触发,拦截该事件即可阻止此行为,以下是两种实现方式:
方法一:直接绑定事件处理
修改DataGrid的XAML,添加事件绑定:
<DataGrid ... RequestBringIntoView="MyDataGrid_BusLog_RequestBringIntoView" > </DataGrid>
在后台代码中添加事件处理逻辑,取消事件传递:
private void MyDataGrid_BusLog_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e) { e.Handled = true; }
方法二:自定义通用DataGrid
如果多个DataGrid需要此行为,可自定义控件封装逻辑:
public class NoAutoScrollDataGrid : DataGrid { protected override void OnRequestBringIntoView(RequestBringIntoViewEventArgs e) { e.Handled = true; } }
在XAML中引用自定义控件(需先添加命名空间):
xmlns:local="clr-namespace:WpfApp1" <local:NoAutoScrollDataGrid ... > </local:NoAutoScrollDataGrid>
可选:仅阻止水平滚动
如果需要保留垂直方向的自动滚动,可在事件处理中判断滚动方向:
private void MyDataGrid_BusLog_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e) { var scrollViewer = FindVisualParent<ScrollViewer>(sender as DependencyObject); if (scrollViewer == null) return; var targetElement = e.TargetObject as FrameworkElement; if (targetElement == null) return; var targetOffset = targetElement.TransformToAncestor(scrollViewer).Transform(new Point(0, 0)).X; var viewportWidth = scrollViewer.ViewportWidth; // 仅当目标元素不在水平视野内时,阻止自动滚动 if (targetOffset < 0 || targetOffset + targetElement.ActualWidth > viewportWidth) { e.Handled = true; } } // 辅助方法:查找视觉父元素 private T FindVisualParent<T>(DependencyObject child) where T : DependencyObject { var parent = VisualTreeHelper.GetParent(child); return parent is T ? (T)parent : FindVisualParent<T>(parent); }
内容的提问来源于stack exchange,提问作者user24852915
相关产品推荐
相关产品推荐

