跨窗体调用UserControl数据保存至数据库空值异常求助
问题:主窗体按钮触发UserControl保存数据为空,内部按钮正常
问题描述
通过主窗体的Save按钮触发UserControl中的数据保存到数据库,主窗体已嵌入该UserControl且包含Save按钮。代码运行无报错,但数据库存入的是空值;将Save按钮放置在UserControl内部时,功能完全正常。
相关代码
窗体代码(原错误代码)
namespace REMAS.Forms.Account { public partial class frmCreateFixedAssetCategories : Form { SqlConnection conn = new SqlConnection("Server=localhost;Database=TESTCRUD;User Id=sa;Password=123456"); SqlCommand cmd; SqlDataAdapter adapter; SqlDataReader reader; DataTable dt; string sql, sAction; int iID; private uctInformation uctInformationInstance; public frmCreateFixedAssetCategories() { InitializeComponent(); uctInformationInstance = new uctInformation(); // Assuming you have a panel or some container to host the UserControl } private void btnSaveActions_Click(object sender, EventArgs e) { uctInformationInstance.savedata(); } } }
UserControl代码
namespace REMAS.Forms.Purchase { public partial class uctInformation : UserControl { SqlConnection conn = new SqlConnection("Server=localhost;Database=TESTCRUD;User Id=sa;Password=123456"); SqlCommand cmd; SqlDataAdapter adapter; SqlDataReader reader; DataTable dt; string sql, sAction; int iID; public uctInformation() { InitializeComponent(); } private void uctInformation_Load(object sender, EventArgs e) { ClearText(); } void ClearText() { txbAddresses.Clear(); txbFixedPhone.Clear(); txbFaxuctInf.Clear(); txbMobileuctInf.Clear(); txbEmailuctInf.Clear(); txbWebuctInf.Clear(); txbRegCode.Clear(); txbTaxN.Clear(); txbLanguageuctInf.Clear(); txbAccOwner.Clear(); txbTeamuctInf.Clear(); cmbCategoryuctInf.Items.Clear(); cmbIndustryuctInf.Items.Clear(); cmbSourceuctInf.Items.Clear(); cmbDeptuctInf.Items.Clear(); cmbCompaniesAssoci.Items.Clear(); nudTurnoveructInf.Value = 0; nudEmployeesuctInf.Value = 0; nudPaymentuctInf.Value = 0; rtbNotes.Clear(); } private void txbFixedPhone_KeyPress(object sender, KeyPressEventArgs e) { e.Handled = !char.IsDigit(e.KeyChar) && e.KeyChar != (char)Keys.Back; } private void txbFaxuctInf_KeyPress(object sender, KeyPressEventArgs e) { e.Handled = !char.IsDigit(e.KeyChar) && e.KeyChar != (char)Keys.Back; } private void txbMobileuctInf_KeyPress(object sender, KeyPressEventArgs e) { e.Handled = !char.IsDigit(e.KeyChar) && e.KeyChar != (char)Keys.Back; } public void savedata() { try { if (conn.State == ConnectionState.Closed) conn.Open(); sql = "sp_InsertInformation"; cmd = new SqlCommand(sql, conn); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@addresses", txbAddresses.Texts.ToString()); cmd.Parameters.AddWithValue("@fixedphone", txbFixedPhone.Texts.ToString()); cmd.Parameters.AddWithValue("@fax", txbFaxuctInf.Texts.ToString()); cmd.Parameters.AddWithValue("@mobilephone", txbMobileuctInf.Texts.ToString()); cmd.Parameters.AddWithValue("@email", txbEmailuctInf.Texts.ToString()); cmd.Parameters.AddWithValue("@website", txbWebuctInf.Texts.ToString()); cmd.Parameters.AddWithValue("@category", cmbCategoryuctInf.Texts.ToString()); cmd.Parameters.AddWithValue("@industrisector", cmbIndustryuctInf.Texts.ToString()); cmd.Parameters.AddWithValue("@turnover", nudTurnoveructInf.Text.ToString()); cmd.Parameters.AddWithValue("@employee", nudEmployeesuctInf.Text.ToString()); cmd.Parameters.AddWithValue("@source", cmbSourceuctInf.Texts.ToString()); cmd.Parameters.AddWithValue("@deptdiv", cmbDeptuctInf.Texts.ToString()); cmd.Parameters.AddWithValue("@regcode", txbRegCode.Texts.ToString()); cmd.Parameters.AddWithValue("@taxn", txbTaxN.Texts.ToString()); cmd.Parameters.AddWithValue("@paymentdelay", nudPaymentuctInf.Text.ToString()); cmd.Parameters.AddWithValue("@lang", txbLanguageuctInf.Texts.ToString()); cmd.Parameters.AddWithValue("@accowner", txbAccOwner.Texts.ToString()); cmd.Parameters.AddWithValue("@team", txbTeamuctInf.Texts.ToString()); cmd.Parameters.AddWithValue("@companyassoci", cmbCompaniesAssoci.Texts.ToString()); cmd.Parameters.AddWithValue("@note", rtbNotes.Text.ToString()); cmd.ExecuteNonQuery(); conn.Close(); MessageBox.Show("Insert data successfully", "Information"); } catch (Exception ex) { MessageBox.Show(ex.Message, "Information"); conn.Close(); return; } } } }
现象截图
数据库空值结果

Visual Studio设计界面

原因分析
核心问题是窗体代码中手动new了一个新的uctInformation实例,但这个实例和设计界面中拖入的UserControl不是同一个对象。用户输入的内容都在设计界面生成的实例里,而你调用的是自己new的空实例的savedata方法,自然会向数据库存入空值。
解决方案
场景1:设计界面拖入UserControl
直接使用设计界面自动生成的UserControl实例(注意设计时给UserControl设置的Name属性,比如默认是uctInformation1),删除手动new的代码:
namespace REMAS.Forms.Account { public partial class frmCreateFixedAssetCategories : Form { SqlConnection conn = new SqlConnection("Server=localhost;Database=TESTCRUD;User Id=sa;Password=123456"); SqlCommand cmd; SqlDataAdapter adapter; SqlDataReader reader; DataTable dt; string sql, sAction; int iID; public frmCreateFixedAssetCategories() { InitializeComponent(); // 移除手动new实例的代码 } private void btnSaveActions_Click(object sender, EventArgs e) { // 调用设计界面中UserControl实例的savedata方法 uctInformation1.savedata(); } } }
场景2:动态添加UserControl到容器
如果是动态创建并添加UserControl到容器(比如Panel),需要保存添加到容器的那个实例的引用,而不是重新new:
namespace REMAS.Forms.Account { public partial class frmCreateFixedAssetCategories : Form { SqlConnection conn = new SqlConnection("Server=localhost;Database=TESTCRUD;User Id=sa;Password=123456"); SqlCommand cmd; SqlDataAdapter adapter; SqlDataReader reader; DataTable dt; string sql, sAction; int iID; private uctInformation uctInformationInstance; public frmCreateFixedAssetCategories() { InitializeComponent(); // 创建实例并添加到容器 uctInformationInstance = new uctInformation(); panel1.Controls.Add(uctInformationInstance); uctInformationInstance.Dock = DockStyle.Fill; } private void btnSaveActions_Click(object sender, EventArgs e) { // 调用保存的实例的方法 uctInformationInstance.savedata(); } } }
内容的提问来源于stack exchange,提问作者Yud
相关产品推荐
相关产品推荐

