You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何禁用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 10:54:51