【问题标题】:Updating label in main form from user control从用户控件更新主窗体中的标签
【发布时间】:2012-04-03 07:32:56
【问题描述】:

在我当前的应用程序中,我有一个main form: frmMain,里面有一个statusstrip 和一个label: lblStatus。 我想从我的用户控件中更新该标签,当我单击相关按钮时,我将其添加到我的主窗体中:

ucBeheer ucBeheer = new ucBeheer();
splitContainer1.Panel2.Controls.Add(ucBeheer);

当我执行操作时,我想从我的usercontrol 内部更新lblStatus。我尝试将以下属性添加到我的主窗体中:

    public string updateStatus
    {
        get { return lblStatus.Text; }
        set { lblStatus.Text = value; }
    }

然后在我的用户控件中访问这样的方法:

        frmMain mainForm = new frmMain();
        mainForm.updateStatus = "This is a test";

但这不起作用,我知道这是因为我正在创建我的frmMain 的新对象,但我不知道如何解决这个问题?

我还找到了following way,带有Event Handler,但我不能这样做,因为我的用户控件实际上还没有在我的mainForm中,直到我通过单击按钮将它添加到那里,所以我没有参考。

所以我有点没有想法,我希望有人可以帮助我。 谢谢, 托马斯

编辑:所以我设法做到了以下方式:

        frmMain owningForm = (frmMain)this.Parent.Parent.Parent.Parent;
        owningForm.updateStatus = "This is a test";

但是this.Parent.Parent.Parent.Parent... 对我来说似乎并不是很好的编码,有没有其他方法可以获得最顶级的父母?

【问题讨论】:

    标签: c# .net winforms user-controls label


    【解决方案1】:

    您可以将这样的属性添加到您的用户控件,这样您就可以访问用户控件所在的 frmMain。

    public frmMain MainForm
    {
        get
        {
            var parent = Parent;
            while (parent != null && (parent as frmMain) == null)
            {
                parent = parent.Parent;
            }
            return parent as frmMain;
        }
    } 
    

    更新: 如果你只想要最顶层的父母,你可以使用这样的东西:

    public Control TopMostParent
    {
        get
        {
            var parent = Parent;
            while (parent.Parent != null)
            {
                parent = parent.Parent;
            }
            return parent;
        }
    } 
    

    或者甚至做一个扩展方法:

    public static Control TopMostParent(this Control control)
    {
        var parent = control.Parent;
        while (parent.Parent != null)
        {
            parent = parent.Parent;
        }
        return parent;
    } 
    

    【讨论】:

      【解决方案2】:

      您的控件和表单必须进行通信,因此需要“了解”另一个。实际上,这意味着给一个参考,给另一个参考。因此,您有 2 个选择:控件需要对表单的引用,或者表单需要对控件的引用。

      我这样做的方式是让表单订阅控件发布的事件。这是一个表单,它只引用了其中一个控件的方法。

      class StatusChangedEventArgs : EventArgs
      {
          public string Text { get; set; }
      }
      
      partial class MyControl : UserControl
      {
          public event EventHandler<StatusChangedEventArgs> StatusChanged = delegate { };
      
          public void RaiseStatusChanged( string message )
          {
              StatusChanged( this, new StatusChangedEventArgs { Text = "message" } );
          }
      }
      

      然后,在您的表单中订阅该事件:

      ...
      ucBeheer ucBeheer = new ucBeheer();
      ucBeheer.StatusChanged += HandleStatusChanged;
      splitContainer1.Panel2.Controls.Add(ucBeheer);
      ...
      
      partial class MyForm : Form
      {
          void HandleStatusChanged( object sender, StatusChangedEventArgs args )
          {
              lblStatus.Text = args.Text;
          }
      }
      

      【讨论】:

      • 感谢您的评论,但我真的不明白如何实现这一点?我应该把 StatusChangedEventArgs 类放在哪里,如何让它能够从我的标签中获取和设置文本?
      • 我添加了一个代码示例。只需在您需要控制时致电RaiseStatusChanged
      • 谢谢,这适用于我的大多数表单,但在某些情况下,我在usercontrol 中添加usercontrol,然后这将不起作用。 (我不确定在usercontrol 中添加usercontrol 是否是好的编码,但这是我发现能够正确导航的唯一方法)
      • 那么你有同样的情况,但是用一个父用户控件而不是一个窗体,所以你可以使用相同的技术。如果您使用 Parent.Parent... 找到您的 MyForm 实例,那么您的控件需要了解 MyForm 的实现,这听起来不对。 YMMV。
      【解决方案3】:

      您可以使用 Application.OpenForms FormCollection 按名称引用应用程序的主表单:

      frmMain owningForm = (frmMain)Application.OpenForms["frmMain"];
      
      owningForm.updateStatus = "This is a test";
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-15
        • 1970-01-01
        • 2011-03-28
        • 2012-08-11
        相关资源
        最近更新 更多