You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinForms中AddGame窗体向MainWindow的ListView传值失败求助

WinForms跨窗体数据传递问题解决:无法访问listView1

问题根源

WinForms设计器默认将控件的访问修饰符设为private,这意味着外部窗体(比如你的AddGame)无法直接访问MainWindow里的listView1,这就是报错“因安全级别无法访问”的原因。另外你当前代码里还漏了传递MainWindow实例给AddGame,就算控件权限改了也会触发空引用异常。

下面给两种解决方案,以及关于SQL的疑问解答:


方案一:快速修正(修改控件权限+传递窗体实例)

  1. 修改listView1的访问权限
    打开MainWindow的设计器,选中listView1,在右侧属性窗口找到Modifiers选项,将其改为public或internal。

  2. 完善窗体实例传递
    修改MainWindow中打开AddGame的代码,把当前窗体实例传递过去:

    private void AddGamesButton_Click(object sender, EventArgs e)
    {
        var addGames = new AddGame();
        addGames.setForm1(this); // 新增此行,传递MainWindow实例
        addGames.Show();
    }
    

这样你的原有AddGame代码就能正常访问mainWindow.listView1了。


方案二:事件委托(更符合面向对象封装原则)

不直接暴露控件,通过事件传递数据,避免破坏窗体的封装性:

  1. 定义数据实体类
    新建一个类用来封装游戏数据:

    public class GameInfo
    {
        public string Play0Name { get; set; }
        public string Players { get; set; }
        public string Sequence1 { get; set; }
        public string Sequence2 { get; set; }
        public string Comments { get; set; }
        public string Winner { get; set; }
        public string GameDate { get; set; }
    }
    
  2. 修改AddGame窗体代码
    删除public MainWindow mainWindow和setForm1方法,改为定义事件:

    public partial class AddGame : Form
    {
        // 定义游戏添加完成事件
        public event EventHandler<GameInfo> GameAdded;
    
        public AddGame()
        {
            InitializeComponent();
        }
    
        private void CloseAddFormButton_Click(object sender, EventArgs e)
        {
            Close();
        }
    
        private void Add0Batchbutton_Click(object sender, EventArgs e)
        {
            try
            {
                // 空值检查,给异常添加明确提示
                if (string.IsNullOrEmpty(Play0NametextBox.Text))
                    throw new ArgumentException("游戏名称不能为空");
                if (string.IsNullOrEmpty(PlayersTextBox.Text))
                    throw new ArgumentException("玩家不能为空");
                if (string.IsNullOrEmpty(Sequence1TextBox.Text))
                    throw new ArgumentException("序列1不能为空");
                if (string.IsNullOrEmpty(Sequance2TextBox.Text))
                    throw new ArgumentException("序列2不能为空");
                if (string.IsNullOrEmpty(CommentsTextBox.Text))
                    throw new ArgumentException("备注不能为空");
                if (string.IsNullOrEmpty(WinnerTextBox.Text))
                    throw new ArgumentException("获胜者不能为空");
                if (string.IsNullOrEmpty(GameDateTextBox.Text))
                    throw new ArgumentException("游戏日期不能为空");
    
                // 封装数据
                var gameInfo = new GameInfo
                {
                    Play0Name = Play0NametextBox.Text,
                    Players = PlayersTextBox.Text,
                    Sequence1 = Sequence1TextBox.Text,
                    Sequence2 = Sequance2TextBox.Text,
                    Comments = CommentsTextBox.Text,
                    Winner = WinnerTextBox.Text,
                    GameDate = GameDateTextBox.Text
                };
    
                // 触发事件通知MainWindow
                GameAdded?.Invoke(this, gameInfo);
    
                MessageBox.Show("数据添加成功");
                Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "错误");
            }
        }
    }
    
  3. 修改MainWindow窗体代码
    订阅AddGame的事件并处理数据添加:

    public partial class MainWindow : Form
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    
        private void AddGamesButton_Click(object sender, EventArgs e)
        {
            var addGames = new AddGame();
            // 订阅事件
            addGames.GameAdded += AddGames_GameAdded;
            addGames.Show();
        }
    
        // 事件处理方法:将数据添加到listView1
        private void AddGames_GameAdded(object sender, GameInfo e)
        {
            ListViewItem lvi = new ListViewItem(e.Play0Name);
            lvi.SubItems.Add(e.Players);
            lvi.SubItems.Add(e.Sequence1);
            lvi.SubItems.Add(e.Sequence2);
            lvi.SubItems.Add(e.Comments);
            lvi.SubItems.Add(e.Winner);
            lvi.SubItems.Add(e.GameDate);
            listView1.Items.Add(lvi);
        }
    
        // 其余原有方法不变
        private void Closebutton_Click(object sender, EventArgs e)
        {
            Close();
        }
    
        public void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            foreach (ListViewItem item in listView1.Items)
                item.ForeColor = Color.Gray;
        }
    
        private void DeleteButton_Click(object sender, EventArgs e)
        {
            int selectNumber = -1;
            foreach (ListViewItem item in listView1.Items)
                if (item.Selected)
                {
                    selectNumber = int.Parse(item.Text);
                }
        }
    }
    

关于SQL的疑问

用SQL存储数据是完全可行的,适合需要持久化数据的场景(比如关闭程序后数据不会丢失)。如果只是临时在内存中展示数据,上面的方案就足够;如果需要长期保存数据,可以把GameInfo的数据写入数据库,MainWindow启动时从数据库读取数据加载到listView1,添加新数据时同时写入数据库。

内容的提问来源于stack exchange,提问作者Mnur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 21:30:44