wpf - 滚动时触发 DataGrid SelectionChanged 事件

标签 wpf datagrid

我正在尝试实现一种行为,以允许我的 DataGrid 移动到 DataGrid 底部新添加的行。我有一些按钮可以在 ItemsSource 中添加/删除项目,并在添加新行时以编程方式设置 SelectedCensusReportMapping

我找到了这个解决方案 ( https://www.codeproject.com/Tips/125583/ScrollIntoView-for-a-DataGrid-when-using-MVVM),它确实将新添加的行显示在 DataGrid 中。我遇到的问题是,当我尝试滚动 DataGrid 时,当前选定的行始终保持在 View 中,我无法滚动到其他行,这会将选定的行推出屏幕。

这是我的 DataGrid 的实现:

     <DataGrid Name="DataGrid_CensusReportMapping"
                     ItemsSource="{Binding Model.CensusReportMappings, UpdateSourceTrigger=PropertyChanged}"
                     SelectedItem="{Binding SelectedCensusReportMapping, UpdateSourceTrigger=PropertyChanged}"    
                     AutoGenerateColumns="False"
                     CanUserAddRows="False"
                     CanUserDeleteRows="False">

        <i:Interaction.Behaviors>
            <h:ScrollIntoDataGridBehavior />
        </i:Interaction.Behaviors>
</DataGrid>

如果我通过调试单步执行代码,我发现只要滚动 DataGrid,就会触发该行为。为什么仅通过滚动 DatGrid 即可触发该行为。每当我滚动时都会发生这种情况,无论滚动所选项目是保留在屏幕上还是被推离屏幕。

这是行为代码:

public class ScrollIntoDataGridBehavior : Behavior<DataGrid>
{
    /// <summary>
    /// Override of OnAttached() method to add SelectionChanged event handler
    /// </summary>
    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.SelectionChanged += new SelectionChangedEventHandler(AssociatedObject_SelectionChanged);
    }

    /// <summary>
    /// Override of OnDetaching() method to add SelectionChanged event handler
    /// </summary>
    protected override void OnDetaching()
    {
        base.OnDetaching();
        this.AssociatedObject.SelectionChanged -=
            new SelectionChangedEventHandler(AssociatedObject_SelectionChanged);
    }

    /// <summary>
    /// When the selection is changed, re-focus on new selection using the ScrollIntoView method
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (sender is DataGrid)
        {
            DataGrid grid = (sender as DataGrid);
            if (grid.SelectedItem != null)
            {
                Action action = delegate()
                {
                    grid.UpdateLayout();
                    if (grid.SelectedItem != null)
                    {
                        grid.ScrollIntoView(grid.SelectedItem, null);
                    }
                };

                grid.Dispatcher.BeginInvoke(action);
            }
        }
    }
}

最佳答案

我遇到了与您在这里遇到的类似问题。滚动 DataGrid 时会偶尔触发多个 SelectionChanged 事件。

我注意到 WPF DataGrid 默认使用 UI Virtualization,这意味着 DataGrid 的每一行在滚动到用户视线后都是动态概括的。

如果您将 DataGrid 的属性 EnableRowVirtualization 设置为 false。 WPF 然后会在窗口打开之前预加载 DataGrid 的所有行。这将设法解决这个问题。

其他有用的链接: WPF Toolkit DataGrid scrolling performance problems - why? https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.datagrid.enablerowvirtualization?view=windowsdesktop-6.0 Difference between WPF DataGrid's EnableRowVirtualization and VirtualizingStackPanel.IsVirtualizing properties

PS:不过,我仍然不太确定为什么 DataGrid 滚动会触发 selectionChanged。自 2018 年以来这里的所有答案都是绕过,但触发行为本身仍然发生。

关于wpf - 滚动时触发 DataGrid SelectionChanged 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51968260/

相关文章:

wpf - 如何在 WPF 中将字符串绑定(bind)为 double?

WPF DataGrid DataGridHyperlinkColumn 绑定(bind)到 Uri

wpf - DataGrid 的列宽 (width = "*") 不是 "refreshed"

wpf - WPF DataGrid问题: why the data output twice?

wpf - 如何使用绑定(bind)更新 UI

c# - 如何滚动到 DataGrid 的最后一列?

wpf - 使用 FindAncestor 和 AncestorLevel 将网格高度绑定(bind)到另一个网格

wpf - 类型委托(delegate)的 DependencyProperty

c# - 合并网格列

c# - 从 WPF 数据网格中删除行