【问题标题】:How to prevent Item to be added to DataGrid?如何防止 Item 添加到 DataGrid?
【发布时间】:2017-12-20 17:31:01
【问题描述】:

我的问题

我试图阻止用户在使用内置的 .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&lt;PageItemViewModel&gt;,当有给定条件时(在这种情况下:String.IsNullOrWhiteSpace(PageItemViewModel.Text) == true


编辑:

@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?
}

【问题讨论】:

  • 你可以覆盖OnItemsChanged
  • @MitraM - 在覆盖的 OnItemsChanged 方法中修改集合也会导致 System.InvalidOperationException: 'Removing' is not allowed during an AddNew or EditItem transaction.
  • @Maverik - 创建视图模型完美无缺。
  • @Maverik - 我明白了......但我希望 wpf 数据网格的功能有空行来创建新项目。我不想有一个我需要单击以添加新项目的按钮。
  • 删除了早期的 cmets - 意识到这是一个验证问题,而不是一般的预防问题。我错过了一个关键细节。道歉。

标签: c# wpf datagrid


【解决方案1】:

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

您可以做的是防止提交该对象,方法是在DataGridRowEditEndingEventArgs.EditActionDataGridEditAction.Commit 时处理DataGrid.RowEditEnding 事件并使用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 方法。

【讨论】:

  • 它没有任何问题。先生非常感谢您。我会尽快奖励你的赏金。
【解决方案2】:

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

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
    }
}

【讨论】:

  • 编辑了我的答案。
  • @Picni8 AddingNewItem 事件不提供任何形式的 RoutedEventArgs,因此不提供 Handled 属性。相反,它是AddingNewItemEventArgs。您的代码无效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多