【问题标题】:How to change label number and text with method from another Class?如何使用另一个类的方法更改标签编号和文本?
【发布时间】:2017-05-29 09:15:47
【问题描述】:

我的 Form1 上有不同的标签,并想使用相同的方法更改单个标签的文本。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Class1 change = new Class1();
        change.ChangeLabelText();
    }

    public void ChangeLabel(string msg, Label label)
    {
        if (label.InvokeRequired)
            label.Invoke(new MethodInvoker(delegate { label.Text = msg; }));
        else
            label.Text = msg;
    }
}

如何根据需要传递 label1 或 label2?

class Class1
{
    public void ChangeLabelText()
    {
        Form1 frm1 = new Form1();
        frm1.ChangeLabel("Surname", label2);           
    }
}

label2 带有红色下划线:NOT EXIST IN THE ACTUAL CONTEST

【问题讨论】:

  • 为什么需要给函数发送标签?只需在表单中使用存在标签
  • 您的label2Form1 的一部分,这就是Class1 不知道它的原因。你可以做的是公开标签,然后像这样传递它们:frm1.label2

标签: c# class methods label


【解决方案1】:

我不知道您尝试更改标签的上下文是什么...但是我看到您的示例代码有一些观察结果。

首先,对于您的问题,其中一种方法可能如下,

private void button1_Click(object sender, EventArgs e)
{
    Class1 change = new Class1(this);
    change.ChangeLabelText();
}

public void ChangeLabel(string msg, Label label)
{
    if (label.InvokeRequired)
        label.Invoke(new MethodInvoker(delegate { label.Text = msg; }));
    else
        label.Text = msg;
}

// dont allow UI elements to be accessed directly from outide
public string Fullname
{
    get
    {
        return label1.Text;
    }
    set
    {
        label1.Text = value;
    }
}

// dont allow UI elements to be accessed directly from outide
public string Surname
{
    get
    {
        return label2.Text;
    }
    set
    {
        label2.Text = value;
    }
}

您会看到 Class1 的对象获得对 Form1 的引用。 在 Class1.ChangeLabelText 中,您可以执行以下操作,

class Class1
{
    Form1 _mainForm;
    public Class1(Form1 form)
    {
        _mainForm = form;    
    }
    public void ChangeLabelText()
    {
        //Form1 frm1 = new Form1();
        //frm1.ChangeLabel("Surname", label2);
        _mainForm.Surname = "Surname";
    }
}

看到样品后的观察

  1. 最好不要公开/允许非所有者访问 UI 元素(在这种情况下,Form1 是所有者)
  2. 在 button1_Click 中,您已经在 Form1 实例(对象)中,但是在 ChangeLabelText 中,您正在尝试创建 Form1 的另一个实例。

希望这对您有所帮助。

【讨论】:

  • 我会冷静地研究你的代码。我的意图是做 VB 上可以轻松完成的事情,从不同于 MainWindow 的类中完成,如下所示:MainWindow.TextBox1.Clear()MainWindow.TextBox2.Clear()MainWindow.Label3.Visible = TrueMainWindow.TextBox1.Font = New Font("Microsoft Sans Serif", 20)MainWindow.Label7.Text = "Done correctly!"MainWindow.Label7.Text = "Errors, try again"
  • 我理解你的代码,就像我现在拥有的一样:MainWindow public void CambiaTestoEtichette(string nuovoTesto) { label8.Text=nuovoTesto; } 上的 5 种不同方法,每一种都可以更改不同标签上的文本。我想使用一种方法是发送标签号和文本
【解决方案2】:

另一种方法是让 Class1 引发一个 Event,其中包含标签的名称和将其更改为的字符串。您的表单将接收事件,找到标签本身,并更新值。这样 Class1 永远不需要对 Form1 或任何标签的引用。这仍然是一个糟糕的设计,因为您需要知道标签的名称,但无论如何这就是您要走的方向。

这是 Class1 的样子:

public class Class1
{

    public delegate void dlgChangeLabel(string lblName, string newValue);
    public event dlgChangeLabel ChangeLabel;

    public void ChangeLabelText()
    {
        if (ChangeLabel != null)
        {
            ChangeLabel("label2", "SurName");
        }
    }

}

回到 Form1,我们需要在创建 Class1 实例时订阅 ChangeLabel() 事件:

public partial class Form1 : Form
{

    private void button1_Click(object sender, EventArgs e)
    {
        Class1 change = new Class1();
        change.ChangeLabel += Change_ChangeLabel;
        change.ChangeLabelText();
    }

    private void Change_ChangeLabel(string lblName, string newValue)
    {
        // see if we have a Label with the desired name:
        Control[] matches = this.Controls.Find(lblName, true);
        if (matches.Length > 0 && matches[0] is Label)
        {
            Label lbl = (Label)matches[0];
            ChangeLabel(newValue, lbl); // update it in a thread safe way
        }
    }

    private void ChangeLabel(string msg, Label label)
    {
        if (label.InvokeRequired)
            label.Invoke(new MethodInvoker(delegate { label.Text = msg; }));
        else
            label.Text = msg;
    }

}

显示 Class1 的创建和在 Form Load() 期间连接其事件的替代版本,因此它不附加到按钮处理程序:

public partial class Form1 : Form
{

    private Class1 change = new Class1();

    private void Form1_Load(object sender, EventArgs e)
    {
        change.ChangeLabel += Change_ChangeLabel;
    }

    private void Change_ChangeLabel(string lblName, string newValue)
    {
        Control[] matches = this.Controls.Find(lblName, true);
        if (matches.Length > 0 && matches[0] is Label)
        {
            Label lbl = (Label)matches[0];
            ChangeLabel(newValue, lbl);
        }
    }

    private void ChangeLabel(string msg, Label label)
    {
        if (label.InvokeRequired)
            label.Invoke(new MethodInvoker(delegate { label.Text = msg; }));
        else
            label.Text = msg;
    }

}

现在您只需以某种方式在 Class1 中引发该事件。在你提出之前确保它有一个订阅者(不为空):

// in Class1
private void Foo()
{
    if (ChangeLabel != null)
    {
        ChangeLabel("label2", "SurName");
    }
}

【讨论】:

  • 这行得通,做我想做的事。真的我没有调用 Class1 的按钮,那么,如何更改代码以将 botton 内的部分移动到 Class1 中的 ChangeLabelText() 中?谢谢
  • 您需要连接该事件,所以您可能会在 Form Load() 时这样做?然后你只需要提出那个事件,我会在上面编辑并发布一个替代版本。
  • 非常感谢。以及如何使用其他调用相同方法 Class2、Class3 的类来覆盖 Class1 change = new Class1();....
  • 在这种情况下,您可能希望结合 Shankar 将 Form1 传递给这些类的方法,但让 Public 方法接收控件的 Name 并搜索它,如我的例子。
  • 非常感谢您的帮助,但我正在学习 C#,我的英语不太好。我公开了两个方法 Change_ChangeLabel 和 ChangeLabel。我不知道 Shankar 的方法(谷歌也没有帮助)。你能帮我更多吗?
【解决方案3】:

您需要在方法中将标签作为参数传递

class Class1
{
public void ChangeLabelText(Label lbl)
    {
    Form1 frm1 = new Form1();
    frm1.ChangeLabel("Surname", lbl);
    }
}

然后在您的按钮中单击 -

change.ChangeLabelText(label2);

【讨论】:

  • 我不能将 label2 放在按钮单击方法中,因为应该是 label7、label1 或 label5....我需要一种方法是发送标签编号和文本
【解决方案4】:
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Class1 change = new Class1();
        change.ChangeLabelText(this);
    }

    public void ChangeLabel(string msg, Label label)
    {
        if (label.InvokeRequired)
            label.Invoke(new MethodInvoker(delegate { label.Text = msg; }));
        else
            label.Text = msg;
    }
}

class Class1
{
    public void ChangeLabelText(System.Windows.Forms.Form form)
    {
        if(form != null)
        {
            var labelIdWhoseTextNeedsToChange = "label2"; // Or any dynamic logic to determine which label will have to be updated.
            var labelControl = form.Controls.Find(labelIdWhoseTextNeedsToChange, false);
            if(labelControl != null)
            {
                form.ChangeLabel("Surname", labelControl);
            }
        }
    }
}

【讨论】:

  • 在 Class1 public void ChangeLabelText(Control form) 上有错误:CS1061 控件不包含 findcontrol 定义。尝试使用 System.Web.UI 添加,但 UI 在 System.Web 上不存在
  • 对不起伙计,我犯了一个愚蠢的错误。将方法签名更改为public void ChangeLabelText(System.Windows.Form form),稍后您可以通过 form.Controls.Find() 方法找到该控件。例如 form.Controls.Find("label2", false); // 第二个参数是假的,因为我不想通过子控件搜索
  • 我已经在使用 System.Windows.Forms;将签名更改为 System.Windows.Forms 表单,因为 System.Windows.Forms 它是命名空间,但它用作类型
  • 应该是System.Windows.Forms.Form form 为了清楚起见,我添加了完整的命名空间。否则你可以添加 using 语句。
  • @MassimoD.N.我已经编辑了我的答案。请参考。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-05
相关资源
最近更新 更多