从子窗体访问主窗体中的控件

  • 本文关键字:窗体 控件 访问 c#
  • 更新时间 :
  • 英文 :


我有一个包含3个主面板的主窗体:

  • 左边是菜单
  • 最上面的是一个简单的媒体播放器
  • 主面板是子面板的主机

歌曲选择是在子面板中完成的(通过datagrid(,我想将歌曲名称发送到顶部面板,以标签song_played开头(以主形式(。

这就是我打开子窗体的方式(点击菜单(:

private void openChildFormInPanel(Form childForm)
{
if (activeForm != null)
activeForm.Close();
activeForm = childForm;
childForm.TopLevel = false;
childForm.FormBorderStyle = FormBorderStyle.None;
childForm.Dock = DockStyle.Fill;
panelChildForm.Controls.Add(childForm);
panelChildForm.Tag = childForm;
panelChildForm.Parent = this;           
childForm.BringToFront();
childForm.Show();
}

panelChildForm是位于主窗体中的子面板。

点击事件时,我触发:

openChildFormInPanel(new Stats_form());

在我的子窗体中,我尝试了几种解决方案,但有一个例外System.NullReferenceException,因为父窗体总是null:

this.Owner.Controls["song_played"].Text = (string)dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[2].Value;

我也试过:

((Form1)this.Owner).lablSetText((string)dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells[2].Value);

Form1是我的主窗体的名称,labSetText是在主窗体上设置标签文本的函数

最后,

this.Parent.Controls["song_played"].Text = " dfgdfggdf";

激发相同的异常

感谢您的帮助:(

您可以继续在调试器中四处查看-Quick Watch会有所帮助-最终您会在childForm实例上找到this的属性,这些属性允许您"向上"返回到main for并"向下"返回到顶部面板。

我想提出另一种不那么脆弱的方法。

与其只为具有数据网格视图的子窗体提供Form,不如派生您自己的窗体并添加一个事件:

public SongSelectorForm : Form
{
public event EventHandler<String> SongChanged;
private void OnDataGridViewClick(object sender, EventArgs e)
{
SongChanged?.Invoke(this, "New Song Name"); //Taken from the data grid view.
//N.B. ?.Invoke is a safe way of calling the event handler in case no one is listened.
}
}

现在在MainForm中,当您添加ChildForm时,您可以订阅事件:

private void openChildFormInPanel(SongSelectorForm childForm)
{
//snip the above
childForm.SongChanged += HandleSongChange;
}
//We are adding a new method to the main form now to specifically handle a song change event from somewhere.
private void HandleSongChange(object sender, String songName)
{
this.TopForm.SongName = songName; //or whatever you use to update the songname in the top form.
}

由于主形式是"父母",它知道自己的孩子是有道理的。使用事件是"父母"在孩子们不了解彼此的情况下安排孩子们行为的一种方式。

我添加了一个TopForm.SongName,这样"家长"就可以更容易地与TopForm对话,而不知道底层控件是什么:

例如

//in topform
public String SongName
{
get { return someControl.Text; }
set { someControl.Text = value; }
}

这允许您更改TopForm中的内容,但仍然为Mainform保留了一种简单的方式来更改SongName,而无需更改。

你对C#了解得越多,就会发现你可以使用接口来定义这些组件之间的"契约",这样它们对彼此的了解就更少了,这样就更容易更改一个部分,而不用担心破坏其他部分。

最新更新