c# - 数据绑定(bind)问题

标签 c# .net winforms data-binding datagridview

所以我有这个 datagridview,它链接到绑定(bind)到基础数据表的绑定(bind)源。问题是我需要手动将行添加到 datagridview。

这不能在绑定(bind)时完成,所以我必须使用数据绑定(bind)。

如果我将行添加到基础数据表,当保存数据表时,行会重复,可能是因为绑定(bind)源以某种方式获得了一个副本并将其也插入。

将它添加到绑定(bind)源是我一直在尝试做的事情,但效果不佳。

让我准确解释一下我的设置是什么:

我有一个包含两个表的数据库: CashReceiptTable 和 CashReceiptItemsTable

CashReceiptItemsTable 包含 CashReceiptTable 的外键。

该表单允许用户添加和修改这两个表。

当用户输入新的现金收据时,现金收据的id为-1,cashReceiptitemstable中的FK为-1。保存数据库后,更新 cashReceipt 的 id,我必须手动更新 cashreceiptitem 的 FK。

问题如下:

当我尝试更新 cashreceiteitems 绑定(bind)源中多行的 CashReceiptID(FK)时,第一行被更新并消失(因为它被过滤),其他行被删除,我不能再访问它们。

我不知道这是为什么,我还没有更新过滤器,所以它们应该仍然存在,但尝试访问它们会抛出 RowNotInTableException。

我设法解决了将绑定(bind)源中的行复制到内存数组,删除绑定(bind)源中的第一行(所有其他行都消失),更新行的 FK 并将它们重新插入到绑定(bind)源并保存表格。

这工作正常,但为什么行消失了?

我还有一个小问题。当 CashReceiptsTable 为空并且我向其添加新行时,如果我向 CashReceiptsItemTable 添加多行,则会导致问题。手动将项目添加到绑定(bind)源时,添加新行会弹出到前一行并将其推送到数据表中。这从我的 FK 更新例程中隐藏了它并且它丢失了,它还将它从 DataGridView 中删除。

在我将第一行添加到 CashReceiptsTable 时执行此操作。为什么会这样,我该如何解决?

我在这里发布了自动填充它的代码:

        private void autopopulate(decimal totalPayment) {
            //remove old rows
            for (int i = 0; i < tblCashReceiptsApplyToBindingSource.List.Count; i++) {
                DataRowView viewRow = tblCashReceiptsApplyToBindingSource.List[i] as DataRowView;
                RentalEaseDataSet.tblCashReceiptsApplyToRow row = viewRow.Row as RentalEaseDataSet.tblCashReceiptsApplyToRow;

                if (row.CashReceiptsID == this.ReceiptID) {
                    tblCashReceiptsApplyToBindingSource.List.Remove(viewRow);
                    i--;
                }
            }

            decimal payment = totalPayment;

            //look for an exact amount
            foreach (DataGridViewRow dueRow in dataViewDueRO.Rows) {
                decimal due = -1 * (Decimal)dueRow.Cells[Due.Index].Value;
                if (due == payment) {
                    String charge = (String)dueRow.Cells[Description.Index].Value;
                    int chargeID = ManageCheckbooks.findTransactionID(charge);

                    tblCashReceiptsApplyToBindingSource.AddNew();

                    RentalEaseDataSet.tblCashReceiptsApplyToRow row = ((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row as RentalEaseDataSet.tblCashReceiptsApplyToRow;
                    row.CashReceiptsID = this.ReceiptID;
                    row.ApplyTo = chargeID;

                    row.Paid = payment; //convert to positive

                    payment = 0;
                    break;
                }
            }

            //if the exact amount was found, payment will = 0, and this will do nothing, otherwise,
            //divy out everything left over (which will be everything)
            foreach (DataGridViewRow dueRow in dataViewDueRO.Rows) {
                String charge = (String)dueRow.Cells[Description.Index].Value;
                decimal due = (Decimal)dueRow.Cells[Due.Index].Value;

                if (due > 0 || payment <= 0) {
                    continue;
                }

                int chargeID = ManageCheckbooks.findTransactionID(charge);

                payment += due; //due is negative, so this will subtract how much the user owes

                tblCashReceiptsApplyToBindingSource.AddNew();

                RentalEaseDataSet.tblCashReceiptsApplyToRow row = ((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row as RentalEaseDataSet.tblCashReceiptsApplyToRow;
                row.CashReceiptsID = this.ReceiptID;
                row.ApplyTo = chargeID;

                if (payment >= 0) {
                    //payment is enough to cover this
                    row.Paid = due * -1; //convert to positive
                } else {
                    //doesn't have enough money to conver this, can only cover partial, or none
                    row.Paid = (due - payment) * -1; //math:
                    //money remaining $50, current charge = $60
                    //payment = 50 + -60 = -10
                    //row["Paid"] = (-60 - -10) * -1
                    //row["Paid"] = (-60 + 10) * -1
                    //row["Paid"] = -50 * -1
                    //row["Paid"] = 50
                }

                if (payment <= 0) {
                    break; //don't conintue, no more money to distribute
                }
            }

            isVirginRow = true;
        }

这是将它保存到数据库的函数:

    protected override void saveToDatabase() {
        tblCashReceiptsBindingSource.EndEdit();
        isVirginRow = false;

        RentalEaseDataSet.tblCashReceiptsRow[] rows = rentalEaseDataSet.tblCashReceipts.Select("ID < 0") as RentalEaseDataSet.tblCashReceiptsRow[];
        int newID = -1;
        if (rows.Count() > 0) {
            tblCashReceiptsTableAdapter.Update(rows[0]);
            newID = rows[0].ID;
        }

        tblCashReceiptsTableAdapter.Update(rentalEaseDataSet.tblCashReceipts);


        //update table
        /*foreach (RentalEaseDataSet.tblCashReceiptsApplyToRow row in rentalEaseDataSet.tblCashReceiptsApplyTo.Select("CashReceiptsID = -1")) {
            row.CashReceiptsID = newID;
        }*/

        //update binding source
        DataRowView[] applicationsOld = new DataRowView[tblCashReceiptsApplyToBindingSource.List.Count];
        RentalEaseDataSet.tblCashReceiptsApplyToRow[] applicationsNew = new RentalEaseDataSet.tblCashReceiptsApplyToRow[tblCashReceiptsApplyToBindingSource.List.Count];
        tblCashReceiptsApplyToBindingSource.List.CopyTo(applicationsOld, 0);
        for (int i = 0; i < applicationsOld.Count(); i++) {
            RentalEaseDataSet.tblCashReceiptsApplyToRow row = applicationsOld[i].Row as RentalEaseDataSet.tblCashReceiptsApplyToRow;

            if (row.CashReceiptsID < 0) {
                applicationsNew[i] = rentalEaseDataSet.tblCashReceiptsApplyTo.NewRow() as RentalEaseDataSet.tblCashReceiptsApplyToRow;
                applicationsNew[i]["ID"] = row.ID;
                applicationsNew[i]["CashReceiptsID"] = this.ReceiptID;
                applicationsNew[i][2] = row[2];
                applicationsNew[i][3] = row[3];
                applicationsNew[i][4] = row[4];
                //row.Delete();
            }
        }
        for (int i = 0; i < applicationsOld.Count(); i++) {
            try {
                if ((int)applicationsOld[i].Row["ID"] < 0) {
                    applicationsOld[i].Row.Delete();
                }
            } catch (RowNotInTableException) {
                break;
            }
        }
        this.tblCashReceiptsApplyToBindingSource.Filter = "CashReceiptsID = " + this.ReceiptID;

        foreach (DataRow newRow in applicationsNew) {
            if (newRow == null) {
                break;
            }
            tblCashReceiptsApplyToBindingSource.AddNew();
            ((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row[0] = newRow[0];
            ((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row[1] = newRow[1];
            ((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row[2] = newRow[2];
            ((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row[3] = newRow[3];
            ((DataRowView)tblCashReceiptsApplyToBindingSource.Current).Row[4] = newRow[4];
        }

        tblCashReceiptsApplyToBindingSource.EndEdit();

        checkForBadRows();

        tblCashReceiptsApplyToTableAdapter.Update(rentalEaseDataSet.tblCashReceiptsApplyTo);
        tblCashReceiptsApplyToTableAdapter.Fill(rentalEaseDataSet.tblCashReceiptsApplyTo);
    }

最佳答案

您可能想尝试向 DataGridView 添加行。由于您绑定(bind)到它,DataGridView 成为您的“访问点”。

我有几个绑定(bind)到 DataGridView 的应用程序,在大多数情况下,当我添加一行时,我是通过 DataGridView 这样做的。它已经具有属性/方法/事件,可让您相对轻松地进行添加。

如果您需要更多信息,我可以更新。

关于c# - 数据绑定(bind)问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2269353/

相关文章:

c# - 启用基本和 Windows 身份验证

.net - 这是否是现有的设计模式?

c# - 使用 XML 命名空间在 C# 中针对模式创建和验证 XML

c# - Windows 服务中托管的 WCF 服务无法正常运行

.net - 系统颜色与专业颜色

c# - 找不到类型 'Track_Attack.TAGeneric' 的构造函数。 C# 窗体

c# WPF 对 Winform 控件的透明性

c# - 防止重复注册 - CaSTLe Windsor

c# - Winform 变量作用域

c# - 在 Visual Studio 2013 中构建失败并显示 "Could not copy the file.. because it was not found"