如何防止Item添加到DataGrid?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何防止Item添加到DataGrid?相关的知识,希望对你有一定的参考价值。

我的问题

我正在尝试阻止用户在使用内置的.NET DataGrid AddNewItem功能时添加空的DataGrid行。因此,当用户尝试提交DataGrid的AddNew事务并将PageItemViewModel.Text留空时,它应该从DataGrid中消失。

代码

ViewModels

public class PageItemViewModel
{
    public string Text { get; set; }
}

public class PageViewModel
{
    public ObservableCollection<PageItemViewModel> PageItems { get; } = new ObservableCollection<PageItemViewModel>();
}

View

<DataGrid AutoGenerateColumns="True"
          CanUserAddRows="True"
          ItemsSource="{Binding PageItems}" />

我已经试过了

...在处理时从DataGridItemsSource中删除自动创建的对象:

...但总是收到例外情况:

  • “System.InvalidOperationException:在AddNew或EditItem事务期间不允许'删除'。”
  • “System.InvalidOperationException:在CollectionChanged事件期间无法更改ObservableCollection。”
  • “System.InvalidOperationException:当ItemsSource正在使用时,操作无效。请改为使用ItemsControl.ItemsSource访问和修改元素。”

我的问题

当存在给定条件时,如何防止新创建的PageItemViewModel被添加到ObservableCollection<PageItemViewModel>(在这种情况下:String.IsNullOrWhiteSpace(PageItemViewModel.Text) == true


EDIT:

@picnic8AddingNewItem事件不提供任何形式的RoutedEventArgs,因此没有Handled财产。相反,它是AddingNewItemEventArgs。您的代码无效。

private void DataGrid_AddingNewItem(object sender, AddingNewItemEventArgs e)
{
    var viewModel = (PageItemViewModel)e.NewItem;
    bool cancelAddingNewItem = String.IsNullOrWhiteSpace(viewModel.Text) == true;
    // ??? How can i actually stop it from here?
}
答案

您不能也不应该阻止添加到底层集合,因为当最终用户开始在新行中键入时,DataGrid将创建并添加一个新的PageItemViewModel对象,该对象在此时使用默认值进行初始化。

你可以做的是通过在DataGrid.RowEditEndingDataGridRowEditEndingEventArgs.EditAction时处理DataGridEditAction.Commit事件来防止提交该对象,并在验证失败时使用DataGrid.CancelEdit方法有效地删除新对象(或恢复现有对象状态)。

private void DataGrid_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
{
    if (e.EditAction == DataGridEditAction.Commit)
    {
        var bindingGroup = e.Row.BindingGroup;
        if (bindingGroup != null && bindingGroup.CommitEdit())
        {
            var item = (PageItemViewModel)e.Row.Item;
            if (string.IsNullOrWhiteSpace(item.Text))
            {
                e.Cancel = true;
                ((DataGrid)sender).CancelEdit();
            }
        }
    }
}

一个重要的细节是在将当前编辑器值推送到数据源之前触发了RowEditEnding事件,因此您需要在执行验证之前手动执行此操作。我已经使用了BindingGroup.CommitEdit方法。

另一答案

在您的VM中,订阅AddingNewItem事件并检查您的状况。如果条件失败,您可以停止操作。

var datagrid.AddingNewItem += HandleOnAddingNewItem;

public void HandleOnAddingNewItem(object sender, RoutedEventArgs e)
{
    if(myConditionIsTrue)
    {
        e.Handled = true; // This will stop the bubbling/tunneling of the event
    }
}

以上是关于如何防止Item添加到DataGrid?的主要内容,如果未能解决你的问题,请参考以下文章

如何将回收器视图添加到片段

如何防止 ComboBox 中的 NewItemPlaceholder 行绑定到与 WPF 中的 DataGrid 相同的 DataTable

如何防止钥匙串项目不会添加到备份中?

使用导航控制器按下后退按钮后如何防止前一个片段显示?

如何创建 dataGridViewComboBoxCell 并将其添加到 dataGrid

QTreeWidget控件中 itemchanged信号触发后,怎么获取item修改前的值