WPF数据表格“刷新”操作在执行添加新项或编辑项事务时不允许,涉及MVVM模式。

14

我有下面这个网格:

    <DataGrid

        x:Name="TablesDataGrid"
        Grid.Column="0"
        Grid.Row="1"
        ItemsSource="{Binding FilteredModels.View}"
        AlternationCount="2"
        AutoGenerateColumns="False"
        CanUserSortColumns="True"
        CanUserReorderColumns="False"
  CanUserDeleteRows="False"
  CanUserAddRows="False"
  SelectionMode="Extended"
        IsReadOnly="False"
  SelectionUnit="FullRow"
        RowHeight="25"
  HorizontalAlignment="Stretch"
  ColumnWidth="Auto">
            <DataGrid.Columns >
                <DataGridCheckBoxColumn Width="*" Binding="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"  IsReadOnly="False">
                    <DataGridCheckBoxColumn.HeaderTemplate>
                        <DataTemplate>
                            <CheckBox IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.CheckAll}"/>
                        </DataTemplate>
                    </DataGridCheckBoxColumn.HeaderTemplate>
                </DataGridCheckBoxColumn>
                <DataGridTextColumn Header="Source Table" Binding="{Binding SourceTableFullName}" Width="4*"></DataGridTextColumn>
                <DataGridTextColumn Header="EDW Schema"  Binding="{Binding SchemaName}" Width="2*"></DataGridTextColumn>
                <DataGridTextColumn Header="EDW Table" Binding="{Binding TableName}" Width="4*"></DataGridTextColumn>
                <DataGridTextColumn Header="Status" Binding="{Binding Status}" Width="*"></DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>

然后我有一个searchCommand,它在视图模型中执行对collectionViewSource FilteredModels的搜索,然后调用

this.FilteredModels.View.Refresh();

当用户勾选几个复选框并将网格发送到编辑模式,然后执行搜索操作时,我们会收到以下错误。

WPF DataGrid 'Refresh' is not allowed during an AddNew or EditItem transaction

当复选框被选中时,或者甚至在单击搜索按钮时,是否有一种方法可以强制网格退出编辑模式?还是有其他解决方法吗?

谢谢!

3个回答

49

我知道回答已经太晚了...但对于正在寻找答案的人

可以像这样连续两次使用cancelEdit或commitEdit方法

//用于commit

this.datagrid_layers.CommitEdit();
this.datagrid_layers.CommitEdit();

//取消用

this.datagrid_layers.CancelEdit();
this.datagrid_layers.CancelEdit();

4
我不知道为什么只使用一次不起作用,但连续两次使用却有效?有任何想法... - Ash
5
永远不晚:D。你的回答让我节省了很多时间!!! @Ash:我猜datagrid存储两个交易。一个是列的,另一个是行的。在刷新集合视图之前,您需要提交两者。 - fharreau
2
对我来说没什么区别,两个调用都可以,一个是不够的。同时感谢你“晚”回答,对我来说也不算太晚。 - Martini Bianco
1
可能这就是原因:“如果单元格当前处于编辑模式,则CancelEdit方法会取消单元格编辑,但不会取消任何待处理的行编辑。如果单元格不处于编辑模式,则CancelEdit会取消所有待处理的行编辑。” msdn上的CancelEdit - BalintPogatsa
3
不要调用两次CommitEdit(这很令人困惑),请调用:CommitEdit(DataGridEditingUnit.Row, true); - Scover

5

您应该能够将所选项目转换为IEditableObject并对其调用EndEdit,或调用网格的CancelEdit方法。


5

这个问题有一个干净的MVVM解决方案。首先,您的ViewModels必须实现IEditableObject接口(空操作就足够了)。然而,这还不够,因为DataGrid不会监听IEditableObject.CancelEdit
另一个问题是,ICollectionViewIEditableCollectionView都没有实现另一个。虽然只有ICollectionView可以刷新,但只有IEditableCollectionView可以提交/取消。幸运的是,由CollectionViewSource.GetDefaultView返回的集合视图实现了两个

// ViewModel.cs
public class ItemVM : IEditableObject, INotifyPropertyChanged { }

public class ModuleVM : INotifyPropertyChanged {
   ICollectionView Items { get; }

   public ModuleVM(ObservableCollection<ItemVM> items) {
      Items = CollectionViewSource.GetDefaultView(items);
   }

   public void RefreshSafely() {
      ((IEditableCollectionView)Items).CancelEdit(); // alterantively, CommitEdit()
      Items.Refresh();
   }
}

换句话说,您可以将ICollectionView转换为IEditableCollectionView,并首先调用CancelEdit()

2
谢谢。昨天我花了很多时间在这个问题上苦苦挣扎。每次我更改DataGrid上的复选框并尝试打开对话框时,都会出现DeferRefresh异常。我正在使用MVVM,所以无法在DataGrid上执行commitEdit。通过将您上面的示例组合如下:var Items = CollectionViewSource.GetDefaultView(vm.ThisCustomer.CurrentOrder.OrderDetailsList);
((System.ComponentModel.IEditableCollectionView)Items).CommitEdit(); Items.Refresh();问题得到解决。太好了!
- Dave Oakley

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