简介
在很多场景下,我们的程序需要完成窗体间的传值功能,有时候是父窗体→子窗体单向传值、子窗体→父窗体传值甚至是,也有时候我们需要父窗体?子窗体双向传值。
在本文中主要介绍一些能够实现双向传值的方法,能够双向传值的方法也能够实现单向传值。
本文的所有源码都可以在GitHub上下载。
本文介绍的方法仅限于我自己知道并且实现过的,我相信还有很多我并不知道的方法,因此也许在很多朋友眼中本文的内容是浅显甚至可笑的,希望路过的各方朋友不吝赐教,我也希望不断地进步!
方法1:Public字段+ShowDialog
原理
这个方法的原理就是:
1.父窗体在实例化子窗体对象(假定名为childWindow)的时候,通过对子窗体Public字段进行赋值的方法,完成父窗体→子窗体的传值;
2.父窗体实例化子窗体后,调用子窗体的childWindow.ShowDialog()方法;
3.随后在父窗体中对childWindow.DialogResult的值进行判断,当会话结束的时候,将childWindow的字段值传给父窗体,实现子窗体→父窗体的传值。
代码
示例代码:
父窗体为MainWindow,子窗体为ChildWindow,我们将两个窗体间Title字段值进行互传。逻辑代码我们都放在了窗体的按钮点击事件中,用按钮来触发。
父窗体代码:
/// <summary>
/// 给子窗体传值
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_ShowChild_Click(object sender, RoutedEventArgs e)
{
ChildWindow child = new ChildWindow() { Title="我的名字是父窗体给的!" };//第1步,给子窗体传值了
child.ShowDialog();//第2步,调用ShowDialog
if (child.DialogResult==true)//第3步,然后对DialogResult进行判断
{
this.Title = child.Title;//子窗体给父窗体传值
}
}
子窗体代码
/// <summary>
/// 给父窗体传值
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_ShowFather_Click(object sender, RoutedEventArgs e)
{
this.Title = "我要给父窗体传值";
this.DialogResult = true;//第3步,首先会话结束
}
效果截图
截图为证:
父窗体→子窗体
点击“给子窗体传值”
子窗体→父窗体
点击“给父窗体传值”
总结
优点:这种方法简单方便,可以实现子窗体和父窗体间互相传值;
缺点:不够灵活,子窗体和父窗体都需要承载中间值的对象,而且需要借助ShowDialog()和DialogResult。
方法2:公共类的静态字段
原理
这个方法的原理就是:父窗体和子窗体分别对同一公共类的静态字段(可以是同一个字段也可以是不同的字段)进行赋值,然后父窗体和子窗体各自获取这些字段的值,就能够实现窗体间的传值。
该方法同样需要借助到ShowDialog()和DialogResult。
代码
公共类代码
/// <summary>
/// 公共类
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public class InfoClass
{
public static string Title { get; set; }
public static string Message { get; set; }
}
父窗体代码
/// <summary>
/// 实例化子窗体,为公用类静态字段赋值
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_ShowChild_Click(object sender, RoutedEventArgs e)
{
InfoClass.Title = "我的名字来自公共类!";
ChildWindow child = new ChildWindow();
child.ShowDialog();
if (child.DialogResult==true)
{
this.Title=InfoClass.Title;
MessageBox.Show(InfoClass.Message);
}
}
子窗体代码
/// <summary>
/// 加载事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.Title = InfoClass.Title;
}
/// <summary>
/// 修改公共类的静态字段,变相为父窗体赋值
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_ShowFather_Click(object sender, RoutedEventArgs e)
{
InfoClass.Title = "我的名字也是来自公共类!";
InfoClass.Message = "这是子窗体留下的信息!";
this.DialogResult = true;
}
效果截图
截图为证:
父窗体→子窗体
点击“给子窗体传值”
子窗体→父窗体
点击“给父窗体传值”
总结
方法3:构造函数+委托(我认为最好的方法)
原理
这个方法的原理就是:
1.父窗体利用子窗体的构造函数向子窗体传值;
2.自定义子窗体的构造函数,函数签名包含一个委托函数;
3.在子窗体中调用来自父窗体传递的委托函数,对对父窗体进行传值。
代码
委托代码
这个方法需要用到委托函数,我们将委托函数单独定义在公共类文件里面。
代码如下:
public delegate void ShowMessage(string value);
父窗体代码
/// <summary>
/// 通过自定义构造函数,给子窗体传值
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_ShowChild_Click(object sender, RoutedEventArgs e)
{
ChildWindow child = new ChildWindow(ShowErrorMessage,"这是来自父窗体的信息");
child.Show();
}
/// <summary>
/// 符合委托函数ShowMessage返回类型和签名的函数实例
/// </summary>
/// <param name="value"></param>
private void ShowErrorMessage(string value)
{
MessageBox.Show(value,"父窗体提示框");
}
子窗体代码
ShowMessage sm;
string value="";
public ChildWindow(ShowMessage _sm,string _value)
{
InitializeComponent();
sm = _sm;
value = _value;
}
/// <summary>
/// 加载事件,显示父窗体传递来的值
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
MessageBox.Show(value, "子窗体提示框");
}
/// <summary>
/// 调用父窗体传来的委托函数,给父窗体传值
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_ShowFather_Click(object sender, RoutedEventArgs e)
{
sm.Invoke("这是来自子窗体的信息!");
}
效果截图
截图为证:
父窗体→子窗体
点击“给子窗体传值”
子窗体→父窗体
点击“给父窗体传值”
总结
优点:能够在不关闭子窗体的情况下实现两个窗体间的传值(而且不仅限于传值),灵活方便,功能强大;
缺点:需要对委托有一定的了解,使用起来需要对这个方法有一定的理解;