【问题标题】:Opening a winform from a user control and passing back values to the usercontrol从用户控件打开一个winform并将值传回给用户控件
【发布时间】:2010-02-05 23:09:28
【问题描述】:

我想知道是否可以让用户控件打开一个允许用户在其上选择选项的 winform,然后当他关闭表单时 - 他选择的选项/值返回给用户控件?

【问题讨论】:

  • 请您澄清一下您是指 WinForms UserControl 还是 Web 应用程序 UserControl。
  • 我只使用 winforms
  • 我宁愿建议您在用户控件内部创建一个接受委托的方法(其返回类型可以是您希望用户控件使用的返回值的自定义结构)。然后创建一个方法(基于委托),该方法可以显示表单(或根本不显示它)并返回用户控件期望的值。有意义吗?
  • 不是真的!你能用一个基本的例子详细说明吗!?

标签: c# winforms user-controls


【解决方案1】:

为什么不在对话框表单上创建一些公共属性,并在对话框关闭后从 UserControl 访问它们?

public class OptionsForm : Form
{
    // ...

    public string Option1 { get; set; }
    public bool Option2 { get; set; }
}

然后,在 UserControl 中:

public void ShowOptionsForm()
{
    using (var form = new OptionsForm())
    {
        if (form.ShowDialog() == DialogResult.OK)
        {
            var option1Value = form.Option1;
            var option2Value = form.Option2;

            // use option values...
        }
    }
}

【讨论】:

    【解决方案2】:

    请将此答案视为对 Steve Greatrex 现在接受的答案的“扩展评论”:评论太长了,我想展示一些选项,添加一些“口味”。这根本不是对史蒂夫回答的“批评”,恕我直言,它击中了“靶心”。

    假设:如果我之前阅读过这个问题,我会通过对这些要点的评论来查询 OP:

    1. OP 没有指定要“显示”的表单是否以模态方式显示。

    2. OP 没有指定是否每次显示表单时都重新创建它,或者是否应该创建并重新使用它的一个实例。

    3. OP 写道“打开一个允许用户在其上选择选项的 winform ... snip ...“返回他选择的选项/值”:Steve 的代码并未准确显示属性如何暴露为Public 已设置,但我将假设 OP 可能意味着用户与显示的表单上的某些控件进行交互,并且他所指的“选项/值”是表单上控件的属性:比如最终用户在 TextBox 中键入一些文本,或者在 ListBox 中键入选定的索引,并将其 SelectionMode 设置为允许多选的两种选择之一。

    4. OP 没有说明是否希望表单(如果重复使用)保留最终用户与表单上的控件的最后一次交互的结果,如上所述。

      李>
    5. OP 没有说明 UserControl 显示的 Form 是否将其 Parent 属性设置为其他有效容器:我假设他们的意思是“无父”显示 Form。

    评论:

    1. 如果 OP 打算以模态方式显示表单:为了让史蒂夫的代码正常工作,必须将表单的“控制框”作为一个选项删除,并放置一个按钮在“DialogResult 属性设置为“OK”且“Click Event 关闭 Form”的表单上:如果不满足这些条件,Steve 代码中 ShowDialog 的结果将永远不会返回“OK”,并且属性值永远不会是放。注意:通过 'ControlBox 关闭表单将返回“取消”的 DialogResult。

    2. 重复使用显示的表单:如果我们假设表单可能会被重复使用,那么为什么不创建一次并根据需要“显示并关闭”呢?让我们考虑一下是否有充分的理由将创建的表单公开为 UserControl 的公共成员。

    考虑以下替代想法:尝试提出与史蒂夫的解决方案尽可能“不同”的解决方案:只是为了展示、探索选项。

    我们的“显示表单”将有一个 TextBox 和一个 ListBox 允许多选:我们的目标是公开 TextBox 中的 Text 和 ListBox 中当前选择的索引。

    1. Form 有一个 ControlBox :不需要 Button 来关闭,如上所述。

    2. Form 是否以模态方式显示都没有关系:在任何一种情况下都会以相同的方式设置属性。

    3. 要设置的公共属性将基于读取显示窗体上控件的当前状态。

    4. 表单被创建一次并公开为 Public :因此,“副作用”是当重新显示表单时,它将保留用户选择的先前结果等。当然还有其他方法可以让您在代码中轻松控制它,以使一个或所有控件再次“处女”。

    在我们命名为“DataEntryForm”的“显示表单”中:

    正如史蒂夫展示的那样,我们定义了要公开的公共属性;

    public string TextEntered { get; set; }
    
    public ListBox.SelectedIndexCollection LBSelection { get; set; }
    

    在表单关闭事件中,我们根据控件的状态更新属性:

    private void DataEntryForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        TextEntered = textBox1.Text;
        LBSelection = listBox1.SelectedIndices;
    }
    

    在 UserControl 我们创建一个类型为“DataEntryform”的公共属性(原因需要解释)

    public DataEntryForm theDataEntryForm { get; set; }
    

    我们在 UserControl 的 Load Event 中创建 DataEntryForm 的实例,并将其分配给 public Property

    private void UserControl1_Load(object sender, EventArgs e)
    {
        theDataEntryForm = new DataEntryForm();
    }
    

    此时,我们将把它留给 OP(和您)的想象,以想象何时显示 DataEntryForm 的实例。但是我们当然想演示在 Form 关闭后如何访问属性:所以我们在 UserControl 上放置了一个 Button:

        private void button2_Click(object sender, EventArgs e)
        {
            Console.WriteLine(theDataEntryForm.TextEntered);
            Console.WriteLine(theDataEntryForm.LBSelection.ToString());
        }
    

    注意:我们没有对 ListBox 选择的索引进行任何“花哨”的分析:但我们可以写出它是否为空,或者选择了多少项等。

    另外:我们没有处理如果 OP 想要在“显示的表单”关闭时采取一些行动的问题:这很简单:您只需订阅 UserControl 中 Form 的 FormClosed 事件,并在您的事件处理程序代码中执行您需要执行的操作。

    最后我们来问为什么要创建一个类型为 'DataEntryForm 的公共属性:

    好吧,只需考虑通过 UserControl 中的公共属性公开“显示的表单”:我们允许 UserControl 实例的潜在容器(可能是表单)也可以访问“显示形式” ...这可能很有价值,可以为我们节省一些重复的属性。

    因此,如果 UserControl1 在 Form1 上,并且 Form1 想知道“显示的表单”上 TextBox 的 Text 值:可以像这样访问它:

    this.userControl11.theDataEntryForm.TextEntered
    

    编辑:我的一个朋友写信给我表达他的观点,即允许“更高级别”容器直接访问嵌入在 UserControl 中的“组件”是“违反”良好 OOD 实践并破坏封装:他发布我是一张移动违规罚单:) 所以,请记住他的警告。从他的角度来看,属性应该在 UserControl 中以不同的名称复制,并且只有那些 UserControls 属性才可用于 UserControl 容器。我的偏见是在这里将“UserContro/Form”视为一个“复合对象”,由于该表单仅供 UserForm 使用,因此有理由不复制 Properties /Edit

    当然,由于我们都虔诚地这样做,我们已经忽略了检查所有可能为空的值。

    【讨论】:

      【解决方案3】:

      这里有一个简短的示例,说明您可以如何做到这一点。它不完整,您必须填写一些空白,但它应该让您了解如何解决您的问题。

      此代码位于您构建控件并形成控件的位置

      MyUserControl ctrl = new MyUserControl();
      Action<typeYouPassBack> callBack = myUserControl.FormCallBack;
      MyOptionForm form = new MyOptionForm(callBack);
      

      然后表单类必须看起来像这样:(重要的部分是动作参数)

      class MyOptionForm : Form
      {
        private readonly Action<typeYouPassBack> _callBack;
        public MyOptionForm(Action<typeYouPassBack> callBack)
        {
          _callBack = callBack;
          Close += form_Close;
        }
      
        privatre void form_close(object sender, EventARgs e)
        {
           typeYouPassBack postBackData = //populate the postback data
           _callBack(postBackData);
        }
      }
      

      Action 类型只是一个签名为 void f(T arg) 的委托。在上面的代码中,用户控件应该有一个名为“FormCallBack”的方法,当然,只要在将其分配给“回调”变量时使用正确的名称,它就可以命名为任何你喜欢的名称

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-18
        • 1970-01-01
        相关资源
        最近更新 更多