【问题标题】:Sending Data from child form to Parent Form TextBox将数据从子窗体发送到父窗体文本框
【发布时间】:2010-10-16 22:04:30
【问题描述】:

我有一个父表单,其中包含一个包含名字、姓氏等的“HUD”。其中一个子表单是搜索表单。当用户从 DataGrid 中显示的结果中选择一个成员时,我希望相关信息填写在 HUD 中。我创建了一个 HUD 类,其中包含每个值的变量和一个名为 UpdateHUD() 的方法。我不确定如何让这个工作。我参考了包含 HUD 的父表单的搜索表单,如下所示:

public frmWWCModuleHost _frmWWCModuleHost;

这是我用来嵌入表单的代码。我没有使用 MDI。

 public static void ShowFormInContainerControl(Control ctl, Form frm)
    {
        frm.TopLevel = false;
        frm.FormBorderStyle = FormBorderStyle.None;
        frm.Dock = DockStyle.Fill;
        frm.Visible = true;
        ctl.Controls.Add(frm);
    }

这是我在 Cell 上运行的代码 单击搜索表单。这是在我尝试实现 HUD 类之前。

private void dgvSearchResults_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        _frmWWCModuleHost = new frmWWCModuleHost();
        _frmWWCModuleHost.tbxHUD_LastName.Text = dgvSearchResults.CurrentRow.Cells[1].FormattedValue.ToString();
        _frmWWCModuleHost.tbxHUD_LastName.Invalidate();
        _frmWWCModuleHost.FormPaint();
    }

提前致谢!

~帕特里克


编辑


dgvSearchResults_CellContentClick 现在是最新的。当我逐步执行此代码时,它会在此处获得正确的值,但它永远不会更新实际的 HUD。


编辑 2


我的问题是我声明一个新的 frmWWCModuleHost 而不是将 ref 传递给现有的?我对此的理解还很薄弱。


编辑 3


我通过执行以下操作“解决”了这个问题:在我声明子表单的父表单上,我将 this 作为参数传递。然后在子窗体的构造函数中添加了 _frmWWCModuleHost = m_parent;我的父窗体上有一个 UpdateHUD() 方法,我从子窗体的 _CellClick 事件中调用它。

现在重新表述我的问题;这样做有什么明显的错误吗?

【问题讨论】:

    标签: c# winforms .net-3.5


    【解决方案1】:

    有时在这种情况下,我会创建一个与我想在父类中调用的方法的签名相匹配的委托(我认为在您的情况下是 UpdateHUD),然后传递该委托的一个实例(即对 UpdateHUD 的引用)到子表单(在这种情况下为搜索表单)。当子表单完成接受输入时,它会使用表单上收集的数据调用委托。

    因此,假设 UpdateHUD 是父表单中的一个方法,看起来像这样。

    private void UpdateHUD(string firstName, string lastName) {
        //...
    }
    

    您将创建一个具有相同签名的委托,如下所示。

    public delegate void HUDUpdateHandler(string firstName, string lastName);
    

    然后您将向子表单的构造函数添加 HUDUpdateHandler 参数并将其存储在私有字段中(例如,this.handler = handler)。当您的子表单准备好发回其数据时,您将调用子表单的私有字段(例如this.handler.Invoke(firstNameTextBox.Text, lastNameTextBox.Text))。这将使用子类中的值在您的父类中调用 UpdateHUD,您无需公开任何内容。

    我发现这种方法比引发和捕获事件更容易实现,并且它允许您将父类的内部保持在内部。

    【讨论】:

    • 我是在父表单还是子表单中创建代理?谢谢!
    • 你可以在任何地方创建它,只要它在父母和孩子的范围内。我通常在与父类相同的代码文件中创建它,但我不会将它嵌套在父类本身中。不过,这并不重要,只要它在范围内即可。
    【解决方案2】:

    当子表单搜索完成时,引发“SearchCompleted”事件。然后任何东西(包括父表单)都可以订阅该事件并检索详细信息。

    示例见以下记事本代码:

    class ParentForm
    {
        private readonly ChildForm childForm;
    
        public ParentForm()
        {
            InitializeComponent();
    
            childForm = new ChildForm();
    
            childForm.SearchCompleted += childForm_SearchCompleted;
        }
    
        private void childForm_SearchCompleted(object sender, SearchCompletedEventArgs e)
        {
            // Update the display
            lblName.Text = e.DataToDisplay;
        }
    }
    
    class ChildForm
    {
        public event EventHandler<SearchCompletedEventArgs> SearchCompleted;
    
        private void Search(string query)
        {
            // Do the searching
    
            OnSearchCompleted(new SearchCompletedEventArgs([arg values]));
        }
    
        public void OnSearchCompleted(SearchCompletedEventArgs args)
        {
            if (SearchCompleted != null)
            {
                SearchCompleted(this, args);
            }
        }
    }
    

    【讨论】:

    • 我必须很密集,但是如何在单元格或行单击时执行此操作?我无法在 SearchComplete 上执行此操作,因为返回的结果不止一个。
    • 您从单元格/行单击调用 OnSearchCompleted,从当前选定的行/单元格中取出数据。
    • 哎呀!我会试试看。
    • 我显然还没有做到这一点。我在使用这种方法时遇到了错误。也许我正在把你的代码写成文字。我假设它在哪里声明了 arg 值,我应该把这些值传递出去。
    • 是的。也许您只是传递链接到网格中选定行的 DataRow 或 Domain Model 对象。这样,观察事件的人就可以随心所欲地做自己喜欢的事了。
    【解决方案3】:

    在 .NET 中,表单与其他所有事物一样都是对象,因此您应该从这些术语中考虑问题。

    这样,子表单将需要访问父表单。您可以通过构造函数、方法或字段/属性将父表单引用传递给子表单来提供这一点(尽管构造函数最有意义)。

    然后,您可以从孩子更改父表单中的值。

    但是我会说这不是最好的主意。相反,孩子应该公开一个表明数据发生变化的事件(以及获取该数据的机制),然后父母应该订阅该事件并在触发时使用数据更新自己。

    【讨论】:

    • 我以为我在上面的例子中这样做了还是我弄错了?
    • 好的,我想这就是我现在正在做的事情。在构造函数中。你能详细说明为什么我不应该这样做吗?谢谢!
    • @Mr_Mom:嗯,这是关于关注点分离。通过您的方法,子窗体对父窗体有深入的了解,这是唯一支持的关系。对于事件,孩子不关心谁在响应数据,这使得类更易于重用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-29
    • 2017-09-04
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多