【问题】
在折腾:
的过程中,需要实现,在一个(子)窗体中,去设置另外一个(父)窗体中的值。
注:此处不需要获得另外窗口的值,因为之前已实现该功能了:
【已解决】C#中,如何在一个(子)窗体中,获得另一个(父)窗体中的(控件)变量的值
此处只是需要设置另外窗口中的变量值。
【解决过程】
1.本来打算用变量的形式,把父窗体指针传递给子窗体的,结果还是失败了:
【未解决】Cannot take the address of, get the size of, or declare a pointer to a managed type xxx
2.即使参考了微软官方的:
也只能实现代码:
public partial class completeHint : Form { private string curFullFilename; private string curFolderPath; private frmDownloadSongtasteMusic curParentForm; public completeHint() { InitializeComponent(); } //public unsafe void initParameter(IntPtr* parentForm, string fullFilename, string folderPath) public void initParameter(string fullFilename, string folderPath) { //curFullFilename = fullFilename; //curFolderPath = folderPath; //curParentForm = (frmDownloadSongtasteMusic *)parentForm; Control curParent = this.Parent; Form foundParentForm = curParent.FindForm(); curParentForm = (frmDownloadSongtasteMusic)foundParentForm; curParentForm.resetHintWindow(); }
编译是没有错的,
但是运行时,由于this.Parent为null,所以无法获得所需要的窗体frmDownloadSongtasteMusic。
3.也试过,通过在父窗体frmDownloadSongtasteMusic中调用子窗体之前,通过:
//open hint window if (hintWindow == null) { hintWindow = new completeHint(); } hintWindow.Parent = this; hintWindow.initParameter(curFullFilename, txbSaveTo.Text); hintWindow.Show();
的方式,去手动设置parent,结果出错:
Top-level control cannot be added to a control
所以还是行不通。
4.找了半天资料,都没有合适的。
后来是参考:
C# winfrom datagridview 子父窗口传值问题
去试试那个owner:
public partial class completeHint : Form { private string curFullFilename; private string curFolderPath; private frmDownloadSongtasteMusic curParentForm; public completeHint() { InitializeComponent(); } //public unsafe void initParameter(IntPtr* parentForm, string fullFilename, string folderPath) public void initParameter(string fullFilename, string folderPath) { //curFullFilename = fullFilename; //curFolderPath = folderPath; //curParentForm = (frmDownloadSongtasteMusic *)parentForm; //Control curParent = this.Parent; //Form foundParentForm = curParent.FindForm(); //curParentForm = (frmDownloadSongtasteMusic)foundParentForm; curParentForm = (frmDownloadSongtasteMusic)this.Owner; curParentForm.resetHintWindow(); }
结果竟然是owner也是null:
再试试手动赋值owner:
public void showCompleteHint() { //open hint window if (hintWindow == null) { hintWindow = new completeHint(); } //hintWindow.Parent = this; hintWindow.Owner = this; hintWindow.initParameter(curFullFilename, txbSaveTo.Text);
然后:
//public unsafe void initParameter(IntPtr* parentForm, string fullFilename, string folderPath) public void initParameter(string fullFilename, string folderPath) { //curFullFilename = fullFilename; //curFolderPath = folderPath; //curParentForm = (frmDownloadSongtasteMusic *)parentForm; //Control curParent = this.Parent; //Form foundParentForm = curParent.FindForm(); //curParentForm = (frmDownloadSongtasteMusic)foundParentForm; curParentForm = (frmDownloadSongtasteMusic)this.Owner; curParentForm.resetHintWindow(); }
结果是可以正常获得owner的值的:
接下来,就可以正常的操作父窗体中的值和调用函数了。
【总结】
想要在子窗体中设置父窗体中的值,核心问题在于,在子窗体中,如何获得父窗体这个变量,此处的办法是,在父窗体调用显示子窗体之前,先设置子窗体的Owner为当前的自己self:
hintWindow.Owner = this;
然后子窗体中就可以通过获得Owner,再强制转换为父窗体类型的变量:
private frmDownloadSongtasteMusic curParentForm; //public unsafe void initParameter(IntPtr* parentForm, string fullFilename, string folderPath) public void initParameter(string fullFilename, string folderPath) { ... curParentForm = (frmDownloadSongtasteMusic)this.Owner; }
如此,获得了父窗体类型变量curParentForm后,就可以设置其值,调用其函数了。
【后记 2013-01-07】
后来,帮别人写类似的代码的时候,又参考了:
In C#, how can I change the properties of controls on another form?
解释的,比:
How to: Get a Value from Another Form
Changing a label’s text in another form in C#?
更清楚。
然后,参考其第二种方法,写出对应的代码,如下:
注:
- 此处要实现的:在Form2中拖动TrackBar,改变From1中的TrackBar的值,实现了两个窗体的TrackBar的值保持同步。
- 此处示例代码用的是TrackBar控件,需要.NET 3.5+
- Form1.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace trackbarSetAnotherFormValue { public partial class Form1 : Form { //public TrackBar form1Trackbar; //把变量设置为public的方法不好 public Form1() { InitializeComponent(); } //应该另外公开一个变量,用于读写对应的私有变量,才是好办法 public int currentTrackbarValue { get { return trackBar1.Value; } set { trackBar1.Value = value; } } private void button1_Click(object sender, EventArgs e) { Form2 form2 = new Form2(); form2.parentForm1 = this; form2.Show(); } private void Form1_Load(object sender, EventArgs e) { //form1Trackbar = trackBar1; //把变量设置为public的方法不好 } } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace trackbarSetAnotherFormValue { public partial class Form2 : Form { public Form1 parentForm1 = null; public Form2() { InitializeComponent(); } private void form2Trackbar_Scroll_1(object sender, EventArgs e) { parentForm1.currentTrackbarValue = form2Trackbar.Value; } private void Form2_Load(object sender, EventArgs e) { } } }
效果如下:
总体上说,还是有点麻烦的。。。