C# WinForms中Form2无法获取Form1填充的Spelers列表问题求助
问题:Form2中无法获取Form1填充的Spelers列表内容
我是编程新手(刚学完通用编程逻辑课程),正在用C# WinForms开发猜词游戏,Form1负责游戏设置(玩家数量、命名),用Spelers类实现面向对象,但Form2里访问Form1填充的Spelers列表时为空。
操作流程
- 默认加载Form1,输入玩家数量并命名,通过Spelers类方法将玩家添加到列表;
- 完成命名后关闭Form1并打开Form2(通过布尔开关在Program.cs中执行
Application.Run(form2)保证程序运行); - 在Form2中创建新的Spelers对象获取列表,但列表完全为空。
相关代码
Form1代码
using System; using System.Security.Cryptography.X509Certificates; using System.Windows.Forms; namespace Pictionary { public partial class Form1 : Form { public bool Form2Loaded { get; set; } private int aantalKliks = 0; private int aantalSpelers = 0; public Spelers speler1 = new Spelers(); public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { } private void pictionaryTitle_Click(object sender, EventArgs e) { } private void buttonSpelregels_Click(object sender, EventArgs e) { MessageBox.Show( $"1 - Kies of iedereen voor zichzelf speelt of in teams.{Environment.NewLine}2 - Geef de namen van de spelers in of een team naam per team.{Environment.NewLine}3 - Er word een speler of team gekozen om het woord uit te beelden. Druk op de knop om het woord zichtbaar/onzichtbaar te maken. Druk op de start knop om de ronde te beginnen.{Environment.NewLine}4 - De andere spelers/team hebben 60 seconden de tijd om het woord te raden. Kies de juist optie om de punten toe te voegen.{Environment.NewLine}5 - Druk op de knop stop spel om het spel te stoppen en de punten te laten zien.", "Spelregels"); } private void buttonFreeforall_Click(object sender, EventArgs e) { flowLayoutPanel1.Show(); buttonBack.Show(); buttonTeams.Hide(); buttonFreeforall.Hide(); buttonSpelregels.Hide(); } private void buttonBack_Click(object sender, EventArgs e) { flowLayoutPanel1.Hide(); buttonBack.Hide(); buttonTeams.Show(); buttonFreeforall.Show(); buttonSpelregels.Show(); radioButton2.Checked = false; radioButton3.Checked = false; radioButton4.Checked = false; radioButton5.Checked = false; } private void radioButton2_CheckedChanged(object sender, EventArgs e) { flowLayoutPanel1.Hide(); buttonBack.Hide(); textBox1.Show(); buttonAddName.Show(); aantalSpelers = 2; } private void radioButton3_CheckedChanged(object sender, EventArgs e) { flowLayoutPanel1.Hide(); buttonBack.Hide(); textBox1.Show(); buttonAddName.Show(); aantalSpelers = 3; } private void radioButton4_CheckedChanged(object sender, EventArgs e) { flowLayoutPanel1.Hide(); buttonBack.Hide(); textBox1.Show(); buttonAddName.Show(); aantalSpelers = 4; } private void radioButton5_CheckedChanged(object sender, EventArgs e) { flowLayoutPanel1.Hide(); buttonBack.Hide(); textBox1.Show(); buttonAddName.Show(); aantalSpelers = 5; } private void buttonAddName_Click(object sender, EventArgs e) { if (textBox1.Text == "" || textBox1.Text == "Speler Toegevoegd!") { MessageBox.Show("Naam mag niet blanco zijn!"); } else { switch (aantalKliks) { case 0: speler1.naamSpeler = textBox1.Text; speler1.SpelerNaarLijst(); break; case 1: speler1.naamSpeler = textBox1.Text; speler1.SpelerNaarLijst(); break; case 2: speler1.naamSpeler = textBox1.Text; speler1.SpelerNaarLijst(); break; case 3: speler1.naamSpeler = textBox1.Text; speler1.SpelerNaarLijst(); break; case 4: speler1.naamSpeler = textBox1.Text; speler1.SpelerNaarLijst(); break; } textBox1.Text = "Speler Toegevoegd!"; aantalKliks = aantalKliks + 1; } if (aantalKliks == aantalSpelers) { this.Close(); Form2Loaded = true; } } } }
Form2代码
using System; using System.Collections.Generic; using System.Windows.Forms; namespace Pictionary { public partial class Form2 : Form #region generatedCode { public Spelers speler1 = new Spelers(); public Form2() { InitializeComponent(); } private void Form2_Load(object sender, EventArgs e) { } private bool buttonSwitch = false; private void buttonToggleWord_Click(object sender, EventArgs e) { buttonSwitch = !buttonSwitch; if (buttonSwitch == true) { labelWoord.Text = "Woord: test"; } else { labelWoord.Text = "Woord: "; } } } #endregion
Spelers类代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Pictionary { public class Spelers { //Attributes public string naamSpeler; public List<string> spelerLijst = new List<string>(); //constructors //methods public void SpelerNaarLijst() { spelerLijst.Add(naamSpeler); } }
问题原因
核心问题是你在Form1和Form2中分别创建了独立的Spelers实例。这两个实例是完全不同的对象,各自拥有独立的spelerLijst列表:
- Form1里填充的是Form1内部
speler1实例的列表; - Form2里新建的
speler1是一个全新的、未填充数据的实例,所以列表为空。
解决方案
方案1:通过构造函数传递Spelers实例
这种方式适合仅在Form1和Form2之间传递数据的场景,逻辑清晰:
- 修改Form2的构造函数,接收Spelers实例作为参数:
public partial class Form2 : Form { private Spelers _spelers; // 修改构造函数,接收外部传入的Spelers实例 public Form2(Spelers spelers) { InitializeComponent(); _spelers = spelers; } // 可以在Form2_Load中测试数据是否传递成功 private void Form2_Load(object sender, EventArgs e) { MessageBox.Show($"已添加玩家数量:{_spelers.spelerLijst.Count}"); } // 原有代码保持不变... }
- 修改Form1中启动Form2的逻辑,直接传递已填充的Spelers实例:
在Form1的buttonAddName_Click方法中,替换原有的关闭逻辑:
// 替换原来的 this.Close(); Form2Loaded = true; Form2 form2 = new Form2(speler1); // 把Form1的speler1实例传给Form2 form2.Show(); this.Hide(); // 隐藏Form1而非直接关闭,避免程序退出
- 调整Program.cs的启动逻辑,默认启动Form1即可:
static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); }
方案2:将Spelers设计为单例类
如果需要在整个程序的多个页面共享玩家数据,可以把Spelers改成单例模式,确保全局只有一个实例:
- 修改Spelers类为单例:
public class Spelers { // 静态字段存储唯一实例 private static Spelers _instance; // 私有构造函数,禁止外部创建新实例 private Spelers() {} // 公共属性获取唯一实例 public static Spelers Instance { get { if (_instance == null) { _instance = new Spelers(); } return _instance; } } public string naamSpeler; public List<string> spelerLijst = new List<string>(); public void SpelerNaarLijst() { spelerLijst.Add(naamSpeler); } }
- 在Form1中使用单例实例:
替换Form1中的public Spelers speler1 = new Spelers();,直接通过Spelers.Instance操作:
// 在buttonAddName_Click的switch分支中 Spelers.Instance.naamSpeler = textBox1.Text; Spelers.Instance.SpelerNaarLijst();
- 在Form2中使用同一个单例实例:
替换Form2中的public Spelers speler1 = new Spelers();,直接访问Spelers.Instance:
private void Form2_Load(object sender, EventArgs e) { MessageBox.Show($"已添加玩家数量:{Spelers.Instance.spelerLijst.Count}"); }
额外优化建议
- Spelers类的命名建议改为
SpelerManager或PlayerCollection,更符合其管理玩家列表的语义; - 避免使用公共字段(如
naamSpeler、spelerLijst),改成封装后的属性,防止外部误操作数据:
public class Spelers { private List<string> _spelerLijst = new List<string>(); // 只读属性,外部只能读取列表不能直接修改 public List<string> SpelerLijst => _spelerLijst; // 封装添加玩家的方法,做参数校验 public void AddSpeler(string naam) { if (!string.IsNullOrWhiteSpace(naam)) { _spelerLijst.Add(naam); } } }
内容的提问来源于stack exchange,提问作者Excynic
相关产品推荐
相关产品推荐

