防止数据网格中的行更改

时间:2011-07-26 03:23:15

标签: c# wpf datagrid selectionchanged

我研究了这个并且很难​​过:我有一个WPF DataGrid,并使用MVVM模型。在某些情况下,我希望阻止更改DataGrid中的行的能力。我研究了这个,并尝试过像here那样的技术。

在实践中,这是有效的,但是有一个不受欢迎的'闪烁'(它选择点击的行片刻然后回到之前的选择),而这是一个紧密的解决方案我希望有一个更优雅的方式,如首先防止行更改。

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

我该怎么做?

谢谢。

3 个答案:

答案 0 :(得分:6)

如果您参加previewkeydownpreviewmousedown活动并在特定情况下致电e.Handled=true会怎样?

编辑: 满足mvvm风格: 您可以使用Behavior创建一个DependencyProperty来绑定您的环境。 在这种行为中,您可以处理事件以及其他一些事情,例如用户点击数据行或标题...

答案 1 :(得分:2)

DispatcherPriority已设置为ContextIdle。这使你有闪烁,因为你的SelectedItem设置了两次(并且它被渲染了两次)。只需将优先级设置为“正常”,您就不会再闪烁了。

答案 2 :(得分:0)

PreviewMouseDown方法here有一些示例。

一般协议是将DataGrid.SelectedItem反转回datagrid的SelectionChanged处理程序内的原始值不能按预期工作;似乎有效的所有代码示例都会通过要求Dispatcher稍后安排它来推迟逆转。<​​/ p>

您的数据网格上有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; 
        }
    }
}

关键是在SelectionChanged事件之后触发了SelectedCellsChanged事件 - 特别是设置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;
    }
}

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

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