将多个选定的数据网格行保存到 EF 表

Posted

技术标签:

【中文标题】将多个选定的数据网格行保存到 EF 表【英文标题】:save multiple selected datagrid rows to EF table 【发布时间】:2020-12-21 03:30:28 【问题描述】:

我的 WPF 表单有 DataGrid。第一列是 CheckBox 列。我想在单击按钮时,检查所有 CheckBoxes 行,插入到 EF 表中。怎么做?我会很感激样品。 谢谢。

【问题讨论】:

您现有的代码在哪里?你已经尝试过什么? 我找到了这样的代码。 private void button1_Click(object sender, EventArgs e) int i = 0;列表 ChkedRow = new List(); for (i = 0; i 但它在 WPF 中不起作用 请编辑问题并将您的评论以及格式化代码添加到问题中。这将对我们和未来的读者有所帮助 【参考方案1】:

我想在单击按钮时,检查所有 CheckBoxes 行,插入到 EF 表中

这有点神秘。您是否希望使用 Entity Framework 将 CheckBox 列中具有 Checked 值的所有行添加/更新/删除到您的数据库中?

无论如何,无论你想做什么,你都应该separate your concerns.。在这种情况下,您应该创建方法来读取 DataGrid 中的内容,以及可以插入/更新/删除数据库序列中的元素的方法。

唉,您没有告诉我们很多关于 DataGridView 中的内容以及 DbContext 中的内容。

当您使用 WPF 时,您应该使用 MVVM 模式:您应该有一个 View、一个 Model 和一个 ViewModel。

视图是与操作员的接口。视图包含显示当前值和操作员用来进行更改的网格。视图还包含操作员按下以通知应处理更改的按钮。

模型包含实际数据。 ViewModel 位于 View 和 Model 之间:它知道应该显示数据的哪一部分,知道应该对数据执行操作,但它不知道如何显示数据,也不知道操作是如何进行的开始了。

所以 ViewModel 知道它应该提供一个命令来处理更改,但它不知道这是通过一个小的圆形蓝色按钮还是一个大的三角形按钮启动的,或者该命令是使用菜单启动的物品。这些可视部分不是 ViewModel 的一部分。

如果您不知道我在说什么,那么我建议您花一个下午的时间阅读有关 MVVM、WPF 属性和命令的内容。

视图模型

在操作员编辑数据网格的内容后,他按下一个按钮来通知应该处理更改。你的代码应该是这样的:

class CustomerViewModel

    public ObservableColection<DisplayedCustomer> DisplayedCustomers
    
        get => ...
    

    public ICommand CommandProcessChanges get;  ...

    private bool CanProcessChanges(...)
    
        ...
    

    private void ProcessChanges(...)
    
        ...
    

当方法ProcessChanges被调用时,你知道操作员已经完成了他的修改,所有的修改都在属性Customers中。

您的任务是更新模型中的更改。 ViewModel 不知道也不关心 Model 是否将数据保存在数据库中,或保存在 CSV 文件中,或者数据是否通过 Internet 传输。 ViewModel 只知道操作员想要处理一些数据。

你的 ViewModel 你对 CheckBox 一无所知。您的 ViewModel 不知道 DisplayedCustomers 是如何显示的。它只知道 GridView 的内容在 DisplayedCustomers 中。

我不知道您的 CheckBox 是什么意思:您要删除选中 CheckBox 的所有客户吗?你想获取他们的数据吗?无论如何,您的 DisplayedCustomer 将类似于:

class DisplayedCustomer : INotifyPropertyChanged

    // Customer properties:
    public int Id get; set;
    public string Name get; set;
    ...

    // properties for the CheckBox columns:
    public bool IsDeleteRequested get; set;
    public bool IsFetchRequested get; set;

为简单起见,我省略了 NotifyPropertyChanged 的​​代码。

后两个属性用于显示复选框。如果操作员选中/取消选中它们,布尔值将自动更新。

private void ProcessChanges(...)

    var customerIdsToFetch = this.DisplayedCustomers
        .Where(customer => customer.IsFetchRequested())
        .Select(customer => customer.Id);
    var fetchedCustomers = this.FetchCustomers(customerIdsToFetch);
    this.ProcessFetchedCustomers(fetchedCustomers);

    var customersToDelete = this.DisplayedCustomers
        .Where(customer => customer.IsDeleteRequested);
    this.Model.DeleteCustomers(customersToDelete);

您是否注意到,在 ViewModel 中,您对复选框一无所知?

IEnumerable<Customer> FetchCustomers(IEnumerable<int> customerIds)

    return this.CustomerModel.FetchCustomers(customerIds);


void ProcessFetchedCustomers(IEnumerable<Customer> fetchedCustomers)

    // TODO: what do you want to do with the fetchedCustomers,
    // if your View needs them, for instance to display their names in a ListBox:
    this.FetchedCustomerNames = fetchedCustomers
        .Select(customer => customer.Name)
        .ToList();

注意:您的 ViewModel 不知道 View 对这些获取的客户名称做了什么。因此,如果您决定更改视觉表示,例如您不想在红色 ListBox 中显示它们,但在 LightBlue ComboBox 中显示,则您的 ViewModel 不必更改

模型

因此,您已将关注点分为:可视化表示 (View)、必须可视化的数据 (ViewModel) 和数据源 (Model)。

只有模型知道数据存储在数据库中。如果您决定将数据保存为 XML 格式或 CSV 文件,则您的 View 和 ViewModel 都不必更改。

class CustomerModel

    public ICollection<Customer> FetchCustomersById(IEnumerable<int> customerIds)
    
        using (var dbContext = new OrderContext())
        
            return dbContext.Customers
                .Where(customer => customerIds.Contains(customer.Id))
                .ToList();
        
    

    public void DeleteCustomers(IEnumerable<int> customerIdsToDelete)
    
         using (var dbContext = ...)
         
             var customersToDelete = dbContext.Customers
                .Where(customer => customerIdsToDelete.Contains(customer.Id))
                .ToList();
             dbContext.Customers.DeleteRange(customersToDelete);
             dbContext.SaveChanges();
         
    

假设在未来的版本中,您希望能够取消删除客户。因此,Delete 不会将其从数据库中删除,它只会设置一个布尔属性 IsObsolete

public ICollection<Customer> FetchCustomersById(IEnumerable<int> customerIds)

    using (var dbContext = new OrderContext())
    
        return dbContext.Customers
            .Where(customer => customerIds.Contains(customer.Id)
                            && customer => !customer.IsObsolete)
            .ToList();
        
    

    public void DeleteCustomers(IEnumerable<int> customerIdsToDelete)
    
         using (var dbContext = ...)
         
             foreach (int id in customerIdsToDelete)
             
                 var customerToDelete = dbContext.Customers.Find(id);
                 customerToDelete.IsObsolete = true;
                 dbContext.SaveChanges();
             
         
    

因此,如果管理员想要取消删除意外删除的客户,他只需将属性 IsObsolete 设置为 false。

现在,尽管您更改了内部客户,但您的视图和视图模型都不会注意到这一点。您可以通过使用接口来加强这种灵活性。

结论

您分离了您的关注点:您创建了一个单独的视图/视图模型/模型。因此,您的 View 所要做的就是确保 DisplayedCustomer 已更新。您的 ViewModel 所要做的就是处理 DisplayedCustomers,您的 Model 所要做的就是更新数据库。

只有了解 CheckBox 的部分才需要担心复选框。了解数据库的部分,对复选框一无所知。

【讨论】:

以上是关于将多个选定的数据网格行保存到 EF 表的主要内容,如果未能解决你的问题,请参考以下文章

如何一次将数据插入和更新到 EF 多个表中

将数据网格视图行添加到 vb.net 中的 sql 表

如何结合两个条件来覆盖数据网格的选定行样式?

如何将单击/选定的行数据从一个表传递到并排放置的另一个表

如何将选定的行从一个 wpf 数据网格复制到另一个 wpf 数据网格? [关闭]

根据 id C# 将相关数据填充到选定行