防止DataGrid中行的更改

9
我已经研究了这个问题并感到困惑:我有一个WPF DataGrid,并使用MVVM模式。在某些情况下,我希望防止更改DataGrid中的行。我已经进行了研究,并尝试了像此处所发现的技术。

实践中,这个方法是有效的,但是有一个不受欢迎的'闪烁'(它会选择点击的行一段时间然后返回到以前的选择),虽然这是一个接近的解决方案,但我希望有一个更加优雅的方式,比如完全防止首先更改行。

我很惊讶没有SelectionChanging或BeforeSelectionChanged, 所以我可以取消事件从触发; 并且强制在我的视图模型中防止索引更改似乎没有任何区别。

我该怎么办?

谢谢。

3个回答

6
如果您在特定情况下使用previewkeydownpreviewmousedown事件并只是调用e.Handled=true,会发生什么?
编辑: 为了满足MVVM风格: 您可以创建一个带有DependencyPropertyBehavior,将您的情况绑定到该属性上。 在此行为中,您可以处理事件,以及其他一些内容,例如用户是否单击数据行或标题...

前面的建议非常完美(虽然后面的建议也很有趣,我也考虑尝试一下)- 谢谢。 - Mani5556

2

DispatcherPriority已经设置为ContextIdle。这会导致闪烁,因为您的SelectedItem被设置了两次(并且已经呈现了两次)。只需将优先级设置为Normal,就不会再出现闪烁。


0

这里有一些关于PreviewMouseDown方法的例子在这里

普遍认为,在datagrid的SelectionChanged处理程序中将DataGrid.SelectedItem反转回其原始值不起作用;所有看似有效的代码示例都通过请求Dispatcher稍后安排来推迟反转。

你的datagrid上有CellStyle吗?对我而言,以下内容有效:

xaml:

<DataGrid.CellStyle>
    <Style TargetType="{x:Type DataGridCell}">
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Background" Value="DarkSlateBlue"/>
                <Setter Property="Foreground" Value="White"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</DataGrid.CellStyle>

代码后台:

private void MyDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.AddedItems.Count > 0)
    {
        object x = e.AddedItems[0];
        if (x is MyObjectType && x != myViewModel.CurrentItem &&
            myViewModel.ShouldNotDeselectCurrentItem())
        {
            // this will actually revert the SelectedItem correctly, but it won't highlight the correct (old) row.
            this.MyDataGrid.SelectedItem = null;
            this.MyDataGrid.SelectedItem = myViewModel.CurrentItem; 
        }
    }
}

重点是SelectedCellsChanged事件在SelectionChanged事件之后触发 - 特别是,设置SelectedItem不会正确更新SelectedCells,因为它们是只读属性,所以需要更多的代码。
private void MyDataGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
    List<DataGridCellInfo> selectedCells = MyDataGrid.SelectedCells.ToList();

    List<MyObjectType> wrongObjects = selectedCells.Select(cellInfo => cellInfo.Item as MyObjectType)
        .Where (myObject => myObject != myViewModel.CurrentItem).Distinct().ToList();
    if (wrongObjects.Count > 0)
    {
        MyDataGrid.UnselectAllCells();
        MyDataGrid.SelectedItem = null;
        MyDataGrid.SelectedItem = myViewModel.CurrentItem;
    }
}

显然,处理程序需要连接到数据网格上相应的事件。

这个操作按预期工作,如果需要,可以正确取消选择更改,并且不会产生闪烁。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接