【问题标题】:Clearing wpf datagrid cells by user at runtime用户在运行时清除 wpf datagrid 单元格
【发布时间】:2015-07-28 14:44:34
【问题描述】:

我有一个数据网格,它应该是供最终用户使用的“输入表”。 (用户提供数据,点击按钮,程序处理数据)

它绑定到一个 ObservableCollection(用户类包含简单的东西,如电子邮件、姓名、登录等)

一切工作正常绑定明智...但是,我想让用户更正他们的输入,即选择一行并将其从网格中删除,或清除几个单元格的内容等 - 并非所有字段都是强制性的。

但是,当按下 Del 键时,什么也没有发生。我尝试处理 previewKeyDown 事件等,但遇到了以下问题:

How I can Delete Selected Row in datagrid wpf?

这是否意味着我在使用绑定时无法删除项目?我不知道如何可靠地修改基础集合 - 我怎么知道是否应该删除 Name、Login、Email 的值以及我的集合中的哪个用户?

我认为双向绑定可以解决这个问题...

我的代码:

ItemsSource="{Binding ElementName=ThisUc,
            Path=UsersToCreate,
            Mode=TwoWay,
            UpdateSourceTrigger=PropertyChanged}"


private ObservableCollection<User> _usersToCreate;
        public ObservableCollection<User> UsersToCreate
        {
            get { return _usersToCreate ?? (_usersToCreate = new ObservableCollection<User>()); }
            set
            {
                _usersToCreate = value;
                RaisePropertyChanged("UsersToCreate");
                ProgressBarMax = UsersToCreate.Count;
            }
        }

干杯

【问题讨论】:

  • 绑定到视图模型中的选定项。按下删除键后,从 observablecollection 中删除该项目

标签: c# wpf datagrid


【解决方案1】:

这是否意味着我在使用绑定时无法删除项目?

不。这只是意味着如果您通过ItemsSource 设置您的项目,DataGrid 无法控制该集合(它可以是任何类型的集合!)并且依赖于您来处理它。

我不知道如何可靠地修改基础集合 - 我如何知道是否应该删除 Name、Login、Email 的值以及集合中的哪个用户?

如果你知道行,你就知道用户。 User 对象是 DataContextDataGridRow 及其单元格。您只需从UsersToCreate 集合中删除UserDataGrid 就会相应更新。

您可以绑定DataGridSelectedItem 属性,这将返回所选行的User 对象。

至于清除一个给定的单元格,这并不容易...单元格通常只表示该行的数据项的属性,清除其值的唯一方法是将该属性重置为其默认值。在这种情况下,识别属性并不简单。

清除单元格的最佳方法是在其模板中使用带有一些自定义TextBoxDataGridTemplateColumn,它处理PreviewKeyUp 事件并在检测到Del 时执行TextBox.Clear() > 键被按下并释放。

【讨论】:

  • 谢谢 - 我会在这里发布我的完整解决方案 :)
【解决方案2】:

当然可以:

<DataGrid>
    <DataGrid.InputBindings>
        <KeyBinding Key="D" Command="{Binding DeleteCommand}" />
        <KeyBinding Key="Delete" Command="{Binding DeleteCommand}" />
    </DataGrid.InputBindings>
</DataGrid>

编辑: 您可以将所选项目作为参数传递,也可以完全按照 moncada 的建议进行操作。为此,我认为用户必须从数据网格中选择一行而不是单元格,但现在不确定。

【讨论】:

    【解决方案3】:

    为了将来参考,这是我的完整解决方案:

    private void UserDataGrid_OnPreviewKeyDown(object sender, KeyEventArgs e)
        {
            var grid = sender as System.Windows.Controls.DataGrid;
            if (e.Key == Key.Delete)
            {
                //treat each cell individually
                foreach (var item in grid.SelectedCells)
                {
                    User user = item.Item as User;
                    if (user == null)
                        continue;
                    //clear the property of the selected cell
                    foreach (var property in typeof(User).GetProperties())
                    {
                        if (property.Name == item.Column.Header.ToString())
                        {
                            property.SetValue(user, null, null);
                        }
                    }
                    //recreated the user object
                    User newUser = new User
                    {
                        Login = user.Login,
                        Address = user.Address,
                        Email = user.Email,
                        Name = user.Name,
                        Description = user.Description
                    };
                    //remove the old one and place the new one to update collection visually (otherwise DataGrid updates when only double-clicked)
                    var index = UsersToCreate.IndexOf(user);
                    UsersToCreate.Remove(user);
                    UsersToCreate.Insert(index, newUser);
                }
                //now check if any rows are completely empty - if so, then remove from DGV
                List<int> indexesToRemove = new List<int>();
                foreach (var user in UsersToCreate)
                {
                    bool hasValue = false;
                    foreach (var property in typeof(User).GetProperties())
                    {
                        if (property.GetValue(user, null) != null)
                        {
                            hasValue = true;
                        }
                    }
                    if (!hasValue)
                    {
                        indexesToRemove.Add(UsersToCreate.IndexOf(user));
                    }
                }
                //go upside down to avoid index out of range (first remove last rows indexes)
                for (int i = indexesToRemove.Count - 1; i >= 0; i--)
                {
                    var index = indexesToRemove[i];
                    UsersToCreate.RemoveAt(index);
                }
            }
        }
    

    虽然它很大,但我认为它非常简洁,因为它允许选择多行中的多个单元格并清除它们而无需重新排序数据网格等。而且,如果所有属性都为空,它允许删除整行用户。

    遗憾的是,我需要读取用户,因为当我只是更新属性时,datagrid 不会在视觉上更新 - 集合已更新,但您需要在特定属性单元格上单击以查看它已被擦除。

    谢谢大家的帮助

    【讨论】:

    • 很高兴你做到了 :) 如果这对你有用,请将其标记为答案,以便其他人可以轻松找到它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-22
    • 2018-04-29
    • 2011-07-09
    • 1970-01-01
    • 2014-10-09
    • 2014-11-05
    • 2017-08-07
    相关资源
    最近更新 更多