【问题标题】:Is there a way to prevent the change of the selected row in a WPF DataGrid?有没有办法防止 WPF DataGrid 中选定行的更改?
【发布时间】:2019-11-15 16:41:29
【问题描述】:

我想确保在 wpf DataGrid 中始终选择最后一行(使用 MVVM)。下面的代码绑定到一个按钮。它选择 DataGrid 中的最后一行。效果很好。

    private void SelectLastRow(object obj)
    {
        var temp = DisplayedRows.Last();
        selectedRow = temp;
        OnPropertyChanged(nameof(SelectedRow));
    }

如果我将相同的代码放入 SelectedRow 设置器(绑定到 DataGrid 的 SelectedRow 属性),它将不起作用。设置器已执行,但在 GUI 上不是选择最后一行,而是我单击的那一行。知道为什么吗?如果 DataGrid 中存在验证错误,我的总体目标是防止行更改。

    private object selectedRow;
    public object SelectedRow
    {
        get => selectedRow;
        set
        {
            var temp = DisplayedRows.Last();
            selectedRow = temp;
            OnPropertyChanged(nameof(SelectedRow));
        }
    }

【问题讨论】:

    标签: c# wpf mvvm


    【解决方案1】:

    由于事件触发的顺序,这个有点复杂。当您单击您的DataGrid 时,以下事件将按列出的顺序发生。

    1. PreviewMouseDown
    2. SelectionChanged
    3. MouseLeftButtonUp

    还有其他鼠标事件发生,但我们只会触及这些。您的 DataGrid.SelectionChanged 事件将触发并更新您的 ViewModel 中的 SelectedRow 属性(如您所见),但由于接下来是 MouseLeftButtonUp 处理程序,它将覆盖您创建的所选行绑定。

    private void DataGrid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
       e.Handled = true;
    }
    

    但这实际上会阻止所有鼠标事件在 DataGrid 中触发(包括SelectionChanged 事件),这可能是您不希望的。

    由于您的目标是覆盖对某些项目的选择,因此您应该考虑改为绑定到 DataGridRow.IsEnabled 属性。这样,可以在您的 ViewModel 中将其设置为 false,以在您选择时禁用验证错误时的行选择。

    例子

    <DataGrid>
         <DataGrid.RowStyle>
               <Style TargetType="DataGridRow">
                   <Setter Property="IsEnabled" Value="{Binding MyIsEnabledProperty}"/>
               </Style>
         </DataGrid.RowStyle>
    </DataGrid>
    

    【讨论】:

    • 亲爱的@Tronald 非常感谢。现在我明白了问题所在。我在 dataGrid_SelectionChanged 事件中设置了e.Handled = true;。这样,SelectedRow 设置器在 VM 中运行。然后 dataGrid_SelectionChanged 运行,但选择仍然改变。你知道问题出在哪里吗? (我的最终目标是防止在行包含验证错误时更改选择。)
    • @IstvanHeckl 我已经编辑了答案以更好地满足您的目标
    【解决方案2】:

    @Tronald 和其他人提供了帮助。我的目标是在出现验证错误时阻止更改行。我用IDataErrorInfo。在PreviewMouseLeftButtonDown 事件后面的代码中检查我是否要选择另一行。如果是真的,那么我必须检查 dataGrid 中是否有错误。 Validation.GetHasError(parent) 是不够的,因为它只检查 datGrid 而不是 DataGridRow-s。我在行编辑结束时按 Enter。

    private void DataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var selectedItemNext = (e.OriginalSource as FrameworkElement).DataContext;
        var selectedItemNow = dataGrid.SelectedItem;
        if (selectedItemNext != selectedItemNow)
            if (!IsValid(sender as DependencyObject))
                e.Handled = true;
    }    
    
    public bool IsValid(DependencyObject parent)
    {
        if (Validation.GetHasError(parent))
            return false;
        for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i)
            if (!IsValid(VisualTreeHelper.GetChild(parent, i)))
                return false;
        return true;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-12
      • 1970-01-01
      • 2011-02-28
      • 2011-05-03
      • 1970-01-01
      • 2019-02-15
      • 1970-01-01
      相关资源
      最近更新 更多