通过另一个类更新标签

时间:2015-02-14 02:43:09

标签: c# winforms visual-studio-2013

我试图在Run中调用方法script1。然后从script1调用方法alertwait尝试更新Form1中的statusLabel。但是这段代码有错误。

static Label status = this.Controls.Find("statusLabel", true).FirstOrDefault() as Label;

此代码仅适用于Form1。因为this在另一个类中返回错误。也许这是不正确的,你知道更好的解决方案。

P.S。我知道如何解决这个问题(见下文"不是最好的解决方案"),但代码将是~10-30个新行。

项目

Form1.cs的

public partial class Form1 : Form
{
    private void statusLabel_Click(object sender, EventArgs e)
    {
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        script1.Run();
        ...
        script30.Run();
    }
}

function.cs(常用功能)

public class function
{
    static Label statusLabel = this.Controls.Find("statusLabel", true).FirstOrDefault() as Label;

    static public void alert(string str)
    {
        statusLabel.Text = str;
    }

    static public void wait(int sec)
    {
        int i = 0;
        while (i++ < sec)
        {
            statusLabel.Text = "Wait: " + (sec+1-i).ToString();
            Thread.Sleep(1000);
        }
    }
}

script1.cs(script1,script2 ......它是大约30个迷你程序)

public class script1
{
    static public void Run()
    {
        function.alert("Script1 is running");
        function.wait(5);
        function.alert("Script1 is done");
    }
}

不是最佳解决方案

在function.cs中删除

static Label status = this.Controls.Find("statusLabel", true).FirstOrDefault() as Label;

Form1.cs的

public partial class Form1 : Form
{
    private void Form1_Load(object sender, EventArgs e)
    {
        script1.Run(this.statusLabel);
    }
}

function.cs

public class function
{
    private Label _statusLabel;

    public scriptClass(Label statusLabel)
    {
        _statusLabel = statusLabel;
    }
}

script1.cs(script1,script2 ......它是大约30个迷你程序)

public class script1
{

    static public void Run(Label statusLabel)
    {
        function _function = new function(statusLabel);
    }
}

1 个答案:

答案 0 :(得分:2)

statusLabel类拥有Form1对象,并且应由Form1类封装和隐藏。为了确保类的良好解耦以及正确的数据隐藏,只有statusLabel类应该直接访问它。它应该(默认情况下)能够通过名为this.Controls.Find()的字段访问它(即不需要调用function(也不应该从Controls类开始工作,因为该类也不是对象的所有者,也不是script1属性的所有者。

执行此操作的正确方法是StatusText类公开StatusTextChanged属性,以及属性值更改时引发的事件。实现该事件有两种规范方法:

  1. 实施名为class script1 { public static string StatusText { get; private set; } public static event EventHandler StatusTextChanged; static public void Run() { ChangeStatusText("Script1 is running"); function.wait(5); ChangeStatusText("Script1 is done"); } static void ChangeStatusText(string text) { StatusText = text; EventHandler handler = StatusTextChanged; if (handler != null) { handler(null, EventArgs.Empty); } } }
  2. 的活动
  3. 实施INotifyPropertyChanged界面
  4. 请注意,在您的示例中,#2不是一个选项,因为您使用静态类来实现脚本。恕我直言,由于各种原因,这是不可取的,但由于#1是一个非常好的解决方案,所以我不会说明这一点。 :)

    第一个看起来像这样:

    Form1

    然后在public partial class Form1 { private void Form1_Load(object sender, EventArgs e) { script1.StatusTextChanged += (sender1, e1) => statusLabel.Text = script1.Text; script1.Run(); ... script30.StatusTextChanged += (sender1, e1) => statusLabel.Text = script30.Text; script30.Run(); } }

    scriptX

    请注意,上述每个scriptX类都必须重新实现该事件。您可以改为创建一个基类,每个Form1类都继承,并且包含相关事件。然后Form1类只需要订阅一个基类事件。它还将解决或至少减少让事件处理程序订阅30个不同事件的问题。

    当然,在这种情况下,scriptX类将不知道哪个脚本正在更新文本,但在您的情况下这可能无关紧要。

    另请注意,如果 使{{1}}类非静态,则可能会再次遇到必须多次订阅的问题。但这更容易处理,因为在这种情况下你肯定会使用基类,所以很容易将“subscribe,run script,unsubscribe”逻辑推广到辅助方法中。