【问题标题】:Winforms bindingsource issue adding new recordWinforms bindingsource问题添加新记录
【发布时间】:2016-08-02 13:22:13
【问题描述】:

我有以下代码将绑定数据加载到主从窗口,主数据绑定到文本框和其他控件,详细数据绑定到 DataGridView:

在表单加载时:

    DataSet dsOrders = new DataSet("dsOrders");

            SqlDataAdapter daOrderHeader;// = new SqlDataAdapter();
            SqlDataAdapter daOrderDetail;// = new SqlDataAdapter();

            BindingSource bsOrderHeader = new BindingSource();
            BindingSource bsOrderDetail = new BindingSource();

    DataTable dtOrderHeader = new DataTable("dtOrderHeader");
                DataTable dtOrderDetail = new DataTable("dtOrderDetail");

                dsOrders.Tables.Add(dtOrderHeader);
                dsOrders.Tables.Add(dtOrderDetail);

                daOrderHeader = DataAdapterOrderHeader();
                daOrderDetail = DataAdapterOrderDetail();

                daOrderHeader.Fill(dtOrderHeader);
                daOrderDetail.Fill(dtOrderDetail);

                ////Set up a master-detail relationship between the DataTables
                DataColumn keyOrderHeaderColumn = dsOrders.Tables["dtOrderHeader"].Columns["ID"];
                DataColumn foreignKeyOrderDetailColumn = dsOrders.Tables["dtOrderDetail"].Columns["OrderId"];
                dsOrders.Relations.Add("rOrders", keyOrderHeaderColumn, foreignKeyOrderDetailColumn);

                bsOrderHeader.DataSource = dsOrders;
                bsOrderHeader.DataMember = "dtOrderHeader";
                bsOrderDetail.DataSource = bsOrderHeader;
                bsOrderDetail.DataMember = "rOrders";

tbxOrderNo.DataBindings.Add("Text", bsOrderHeader, "ID");
            tbxCustomer.DataBindings.Add("Text", bsOrderHeader, "Name");
            tbxTaxRate.DataBindings.Add("Text", bsOrderHeader, "TaxRate");
            tbxShipping.DataBindings.Add("Text", bsOrderHeader, "Shipping");
            tbxExchangeRate.DataBindings.Add("Text", bsOrderHeader, "ExchangeRate");
            dtpOrderDate.DataBindings.Add("Text", bsOrderHeader, "OrderDate");
            cbxPriceCode.DataBindings.Add("SelectedIndex", bsOrderHeader, "PriceCode");
            dgvItems.DataSource = bsOrderDetail;

enter code here

关于添加新记录:

DataRow drOrderHeader = dsOrders.Tables["dtOrderHeader"].NewRow();
            drOrderHeader["ID"] = (maxID + 1);
            dsOrders.Tables["dtOrderHeader"].Rows.Add(drOrderHeader);
            DataRow drOrderDetail = dsOrders.Tables["dtOrderDetail"].NewRow();
            drOrderDetail["OrderId"] = (maxID + 1);
            dsOrders.Tables["dtOrderDetail"].Rows.Add(drOrderDetail);
            bsOrderHeader.DataSource = dsOrders.Tables["dtOrderHeader"];
            bsOrderDetail.DataSource = dsOrders.Tables["dtOrderDetail"];

当我单击添加新行按钮时,bindingsource.count 属性显示已添加新记录,但 winform 控件仍保留在同一记录上,我无法滚动到新创建的记录,bindingsource.movelast 也停止工作。

请问有什么建议吗?我需要滚动到新添加的记录/行,清除所有 winform 文本框并准备输入新记录的数据,除了我生成的 OrderId 和创建时在此代码中的数据

更新:对添加按钮进行了更改,但未成功

newOrderId = Convert.ToInt32(dsOrders.Tables["dtOrderHeader"].Compute("max(ID)", string.Empty)) + 1;
            DataRow drOrderHeader = dsOrders.Tables["dtOrderHeader"].NewRow();
            drOrderHeader["ID"] = (newOrderId);
            dsOrders.Tables["dtOrderHeader"].Rows.Add(drOrderHeader);
            DataRow drOrderDetail = dsOrders.Tables["dtOrderDetail"].NewRow();
            drOrderDetail["OrderId"] = (newOrderId);
            dsOrders.Tables["dtOrderDetail"].Rows.Add(drOrderDetail);
            bsOrderHeader.Position = bsOrderHeader.Find("ID", newOrderId);

【问题讨论】:

    标签: c# winforms datagridview dataset bindingsource


    【解决方案1】:

    正如您已经发现的,数据绑定会检测您在底层数据源中所做的更改,因此有以下两行:

    bsOrderHeader.DataSource = dsOrders.Tables["dtOrderHeader"];
    bsOrderDetail.DataSource = dsOrders.Tables["dtOrderDetail"];
    

    是多余的。不仅如此,第二个错误地更改了bsOrderDetail 的数据源类型。所以只需删除它们。

    为了将 UI 重新绑定到新添加的记录,您只需将 bsOrderHeaderPosition 属性设置为新记录的索引,如下所示:

    bsOrderHeader.Position = bsOrderHeader.Find("ID", drOrderHeader["ID"]);
    

    数据绑定基础架构将自动重新绑定主控件和(通过DataRelation)详细网格视图。

    编辑:这是完整的工作演示。如果您的代码更新后无法正常工作,应该是帖子中没有显示的其他代码部分造成的。

    using System;
    using System.Data;
    using System.Windows.Forms;
    
    namespace Samples
    {
        static class Program
        {
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                var form = new Form();
    
    
                DataSet dsOrders = new DataSet("dsOrders");
    
                //SqlDataAdapter daOrderHeader;// = new SqlDataAdapter();
                //SqlDataAdapter daOrderDetail;// = new SqlDataAdapter();
    
                BindingSource bsOrderHeader = new BindingSource();
                BindingSource bsOrderDetail = new BindingSource();
    
                DataTable dtOrderHeader = new DataTable("dtOrderHeader");
                DataTable dtOrderDetail = new DataTable("dtOrderDetail");
    
                dsOrders.Tables.Add(dtOrderHeader);
                dsOrders.Tables.Add(dtOrderDetail);
    
                //daOrderHeader = DataAdapterOrderHeader();
                //daOrderDetail = DataAdapterOrderDetail();
    
                //daOrderHeader.Fill(dtOrderHeader);
                //daOrderDetail.Fill(dtOrderDetail);
                dtOrderHeader.Columns.Add("ID", typeof(int));
                dtOrderHeader.Columns.Add("Name", typeof(string));
                dtOrderHeader.Columns.Add("TaxRate", typeof(decimal));
                dtOrderHeader.Columns.Add("Shipping", typeof(string));
                dtOrderHeader.Columns.Add("ExchangeRate", typeof(decimal));
                dtOrderHeader.Columns.Add("OrderDate", typeof(DateTime));
                dtOrderHeader.Columns.Add("PriceCode", typeof(int));
    
                dtOrderHeader.PrimaryKey = new[] { dtOrderHeader.Columns["ID"] };
    
                dtOrderDetail.Columns.Add("OrderId", typeof(int));
                dtOrderDetail.Columns.Add("Quantity", typeof(decimal));
    
                ////Set up a master-detail relationship between the DataTables
                DataColumn keyOrderHeaderColumn = dsOrders.Tables["dtOrderHeader"].Columns["ID"];
                DataColumn foreignKeyOrderDetailColumn = dsOrders.Tables["dtOrderDetail"].Columns["OrderId"];
                var rel = dsOrders.Relations.Add("rOrders", keyOrderHeaderColumn, foreignKeyOrderDetailColumn);
    
                bsOrderHeader.DataSource = dsOrders;
                bsOrderHeader.DataMember = "dtOrderHeader";
                bsOrderDetail.DataSource = bsOrderHeader;
                bsOrderDetail.DataMember = "rOrders";
    
                var splitView = new SplitContainer { Dock = DockStyle.Fill, Parent = form };
                var tbxOrderNo = new TextBox();
                var tbxCustomer = new TextBox();
                var tbxTaxRate = new TextBox();
                var tbxShipping = new TextBox();
                var tbxExchangeRate = new TextBox();
                var dtpOrderDate = new DateTimePicker();
                int y = 8;
                foreach (var c in new Control[] { tbxOrderNo, tbxCustomer, tbxTaxRate, tbxShipping, tbxExchangeRate, dtpOrderDate })
                {
                    c.Top = y;
                    c.Left = 16;
                    splitView.Panel1.Controls.Add(c);
                    y = c.Bottom + 8;
                }
    
                var dgvItems = new DataGridView { Dock = DockStyle.Fill, Parent = splitView.Panel2 };
    
                tbxOrderNo.DataBindings.Add("Text", bsOrderHeader, "ID");
                tbxCustomer.DataBindings.Add("Text", bsOrderHeader, "Name");
                tbxTaxRate.DataBindings.Add("Text", bsOrderHeader, "TaxRate");
                tbxShipping.DataBindings.Add("Text", bsOrderHeader, "Shipping");
                tbxExchangeRate.DataBindings.Add("Text", bsOrderHeader, "ExchangeRate");
                dtpOrderDate.DataBindings.Add("Text", bsOrderHeader, "OrderDate");
                //cbxPriceCode.DataBindings.Add("SelectedIndex", bsOrderHeader, "PriceCode");
                dgvItems.DataSource = bsOrderDetail;
    
    
                Func<DataRow> addOrder = () =>
                {
                    var maxOrderId = dsOrders.Tables["dtOrderHeader"].Compute("max(ID)", string.Empty);
                    int newOrderId =  (maxOrderId != null && maxOrderId != DBNull.Value ? Convert.ToInt32(maxOrderId) : 0) + 1;
                    DataRow drOrderHeader = dsOrders.Tables["dtOrderHeader"].NewRow();
                    drOrderHeader["ID"] = newOrderId;
                    dsOrders.Tables["dtOrderHeader"].Rows.Add(drOrderHeader);
                    DataRow drOrderDetail = dsOrders.Tables["dtOrderDetail"].NewRow();
                    drOrderDetail["OrderId"] = newOrderId;
                    dsOrders.Tables["dtOrderDetail"].Rows.Add(drOrderDetail);
                    return drOrderHeader;
                };
    
                for (int i = 0; i < 5; i++) addOrder();
    
                var addButton = new Button { Dock = DockStyle.Bottom, Parent = form, Text = "Add" };
                addButton.Click += (sender, e) =>
                {
                    var drOrderHeader = addOrder();
                    bsOrderHeader.Position = bsOrderHeader.Find("ID", drOrderHeader["ID"]);
                };
    
                Application.Run(form);
            }
        }
    }
    

    【讨论】:

    • 伊万,感谢您帮助我。我已经修改了我的代码(请参阅更新),但我得到了相同的结果,它保留在我单击添加按钮后它所在的记录上,并且 bsOrderHeader.MoveLast 停止工作。
    • 这很奇怪。查看编辑并检查未显示的代码。
    • 感谢伊万,它成功了。我还有另一个问题,我的表单上的一个控件是一个复选框和另一个组合框,它们都必须在 DataTable 中设置默认值,(dtOrderHeader.Columns["Paid"].DefaultValue = 0; dtOrderHeader.Columns["PriceCode"].DefaultValue = 0;) 直到我修复它它破坏了绑定源导航并且不会t 滚动到新添加的记录。无论如何,再次感谢,非常感谢您的帮助。
    • 我也有这个问题。绑定到 CheckBox.Checked 属性的列。我的解决方案是在添加行时简单地初始化列值。为每个超级顾问方法设置 DefaultValue 也可以。
    猜你喜欢
    • 1970-01-01
    • 2011-10-17
    • 1970-01-01
    • 2012-11-06
    • 2023-03-31
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    相关资源
    最近更新 更多