【问题标题】:C# How do i change a label text from another formC#如何从另一个表单更改标签文本
【发布时间】:2014-11-27 22:49:08
【问题描述】:

所以我有两种形式。

表格 1 是我的主要表格,表格 2 是我在文本框中输入文本的地方,以显示在表格 1 的标签上。“确认”按钮和实际更改标签的输入文本也在表格上2 需要保持这种状态。

由于某种原因,这不起作用。

Form 2 有一个文本框和一个按钮,当我按下按钮时,它会改变指定字符串的字符串值。
此字符串链接到表单 1 上的标签。字符串正在更改,所以这不是问题,我通过添加一个按钮确认了这一点,该按钮会弹出一个显示新字符串值的消息框。

在寻找答案时,我发现这一定是某种令人耳目一新的问题,我尝试了很多方法都没有成功。只有那些将我的按钮放在表单 1 而不是 2 上的方法才有效。

我已经在谷歌上搜索了 3 个小时来解决这个问题,但要么这些方法不起作用,要么他们将我的按钮从表单 2 更改为我的主表单(表单 1)。

请不要说我懒惰,我真的找不到有效的方法!

编辑:

代码

GameScreen.cs

namespace _2pGame
{   
    public partial class GameScreen : Form
    {     
        public  GameScreen()
        {
            InitializeComponent();

            P1NameLabel.Text = gm.P1Name;
            P1ClassLabel.Text = gm.P1Class;
            P2NameLabel.Text = gm.P2Name;
            P2ClassLabel.Text = gm.P2Class;                
        }       

        private void PlayerInfoButton_Click(object sender, EventArgs e)
        {
            PlayerInfo playerinfoload = new PlayerInfo();
            playerinfoload.Show();
        }
   }    

}

PlayerInfo.cs

namespace _2pGame 
{       
    public partial class PlayerInfo : Form 
    { 
        public PlayerInfo() 
        {
            InitializeComponent();        
        }

        public void ConfirmPlayerInfo_Click(object sender, EventArgs e)
        {
            gm.P1Class = P1ClassChoice.Text;
            gm.P1Name = P1TextBox.Text;
            gm.P2Class = P2ClassChoice.Text;
            gm.P2Name = P2TextBox.Text;                     
        }   
    }
}

Refs.cs

namespace _2pGame
{    
    public partial class gm
    {        
        public static string 
        P1Class,
        P2Class,
        P1Name,
        P2Name;        
    }
}

【问题讨论】:

  • 您真的应该发布显示这种错误行为的实际代码(或者如果它太长,则发布一个编辑过的代码)
  • 您将字符串链接到表单 1 上的标签的方式很可能有问题。仅仅因为您的字符串更改并不意味着它也会更改标签。我们需要查看代码。

标签: c# forms text


【解决方案1】:

处理这种众所周知的情况的一种方法是通过委托....

在你的 PlayerInfo 表单中声明

public partial class PlayerInfo : Form 
{ 
    // define the delegate type (a parameterless method that returns nothing)
    public delegate void OnConfirmPlayer();

    // declare a public variable of that delegate type
    public OnConfirmPlayer PlayerConfirmed;

    .....

    public void ConfirmPlayerInfo_Click(object sender, EventArgs e)
    {
        gm.P1Class = P1ClassChoice.Text;
        gm.P1Name = P1TextBox.Text;
        gm.P2Class = P2ClassChoice.Text;
        gm.P2Name = P2TextBox.Text;

        // Check is someone is interested to be informed of this change
        // If someone assign a value to the public delegate variable then
        // you have to call that method to let the subscriber know 
        if (PlayerConfirmed != null) 
            PlayerConfirmed();
    }
}

然后在您的 GameScreen 表单中,在显示 PlayerInfo 表单之前,将 public PlayerInfo.PlayerConfirmed 设置为 GameScreen 表单类中的方法

private void PlayerInfoButton_Click(object sender, EventArgs e)
{
    PlayerInfo playerinfoload = new PlayerInfo();

    // Subscribe to the notification from PlayerInfo instance
    playerinfoload.PlayerConfirmed += PlayerHasBeenConfirmed;

    playerinfoload.Show();
}

// Method that receives the notification from PlayerInfo 
private void PlayerHasBeenConfirmed()
{
     P1NameLabel.Text = gm.P1Name;
     P1ClassLabel.Text = gm.P1Class;
     P2NameLabel.Text = gm.P2Name;
     P2ClassLabel.Text = gm.P2Class; 
}

这种方法的优点是避免了 GameScreen 和 PlayerInfo 之间的耦合。无需在 PlayerInfo 中知道 GameScreen 表单的存在及其属性的名称。您只需发布一个委托,订阅者可以注册以了解更改并让订阅者根据自己的代码进行操作。

【讨论】:

  • 感谢这项工作!尽管我不完全理解它,但我会使用它。但这需要经过一些研究!
  • 关键字delegate 允许我们以与使用关键字class 相同的方式定义类型。再次,这种类型用于定义变量,就像您对类所做的那样。这种类型不是属性和方法,而是对方法的引用。一旦你有了一个委托类型,你就可以声明这个类型的变量,并用 delegate variable += functioname 来给它们赋值。此时您可以使用该变量来调用该方法。 delegates C# Programming Guide
  • 关于线程和线程安全还有一些话要说,仅此代码不能保证,但现在可能不符合上下文。
【解决方案2】:

您需要对主表单的引用并在每次需要更新时分配文本框值。

public partial class PlayerInfo : Form 
{ 
    private readonly GameScreen _main;

    public PlayerInfo(GameScreen main) 
    {
        _main = main;
        InitializeComponent();        
     }

    public void ConfirmPlayerInfo_Click(object sender, EventArgs e)
    {
        gm.P1Class = P1ClassChoice.Text;
        gm.P1Name = P1TextBox.Text;
        gm.P2Class = P2ClassChoice.Text;
        gm.P2Name = P2TextBox.Text;

        main.P1NameLabel.Text = gm.P1Name;
        main.P1ClassLabel.Text = gm.P1Class;
        main.P2NameLabel.Text = gm.P2Name;
        main.P2ClassLabel.Text = gm.P2Class;  

    }
}

还需要在创建 PlayerInfo 表单时传递引用

private void PlayerInfoButton_Click(object sender, EventArgs e)
    {
        PlayerInfo playerinfoload = new PlayerInfo(this); //pass ref to self
        playerinfoload.Show();
    }

请注意,还有其他更好的方法可以做到这一点,但这是我能想到的最简单的方法。 如果您想要更好的东西,您可能可以查看事件或中介模式。

【讨论】:

  • 感谢您的努力,方法有效。但看到了史蒂夫代码的潜力,我将使用他的。
  • 是的,Steve 的代码绝对是更好的方法
猜你喜欢
  • 1970-01-01
  • 2021-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多