一、知识点简介
在WinForm项目开发中,一个项目里面会有多个窗体,例如登录窗体、注册窗体、主窗体。本节课主要学习:程序入口Program文件作用、两种窗体弹出方式Show()和ShowDialog()、模态与非模态窗口区别、DialogResult对话框返回值、实现登录窗体跳转主窗体。
本案例业务逻辑:程序启动先打开登录界面,输入账号密码admin登录成功,自动关闭登录窗口,直接进入主窗体。
二、项目结构
1、Program.cs:程序入口文件,整个项目最先执行
2、FormLogin.cs:登录窗体(启动页面)
3、FormMain.cs:项目主窗体(登录成功跳转页面)
三、全部源代码
1、Program.cs 入口代码
namespace _2窗体切换和窗体传值
{
internal static class Program
{
//应用程序的主入口点,程序运行最先执行Main方法
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//1.创建登录窗体对象
FormLogin login = new FormLogin();
//以模态对话框方式弹出登录窗体,接收窗体关闭的返回值
DialogResult r = login.ShowDialog();
//判断登录窗体返回值是否为OK
if (r == DialogResult.OK)
{
//关闭登录窗口,启动主窗体作为程序主页面
Application.Run(new FormMain());
}
}
}
}
2、FormLogin.cs 登录窗体代码
namespace _2窗体切换和窗体传值
{
public partial class FormLogin : Form
{
public FormLogin()
{
InitializeComponent();
}
//登录按钮点击事件
private void button1_Click(object sender, EventArgs e)
{
//校验账号和密码
if (textBox1.Text == "admin" && textBox2.Text == "admin")
{
//给当前登录窗体设置对话框结果为OK
this.DialogResult = DialogResult.OK;
}
}
}
}
3、FormMain.cs 主窗体代码
namespace _2窗体切换和窗体传值
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
}
}
}
四、整体执行流程
1、程序启动,执行Program里面的Main()方法;
2、创建FormLogin登录窗体,使用ShowDialog()模态弹出;
3、程序阻塞,等待登录窗体关闭;
4、用户输入账号密码admin/admin,点击登录按钮;
5、验证成功,设置 this.DialogResult = OK,登录窗体自动关闭;
6、Program接收返回值OK,关闭登录进程,开启主窗体FormMain。
五、逐行详细解析
(一)Program.cs 解析
1、基础初始化代码
Application.EnableVisualStyles(); 开启控件可视化样式,让界面更加美观。
Application.SetCompatibleTextRenderingDefault(false); 设置文本渲染格式,系统默认固定代码,禁止删除。
2、FormLogin login = new FormLogin();
在内存当中创建登录窗体对象,此时窗体不会显示。
3、DialogResult r = login.ShowDialog();
以模态对话框的方式弹出登录窗体。
特点:代码阻塞,弹出新窗口后,后面代码暂停执行,必须关闭当前窗口,代码才会继续往下执行。
ShowDialog() 拥有返回值,返回类型为DialogResult(对话框结果)。
4、if (r == DialogResult.OK)
DialogResult是枚举,常用值:OK、Cancel、Yes、No。
判断用户是否登录成功,如果返回OK代表登录成功。
5、Application.Run(new FormMain());
Application.Run() 代表运行主窗体,一旦执行这句代码,程序的主进程绑定为主窗体,登录窗体进程直接结束,完美实现页面切换。
(二)FormLogin 登录窗体解析
1、账号密码判断
获取两个文本框的内容,判断账号和密码是否全部等于admin。
2、this.DialogResult = DialogResult.OK;
this代表当前登录窗体。
给窗体设置对话框结果为OK,设置完成后,当前登录窗体自动关闭,并且将OK返回给Program。
六、Show() 和 ShowDialog() 核心区别(必考)
1、Show() 非模态窗口
① 非模态弹出,多个窗体之间可以自由切换、互相操作;
② 不会阻塞代码,打开窗体的同时,后面代码立刻执行;
③ 没有返回值,无法获取窗体操作状态。
2、ShowDialog() 模态窗口
① 模态弹出,子窗口不关闭,无法操作父窗口;
② 阻塞代码执行,窗口不关闭,后续代码暂停;
③ 带有返回值(DialogResult),可以接收窗口状态;
④ 适合:登录框、弹窗、提示框、确认框。
七、窗体关闭与隐藏的区别
1、Close():关闭窗体,释放内存,窗体彻底销毁;
2、Hide():隐藏窗体,窗体仍然存在内存中,只是用户看不见,可以随时再次调用Show()显示;
3、如果主窗体Close关闭,所有子窗体会跟着全部关闭。
八、本案例优点
1、利用DialogResult返回值判断登录状态;
2、登录窗体直接自动销毁,不占用内存;
3、通过Application.Run切换主进程,页面切换最干净、最正规;
4、是企业项目标准的登录跳转写法。
九、总结
1、程序入口Main方法最先执行,负责启动整个项目;
2、Show()非模态:不阻塞代码、可随意切换窗口;
3、ShowDialog()模态:阻塞代码、独占窗口、带返回值;
4、DialogResult可以给模态窗口设置返回状态;
5、设置this.DialogResult.OK 可以自动关闭当前弹窗;
6、登录跳转最优方案:模态窗口 + DialogResult + Application.Run切换主窗体。
WinForm 窗体传值(从上往下传、从下往上传)
一、知识点简介
在WinForm项目中,一个项目存在多个窗体,我们经常需要在不同窗体之间互相传递数据。本节课主要学习两种传值方式:
1、从上一个窗体传递数据到下一个窗体(向下传值):使用带参构造函数传值
2、从下一个窗体传递数据到上一个窗体(向上传值):使用静态全局变量传值
额外拓展:窗体遍历所有控件、MessageBox弹窗高级用法、四种窗体关闭方式、模态窗口跳转逻辑。
案例业务:登录页面输入账号密码,验证成功后,把账号传递给主窗体,主窗体标题显示欢迎XXX登录。
二、项目文件结构
1、Program.cs:程序入口,定义全局静态变量,控制窗体跳转
2、Form1.cs:登录窗体(起始窗体)
3、Form2.cs:主窗体(接收数据窗体)
三、完整全部源代码
1、Program.cs 入口文件
namespace _3传值
{
internal static class Program
{
//定义静态全局变量:用来接收登录页面传递过来的用户名
public static string CurrentUsr = "";
//应用程序主入口
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//弹出登录窗体(模态窗口)
Form1 form1 = new Form1();
DialogResult r = form1.ShowDialog();
//判断登录窗体是否返回OK(登录成功)
if (r == DialogResult.OK)
{
//调用Form2的有参构造,把全局用户名传递给主窗体
Application.Run(new Form2(CurrentUsr));
}
}
}
}
2、Form1.cs 登录窗体
namespace _3传值
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//遍历当前窗体所有控件,判断是否为按钮
foreach (Control control in this.Controls)
{
//is关键字:判断对象是否属于指定类型
if (control is System.Windows.Forms.Button)
{
//强制类型转换
System.Windows.Forms.Button btn = (System.Windows.Forms.Button)control;
}
}
}
//登录按钮点击事件
private void button1_Click(object sender, EventArgs e)
{
//校验账号密码
if (textBox1.Text == "admin1" && textBox2.Text == "admin1")
{
//【向上传值】把输入的账号赋值给Program静态全局变量
Program.CurrentUsr = textBox1.Text;
//设置对话框结果为OK,自动关闭当前登录窗口
this.DialogResult = DialogResult.OK;
}
}
//高级弹窗按钮
private void button3_Click(object sender, EventArgs e)
{
//弹出多功能提示框,接收用户点击的按钮
DialogResult result = MessageBox.Show("确定要删除吗", "微信提示",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Warning,
MessageBoxDefaultButton.Button2);
//判断用户点击的是确定还是取消
if (result == DialogResult.OK)
{
MessageBox.Show("点击了确定键");
}
else
{
MessageBox.Show("点击了取消键");
}
}
}
}
3、Form2.cs 主窗体
namespace _3传值
{
public partial class Form2 : Form
{
//自定义有参构造函数:接收从上一个页面传递过来的数据
public Form2(string name)
{
InitializeComponent();
//修改窗体标题,展示传递过来的用户名
this.Text = "欢迎" + name + "进入系统";
}
}
}
四、两种窗体传值原理(必考)
1、向下传值(上窗体==>下窗体)
实现方式:自定义有参构造函数
原理:默认窗体只有无参构造,我们手动写一个带参数的构造函数,在new窗体对象的时候直接把数据传入。
执行:new Form2(CurrentUsr);
优点:简单、安全、最常用,专门用于页面跳转传值。
2、向上传值(下窗体==>上窗体)
实现方式:静态全局变量传值
原理:在Program类中定义static静态变量,静态变量属于类不属于对象,所有窗体都能直接访问。
赋值:Program.CurrentUsr = textBox1.Text;
取值:直接在任意窗体读取 Program.CurrentUsr
五、逐行代码详细解析
1、Program静态全局变量
public static string CurrentUsr = "";
static静态变量,全局共享,所有窗体都可以直接读写,专门用来接收登录页面传上来的数据。
2、模态窗口跳转
DialogResult r = form1.ShowDialog();
以模态方式弹出登录窗口,代码阻塞,窗口不关闭不会执行下面代码。
3、带参构造跳转主窗体
Application.Run(new Form2(CurrentUsr));
调用Form2的有参构造,把全局储存的用户名传给主窗体,实现向下传值。
4、遍历窗体所有控件
foreach (Control control in this.Controls)
{
if (control is System.Windows.Forms.Button)
{
System.Windows.Forms.Button btn = (System.Windows.Forms.Button)control;
}
}
1、this.Controls:当前窗体所有控件的集合;
2、所有控件父类都是Control;
3、is关键字:判断当前控件是不是Button类型;
4、判断成功后强制转换为Button类型,即可使用按钮专属属性。
5、四种关闭窗体的方式
① this.Close():关闭窗体,释放资源;
② 点击窗体右上角叉号关闭;
③ Dispose():销毁窗体资源;
④ this.DialogResult=DialogResult.OK:设置对话框状态,自动关闭(本案例使用)。
6、MessageBox高级弹窗
MessageBox.Show("内容","标题",按钮类型,图标,默认按钮);
参数1:提示内容;参数2:弹窗标题;参数3:OK/取消按钮;参数4:警告图标;参数5:默认选中第二个按钮。
返回值DialogResult,用来判断用户点击的是确定还是取消。
六、完整运行流程
1、程序启动执行Program;
2、弹出Form1登录窗体;
3、输入账号admin1、密码admin1;
4、账号密码正确,把账号赋值给Program静态变量(向上传值);
5、设置DialogResult.OK,登录窗口自动关闭;
6、Program接收OK,调用Form2有参构造;
7、将用户名传递给Form2(向下传值);
8、主窗体标题显示:欢迎admin1进入系统。
七、总结
1、向下传值(跳转页面):重写带参构造函数 new Form2(数据)
2、向上传值(返回上一级):Program定义static全局变量
3、Controls可以遍历窗体所有控件,配合is做类型判断;
4、ShowDialog模态窗口带返回值,适合登录、弹窗;
5、MessageBox可以自定义按钮、图标、默认选项并接收用户操作。
八、易错点
1、普通变量无法全局共享,必须使用static静态变量才能跨窗体传值;
2、向下传值必须手写有参构造,不能直接赋值;
3、遍历控件时父类是Control,必须强制类型转换才能使用子类属性;
4、DialogResult只对ShowDialog()模态窗口生效,Show窗口无效。