快速入门:【c# 之 Winform开发】

Winform

Winform 注意:

  1. winform中,很多属性和方法的单词首字母都是要大写的,例如:Main()方法。

  2. WinForms中,事件函数通常具有两个参数:object senderEventArgs e

    1. object sender:这个参数表示引发事件的对象。当事件被触发时,它指向引发事件的控件或对象。通过sender参数,你可以获得对触发事件的对象的引用,进而进行进一步的操作或判断。
    2. EventArgs e:这个参数包含与事件相关的额外信息。它是一个基类,通常使用派生自它的特定事件参数类,比如MouseEventArgs或KeyPressEventArgs。通过e参数,你可以访问与事件相关的属性、方法和数据。

    假设你有一个按钮的Click事件,当你点击按钮时,事件函数的签名可能如下所示:

    private void button_Click(object sender, EventArgs e)
     {
        // 使用sender参数可以访问到按钮对象
       Button clickedButton = (Button)sender;
        
        // 使用e参数可以访问到与该事件相关的属性或方法
        MessageBox.Show("按钮" + clickedButton.Name + "被点击了!");
    }
    

    通过sender和e参数,你可以在事件函数中获取触发事件的对象和事件相关的信息并进行相应的处理。

  3. Winform中某个组件的事件绑定有两种方式:

  • 法一: 在相应组件处右键属性进入选择某个事件,双击进入进行事件函数的代码编辑。
  • 法二: 在相应组件处右键属性进入选择某个事件,不双击,而是用下拉框复用其它已经写好的事件函数,即代码复用。
  1. winform中某些窗体为什么加上一个Partial关键子,其有什么作用?为什么要加这个关键字?

    • 在C#的WinForms应用程序中,Partial关键字用于实现分部类(Partial Class)。分部类是指将一个类的定义拆分成多个部分,分别定义在不同的源代码文件中,但它们在编译后会被合并成一个完整的类。Partial关键字告诉编译器这个类是分部类的一部分。
    • 使用可视化设计器创建WinForms应用程序时,设计器会自动生成一些代码,如窗体的初始化代码和事件处理程序。这些自动生成的代码通常存储在.designer.cs文件中。手写的代码则通常存储在.cs文件中。通过使用Partial关键字,可以将这两个部分的代码组合成一个类,使其看起来像是一个完整的类。
    • 总之,Partial关键字的作用是将一个类的定义拆分成多个部分,以便更好地管理和组织代码。
  2. 在 WinForms 中,事件绑定处理函数可使用 “+=” 运算符来绑定

    //例如:这表示在 button1 控件上单击时,将调用名为 button1_Click 的方法。
     button1.Click += new EventHandler(button1_Click);
    //总之,WinForms 中事件处理程序的绑定方式有多种,但最常见和最简单的方法是使用 "+=" 运算符。
    

在WinForms中,当您使用 “+=” 运算符将事件处理程序方法绑定到事件时,不需要在方法名称后面添加小括号。

//例如,假设您有一个名为 "button1_Click" 的事件处理程序方法,您可以使用以下方式将其绑定到 "button1" 控件的 "Click" 事件:
button1.Click += button1_Click;
   
//在这个例子中,我们没有在 "button1_Click" 方法名称后面加上小括号。这是因为我们不想调用这个方法,而是将它作为一个处理程序方法来绑定到 "Click" 事件。
   
//如果您在方法名称后面添加了小括号,例如:
button1.Click += button1_Click();
//这将导致 "button1_Click" 方法被立即调用,并且它的返回值(如果有)将被绑定到 "Click" 事件,而不是 "button1_Click" 方法本身。
  1. 在 WinForms 项目中,引用的文件通常存放在项目的输出目录中,而输出目录可以是 bin\Debugbin\Release,具体取决于项目的配置。

默认情况下,当你构建或运行 WinForms 项目时,生成的可执行文件(例如 .exe 文件)以及项目所依赖的其他文件(例如类库、资源文件等)会被输出到输出目录中。

输出目录的默认设置可以在 Visual Studio 中的项目属性中进行配置。你可以打开项目属性对话框,然后选择 “生成” 选项卡,在其中你会找到 “输出路径” 选项,用于指定输出目录的路径。

通常情况下,调试(Debug)配置会将输出目录设置为 bin\Debug,而发布(Release)配置会将输出目录设置为 bin\Release。这是因为在开发过程中,调试配置用于生成带有调试符号和其他调试所需信息的可执行文件,以方便调试和测试。而发布配置则用于生成优化的、不带调试符号的最终发布版本。

所以,引用文件通常存放在 bin\Debugbin\Release 目录中,取决于当前的项目配置。这样做的好处是,当你构建项目时,引用文件会自动复制到输出目录中,以确保项目能够正确运行所需的依赖项。

需要注意的是,如果你手动更改了输出目录的设置,引用文件的存放路径也会相应改变。

项目结构

打开winform项目的.sln解决方案文件时的项目结构:

解决方案: 不包含代码,用于组织项目之间关系。

  • properties(文件夹): 定义程序集的属性, 一般只有一个 AssemblyInfo.cs 类文件,用于保存程序集的信息,如名称,版本等,这些信息一般与项目属性面板中的数据对应,不需要手动编写。

  • 引用(文件夹): 引用的目标是文件,而USING的目标是内容,其主要功能是方便引入命名空间,在引入命名空间的当前代码页写程序代码时,可以免除长长的命名空间;

    using的命名空间必须在引用里面存在,即先引用dll文件后才能using.

    若不存在某个命名空间,可以在引用文件夹处右键选择添加引用即可。

  • App.config文件: 项目的配置文件

  • 各种窗体文件【cs类文件】,例子如下:

    • closeState.cs[关闭状态的窗体]
    • deviceStatus.cs[设备状态窗体]
    • Form_Main.cs[主要表单窗体]

    其中对于每个窗体文件:

    第一个文件用来放事件处理,业务以及逻辑相关的代码

    第二个文件用来放窗口的外观等设计相关的代码

    第三个文件则是用来放我们导入的资源,一般不用看。

    form窗体举例:

    form.cs:源代码(处理代码)

    form.designer.cs:窗体布局代码,自动生成对应的控件代码

    form.resx:窗体的资源

  • priogram.cs文件:Main函数即入口文件,程序的启动文件

  • 剩余的其他cs文件(即其他的c#类文件以及辅助的文件)。

创建项目后项目文件夹的项目结构:

  • bin:存放项目的编译结果

    debug:调试版本(慢),release:快,发布版本,

    pdb:位置信息-调试

  • obj:编译过程中生成的中间临时文件,加快编译速度,

    把每个模块生成的文件都保存下来,可以加快编译速度下次编译只会编译修改过的部分

  • .csproj:项目文件,位置引用,双击打开项目

  • .sln:解决方案。

    双击.sln的解决方案文件即可进入vs IDE编辑和运行项目

    sln:在开发环境中使用的解决方案文件。它将一个或多个项目的所有元素组织到单个的解决方案中。此文件存储在父项目目录中.解决方案文件,他是一个或多个.proj(项目)的集合,双击可以打开项目。


    *.sln:(Visual Studio.Solution) 通过为环境提供对项目、项目项和解决方案项在磁盘上位置的引用,可将它们组织到解决方案中。

项目导入本地资源文件

Note: winform项目的导入资源文件不像web项目,其只需要将资源放在项目目录,这里不是这么操作。

  1. 先打开资源面板

    法一: 进入Properties文件夹,选择其中的Resources.resx。

    法二:鼠标移动到winform项目名处,右键选择属性,再选择资源

  2. 进入资源面板后,选择添加资源(选择添加现有文件),再ctrl+s保存一下

  3. 发现winform项目下会生成一个Resources文件夹,其存储了我们刚刚导入的资源文件。

主要用到的命名空间

主要是利用到常用的命名空间中的属性和方法。

System.Windows.Forms

在这里插入图片描述

InvokeRequired 检查

在 WinForms 中,InvokeRequired 是一个用于检查当前代码是否在创建控件的线程上运行的属性。由于 UI 控件只能在创建它的线程上进行更新,如果在不同的线程上尝试更新 UI,就会引发跨线程操作无效的异常。因此,InvokeRequired 可以用于检测当前代码是否在正确的线程上执行,并在需要时将操作委托到 UI 线程上执行。

InvokeRequired 是一个 bool 类型的属性,用于检查当前代码是否在创建控件的线程上运行。具体地说:

  • 如果当前代码在创建控件的线程上运行,则 InvokeRequired 返回 false,表示可以直接在当前线程上更新 UI 控件。
  • 如果当前代码不在创建控件的线程上运行,即在不同的线程上运行,那么 InvokeRequired 返回 true,表示需要通过 InvokeBeginInvoke 将 UI 操作委托到正确的线程上执行。
    • InvokeBeginInvoke 是用于在 UI 线程上执行委托的两个方法:
    • Invoke 同步执行,即它会阻塞当前线程,直到委托执行完成。如果在 UI 线程上使用 Invoke,并且在委托中执行了耗时的操作,可能导致界面冻结。
    • BeginInvoke 异步执行,即它会立即返回而不等待委托执行完成。这意味着 UI 线程不会被阻塞,可以继续处理其他消息。BeginInvoke 将委托添加到 UI 线程的消息队列,由 UI 线程异步执行。

使用场景:

  1. 多线程操作 UI 控件: 当在多个线程中对 UI 控件进行操作时,需要确保 UI 操作在创建控件的线程上执行。
  2. 异步操作回调: 在异步操作完成后,通过回调方法更新 UI。异步操作通常在不同的线程上执行,所以在回调方法中可能需要使用 InvokeRequired 来确保 UI 操作的线程正确。

语法:

//control 是一个表示 UI 控件的变量。这个变量用于指定需要执行 UI 操作的控件,例如 RichTextBox、TextBox、Label 等。
if (control.InvokeRequired)
{
    //同步执行选择Invoke方法,异步执行选择BeginInvoke方法
    control.Invoke(new Action(() =>
    {
        // UI 操作代码
    }));
}
else
{
    // UI 操作代码
}

例如,如果你想要在一个按钮点击事件中更新文本框的内容,你可以将文本框的实例传递给 control

下面是一个示例,假设你有一个按钮和一个文本框:

private void button1_Click(object sender, EventArgs e)
{
    // 在按钮点击事件中调用 appendMsg 方法,将消息追加到文本框
    appendMsg("Button Clicked!", textBox1);
}

private void appendMsg(string msg, TextBox control = null)
{
    if (control.InvokeRequired)
    {
        //如果返回 true,表示当前代码不在 UI 线程上,需要通过 Invoke 将 UI 操作委托到 UI 线程上执行。
        control.Invoke(new Action(() =>
        {
            // UI 操作代码,例如更新文本框内容
            control.Text = msg;
        }));
    }
    else
    {
        //如果返回 false,表示当前代码已经在 UI 线程上,可以直接更新 UI。
        // UI 操作代码,例如更新文本框内容
        control.Text = msg;
    }
}

窗体

我们创建的窗体类一般都要继承System.Windows.Forms.Form类,因为其很多功能都帮我们搞定了,比如最大化/最小化,关闭等等

Demo.cs

using System;
using System.Windows.Forms;
using System.Drawing;

//指定程序集的版本号
[assembly:System.Reflection.AssemblyVersion("1.1")]
namespace UKE.Winform.Demo
{	
	//窗体是一个类,其要默认继承自System.Windows.Forms.Form,这样可以直接用到里面的属性和方法
	public class MyForm:System.Windows.Forms.Form{
		//声明控件实例
		private Button btnLoad;
		private PictureBox pbPhoto;
		
		//构造函数(同名)
		public MyForm(){
			//设置当前窗体的窗体标题文字
			this.Text = "Hello C#1.1";
			//初始化控件
			btnLoad = new Button();
			btnLoad.Text = "载入图片";//文字
			btnLoad.Left = 10;//位置
			btnLoad.Top = 10;

			//关联按钮事件
			btnLoad.Click += new EventHandler(this.HandlerLoadClick);//注意形参虽然是方法,但不能加()

			pbPhoto = new PictureBox();
			pbPhoto.Width = this.Width / 2; //宽度和高度
			pbPhoto.Height = this.Height / 2;
			pbPhoto.Left = (this.Width - pbPhoto.Width) / 2; //位置
			pbPhoto.Top = (this.Height - pbPhoto.Height) / 2;
			pbPhoto.BorderStyle = BorderStyle.Fixed3D;//边框样式
			
			
			//在WinForms中,this.Controls是一个属性,它是一个表示窗体中子控件的控件集合。
			//控件集合是一种用于存储和管理窗体中的       控件的容器。通过访问this.Controls属性,可以获取或操作窗体中的子控件。
			//它提供了一些方法和属性,可以用来添加、删除、查找和遍历子控件。
			//使用this.Controls可以对窗体中的子控件进行访问、操作和管理,使得WinForms应用程序中构建用户界面变得灵活和方便。
    			this.Controls.Add(btnLoad);
			this.Controls.Add(pbPhoto);

		}
		
		//事件方法
		private void HandlerLoadClick(object sender,EventArgs e){
			//事件代码(选择图片,打开文件对话框/文件选择框)
			OpenFileDialog dialog = new OpenFileDialog();
			dialog.Title = "请选择图片"; //文件选择框左上角文字
			dialog.Filter = "jpg图片(*.jpg)|*.jpg|所有文档(*.*)|(*.*)";//过滤(前面一个用于前端显示,后面一个才是真正过滤,且后面一个不用加小括号包裹)
			
			if(dialog.ShowDialog() == DialogResult.OK){
				
				//show image
				pbPhoto.Image = new Bitmap(dialog.OpenFile());
			}
			//释放控件、组件或其他可释放资源所占用的资源并进行清理操作。
			//当一个控件或者组件不再需要时,应该显式地调用其Dispose方法,以确保在不需要时及时释放它所占用的资源。=
			dialog.Dispose();
			
		}
		
		//入口方法
		[System.STAThread]
		public static void Main(){
			//启用系统界面风格效果,使窗体的效果与当前操作系统的效果保持一致
			System.Windows.Forms.Application.EnableVisualStyles();
			System.Windows.Forms.Application.Run(new MyForm());//传入窗体实例,作为第一个启动的窗体
		}
	
	}
}

窗体的属性

  • Text: 窗体中的左上角边框的文字显示
  • Icon:窗体的图标
  • WindowState: 窗体刚启动状态,枚举类(Normal, 最大/最小)
  • StartPosition: 窗体启动时的坐标位置
  • Size: 窗体的宽和高
  • ShowInTaskbar: 是否在底部任务栏显示任务标识
  • Visible:是否显示窗体

窗体的方法

  • Hide():窗体的隐藏,
  • Close():窗体的关闭
  • Show():窗体的显示

窗体的事件

  • SizeChanged: 窗体尺寸改变时的事件
  • Load: 窗体载入时的事件。注意窗体类的构造函数执行在前,然后才轮到这个Load事件。

窗体间传递数据

利用控件的Tag属性。


在WinForm中,可以使用Tag属性将数据传递给窗体或控件。

Tag属性是一个对象,它可以存储任何类型的数据。可以在一个窗体或控件上设置Tag属性,然后在另一个窗体或控件中读取它,以实现数据传递。


注意: 在使用Tag属性传递数据时,要确保存储在Tag属性中的数据类型与读取它的控件所期望的类型相匹配,否则可能会导致运行时错误

下面是一个使用Tag属性在两个窗体之间传递数据的示例:

假设有一个主窗体MainForm和一个子窗体ChildForm,并且我们想要在主窗体中设置这个字符串,从而在子窗体中显示一个字符串。

可以按照以下步骤实现:

  1. MainForm中设置一个字符串,并将其存储在Tag属性中:
private void MainForm_Load(object sender, EventArgs e)
{
    string myString = "Hello, world!";
    childForm.Tag = myString;
}
  1. ChildForm中读取Tag属性并显示存储的字符串:
private void ChildForm_Load(object sender, EventArgs e)
{
    string myString = this.Tag as string;
    if (!string.IsNullOrEmpty(myString))
    {
        label1.Text = myString;
    }
}

子窗体调用父窗体的方法

利用Owner属性。


可以通过设定窗体的Owner属性,在打开的窗体中调用其Owner(所有者)窗体的方法。


下面是一个示例:

首先,我们有两个窗体,Form1和Form2。

Form2被Form1打开,所以这里的Form2是子窗体,Form1是父窗体,然后这里有个需求: Form2调用Form1的方法。


我们在Form1中创建一个方法:

public partial class Form1 : Form
{
    //这里是Form1中的一个方法
    public void ShowMessage(string message)
    {
        MessageBox.Show(message, "Message from Form2");
    }
    
    private void Button_Click(object sender, EventArgs e)
    {
        Form2 form2 = new Form2();
        form2.Owner = this;//设置Form2的Owner属性是Form1
        form2.Show();//这里是Form1打开Form2窗口
    }
}

在Form2中,我们使用Owner属性来获取对Form1的引用,并调用Form1的方法:

public partial class Form2 : Form
{

    private void Button_Click(object sender, EventArgs e)
    {
        var form1 = this.Owner as Form1;//得到Form1窗体
        //Form2调用Form1中的方法
        form1?.ShowMessage("Hello, I'm Form2.");
    }
}

以上,在Form1点击Button后打开Form2,然后在Form2点击Button就会调用Form1的ShowMessage方法,显示一个消息框。

控件

控件的通用属性

1. Tag属性

在WinForms中,每个控件都可以使用Tag属性

  • Tag属性是一个通用的对象属性,可以用来存储与控件相关的任意数据。它可以接受任何类型的对象作为值,例如字符串、整数、自定义对象等都可存储在Tag属性中。

  • 通过将数据存储在Tag属性中,开发人员可以在控件上附加自定义信息,以方便应用程序开发和处理。

  • 使用Tag属性时,开发人员可以根据需要将其用作控件的标记或元数据。

  • 通过利用Tag属性,可以方便地将控件与其他相关的实体关联起来,如数据库记录、业务对象等,跨窗体传递数据等。


可以通过以下方式访问和使用Tag属性:

  1. 设置Tag属性值:

    button1.Tag = "按钮1";
    
  2. 获取Tag属性值:

    string tagValue = button1.Tag as string;
    
  3. 使用Tag属性的值进行相关操作:

    if (button1.Tag != null && button1.Tag.ToString() == "按钮1")
    {
        // 执行相关操作
    }
    

需要注意的是,由于Tag属性是一个通用的对象属性,所以在使用它时需要注意类型转换和空值检查,以保证代码的正确性和健壮性。

Tag属性的应用:

  • 有时我们想存一个数据,但又不让它显示,这时就可以利用Tag属性。
  • 窗体间需传递简单数据时,也可利用Tag属性。
  1. TabIndex属性

TabIndex:此属性主要用于确定控件的导航顺序。当您使用Tab键在表单中的不同控件中切换时,TabIndex的值决定了这种切换的顺序。值越小,控件在切换顺序中的位置越靠前。

例如:

Button1.TabIndex = 0;
Button2.TabIndex = 1;

在这个例子中,如果您在此表单上按下Tab键,您将首先导航到Button1,然后导航到Button2。


我们需了解每个控件的:

  • 功能
  • 属性
  • 方法
  • 事件

查看信息:

  • VS中,视图->对象浏览器中可看dll文件中的类属性、方法等
  • MSDN(MicroSoft Developer Network)官网文档的搜索栏可以输入某个类的完全限定名来查询相应的控件信息。

基本控件

  • NotifyIcon:

    功能: 系统栏显示的小图标

    特点: 其不占用窗体的面积,其位于vs界面的左下角。

    属性:

    • Visible: 窗体应用启动时是否显示小图标

    事件:

    • 双击时的事件。

    demo.cs:

    //窗体尺寸改变时添加一个事件
            private void Form1_SizeChanged(object sender, EventArgs e)
            {
                switch (this.WindowState)
                {
                    case FormWindowState.Minimized:
                        this.ShowInTaskbar = false;//窗体缩小时不显示底部任务栏图标
                        this.notifyIcon1.Visible = true;//窗体缩小时显示系统栏小图标
                        break;
                    case FormWindowState.Normal:
                    case FormWindowState.Maximized:
                        this.ShowInTaskbar = true;//窗体最大化显示时显示底部任务栏图标
                        this.notifyIcon1.Visible = false;//窗体最大化显示时不显示底部任务栏图标
                        break;
                    default:
                        break;
                }
            }
    
            private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
            {
                this.WindowState = FormWindowState.Normal;//恢复窗体的正常显示界面
            }
    
  • Label

    功能: 显示文字内容。

    属性:

    • Text: 手动文本编辑,在文本里输入文字以及手动换行等。
  • LinkedLabel

    功能: 表示URL的文字内容显示

    事件:

    • 添加click事件实现链接跳转。
  • TextBox

    功能: 文本框

    属性:

    • Text: 单行文字
    • Multiline:多行文字
    • PasswordChar:手动输入密码时显示的符号
    • UseSystemPasswrodChar: 使用系统输入密码时的显示的符号
  • Button

    功能: 按钮

  • DateTimePicker

    功能: 日期时间选择

  • RadioButton

    功能: 多选一,单选框。RadioButton(单选按钮)是一组互斥的选项,在同一组内只能选择一个。当用户选中一个RadioButton时,其他RadioButton会自动取消选择。

  • CheckBox

    功能: 复选框。CheckBox(复选框)是独立的选项,用户可以同时选择多个CheckBox,它们之间没有互斥的关系。

  • GroupBox

    功能: 用于分组。

列表控件

常用列表控件

ListBox

功能: 用于显示一个可滚动的列表。ListBox可以显示一列项目,用户可以选择其中的一个或多个项目。

属性:

  • Items: ListBox中要显示的项目列表。可以使用Items属性的Add方法添加项目,或者直接在设计器中的items属性窗格中手动输入。
  • SelectionMode:ListBox中项目的选择模式。可以设置为Single(只能选择一个项目)、Multiple(可选择多个项目)或Extended(可选择连续多个项目)。
  • SelectedIndex:当前选定项目的索引。

CompoBox:

功能:C#中的ComboBox是Windows Forms中的一个控件,它提供了一个可编辑的下拉列表,用户可以从中选择一个选项,或者输入自定义的文本.

属性:

  • Name: ComboBox控件的名称,用于在代码中引用它。
  • Items: ComboBox中要显示的选项列表。可以使用Items属性的Add方法添加选项,或者直接在设计器中的属性窗格中输入选项。
  • DropDownStyle:此属性决定了下拉列表的显示方式。DropDownStyle属性有三个选项:
    1. DropDownList:下拉列表框只能选择列表中的项,不能手动输入。用户只能通过点击下拉箭头选择已有的项。
    2. DropDown:下拉列表框可以手动输入,用户可以在文本框中输入自定义的值。用户可以通过点击下拉箭头选择已有的项,或者直接在文本框中输入。
    3. Simple:简单列表框,不包含下拉箭头,直接显示所有的选项。用户可以手动输入,但是无法通过下拉选择。通常用于显示较少的选项。
  • SelectedIndex: 当前选定项的索引。可以通过代码设置它来选择ComboBox中的选项。

事件:

一些常见的事件包括:

  • SelectedIndexChanged: 当选定项发生更改时触发的事件。
  • DropDown: 当下拉列表展开时触发的事件。
  • TextChanged: 当文本框中的文本发生更改时触发的事件。

列表绑定数据:

在WinForms中,ListBox不支持数据源绑定,而ComboBox是支持数据源绑定的。


故ComboBox支持数据源绑定和遍历添加数据。

而ListBox仅仅支持遍历添加数据。

法一:【数据源属性进行绑定】

示例代码(一般利用数据源绑定都要写到下面三行代码):

//下面三行示例代码
comboBox1.DataSource = dataList;//将数据源一次性绑定数据,通过设置DataSource属性,ComboBox会自动从数据源中获取数据,并在下拉列表中显示。
comboBox1.DisplayMember = "Title";//将对象属性作为列表显示的文字,一般是指定sql语句返回的列字段
comboBox1.ValueMember = "ID";//指定对象的值属性作为"值"字段,一般是指定sql语句返回的列字段

法二:【利用遍历循环利用Items属性添加】

ListBox是用来显示列表的控件,它可以通过Items属性手动添加和删除项。

如果要绑定数据源到ListBox,需要手动遍历数据源并将数据添加到ListBoxItems集合中。

示例代码:

List<string> dataList = new List<string> { "Item 1", "Item 2", "Item 3" };

foreach (string item in dataList)
{
    listBox1.Items.Add(item);//遍历添加数据到Items属性
}

PictureBox

PictureBox:

功能:用于显示图像或绘制的图形。PictureBox提供了一种简单的方式来显示图像,并且可以进行基本的缩放、绘制和交互操作。

属性:

  • Name: PictureBox控件的名称,用于在代码中引用它

  • Image: 要显示在PictureBox中的图像。可以使用Image属性来加载图像文件,或者直接在设计器中的属性窗格中选择图像。

  • SizeMode:图像在PictureBox中的显示模式。常见的模式包括AutoSize(自动调整大小以适应图像)、StretchImage(拉伸图像以填充PictureBox)和Zoom(按照图像比例显示,并保持图像完整)等。

事件:

一些常见的事件包括:

  • Click: 当用户单击PictureBox时触发的事件。
  • MouseMove: 当鼠标移动到PictureBox上时触发的事件。
  • Paint: 当PictureBox需要进行绘制时触发的事件。
private void Form_Load(object sender, EventArgs e)
{
    // 加载图像到PictureBox
    pictureBox1.Image = Image.FromFile("image.jpg");
    pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
}

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    // 在标题栏显示鼠标坐标
    this.Text = "鼠标坐标:" + e.X + ", " + e.Y;
}

TreeView

TreeView:

功能:用于显示树形结构的数据。它允许用户展开或折叠节点,以查看或编辑层次数据,通常用于创建树状结构的用户界面。

TreeView 控件可以用来展示分层数据,例如文件系统的目录结构、组织结构图、分类目录等。它以树的形式将数据按照层次结构进行显示,每个节点可以有一个父节点和多个子节点。

属性:

  • Nodes :Nodes属性用来操作树的节点。Nodes 属性是一个 TreeNodeCollection 对象,可用于添加、删除和遍历节点。

demo.cs:

// 创建树节点
TreeNode rootNode = new TreeNode("根节点");
rootNode.Nodes.Add("子节点1");
rootNode.Nodes.Add("子节点2");

// 将根节点添加到 TreeView 控件
treeView1.Nodes.Add(rootNode);

ListView

功能:用于以表格形式显示和操作项的集合。它可以在窗体上展示多列的数据,并提供了选中、排序、编辑等功能。

除了基本的操作外,ListView 还提供了其他功能和事件,如排序、编辑、选择、图标设置、视图切换等,可以根据需求进行进一步的定制和扩展。


ListView控件用于显示列表数据,并且使用ListViewItem类来代表每一行的列表项。


ListViewItem类表示ListView中的一个数据行,它包含了该行的显示文本、图像和其他属性。

要使用ListViewItem,可以按照以下步骤操作:

  1. 创建一个ListViewItem对象,可以通过构造函数传入项的文本或者使用ListView.Items.Add方法添加项,例如:
// 创建一个带有文本的ListViewItem
ListViewItem item1 = new ListViewItem("Item 1");

// 或者使用Add方法添加项
listView1.Items.Add("Item 2");
  1. 设置ListViewItem的图像,可以使用ListViewItem.ImageIndex或者ListViewItem.ImageKey属性,其中:
  • ListViewItem.ImageIndex属性使用图像在设置了ListView的LargeImageList或SmallImageList属性的ImageList中的索引。
  • ListViewItem.ImageKey属性使用图像在设置了ListView的LargeImageList或SmallImageList属性的ImageList中的键值。
// 设置项的图像索引
item1.ImageIndex = 0;

// 设置项的图像键值
item1.ImageKey = "key";
  1. 由于ListViewItem类表示ListView中的一个数据行,其中每行的第一列数据的赋值可以通过其Text属性进行赋值,而其他列的数据赋值只能通过子项SubItems赋值。
//设置Text属性方式给每行的第一列数据赋值
item1.Text = xx;

// 设置子项的方式添加每行的其他列的数据
item1.SubItems.Add("Subitem 1");
  1. 将ListViewItem添加到ListView控件中,可以使用ListView.Items集合的Add方法,例如:
listView1.Items.Add(item1);

这样,ListView控件就会显示相应的ListViewItem项。


例如下面的:Demo.cs

//添加列表项
foreach (Student student in list)
{
    ListViewItem listViewItem = new ListViewItem();
    listViewItem.ImageIndex = 0;
    listViewItem.Text = student.NAME;
    listView1.Items.Add(listViewItem);
}

属性:

  • Columns: 此属性可设置列头信息,指定每列的标题、宽度等。

  • Items: 此属性操作项集合,可以添加、删除和修改项。每个项都可以包含多个子项,使用 SubItems 属性来设置子项数据。

    即每行数据,第一列数据是主项数据,其他各列数据均为子项数据。

  • FullRowSelect: 是否开启整行选中

  • Anchor: 当窗体大小变化时,选择哪个方向的边距始终保持不变。

  • Dock: 边框吸附的位置和方向。

  • View: 此属性用于设置视图模式,决定了如何呈现列表项和子项。

    枚举类型,具有以下几个常用的选项:

    1. LargeIcon:以大图标形式显示列表项。每个列表项可以显示一个大图标和一个文本标题。
    2. SmallIcon:以小图标形式显示列表项。每个列表项仅显示一个小图标和一个文本标题。
    3. List:以列表形式显示列表项。每个列表项显示在单独的行上,并且可以包含多个子项。
    4. Details:以详细信息形式显示列表项。每个列表项以多列的形式显示,并且可以包含多个子项。
    5. Tile:以平铺形式显示列表项。每个列表项显示在单独的区域内,可以包含图标、标题和其他自定义内容。
  • ListView控件提供了两个与图像相关的属性:LargeImageList和SmallImageList属性。

    1. LargeImageList属性:

      • LargeImageList属性是一个ImageList对象,用于设置ListView控件中每个项在大图标视图模式下显示的图像列表。
      • 在大图标视图模式下,ListView的每个项通常会显示一个较大的图标和相关文本信息。
      • 通过将LargeImageList属性设置为一个已经填充了图像的ImageList对象,可以为每个项提供相应的图标。
    2. SmallImageList属性:

      • SmallImageList属性也是一个ImageList对象,用于设置ListView控件中每个项在小图标视图模式下显示的图像列表。
      • 在小图标视图模式下,ListView的每个项通常会显示一个较小的图标和相关文本信息。
      • 通过将SmallImageList属性设置为一个已经填充了图像的ImageList对象,可以为每个项提供相应的图标。

      要使用LargeImageList和SmallImageList属性,可以按照以下步骤操作:

      1. 创建一个ImageList对象,并添加需要显示的图像。
      2. 将LargeImageList属性或SmallImageList属性设置为该ImageList对象。

示例代码如下所示:

using System.Windows.Forms;

namespace ListViewExample
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();

            // 设置 ListView 的 View 属性为 Details,以显示多列数据
            listView1.View = View.Details;

            // 添加列头信息
            listView1.Columns.Add("列1", 100);
            listView1.Columns.Add("列2", 100);

            // 添加项信息
            ListViewItem item1 = new ListViewItem("项1");
            item1.SubItems.Add("子项1.1");

            ListViewItem item2 = new ListViewItem("项2");
            item2.SubItems.Add("子项2.1");

            // 将项添加到 ListView 控件
            listView1.Items.Add(item1);
            listView1.Items.Add(item2);
        }
    }
}

在上面的示例中,我们首先将 ListView 的 View 属性设置为 Details,以显示多列数据。然后,通过 Columns 属性添加了两个列头信息。接下来,创建了两个项(item1 和 item2),并使用 SubItems 属性添加了子项的数据。最后,将项添加到 ListView 控件的 Items 集合中。

通过这样的方式,我们可以构建一个表格样式的控件,显示和操作多列的数据。可以根据需要设置列的显示样式、排序方式,以及利用事件和方法处理用户与 ListView 控件的交互。

DataGridView

What:

DataGridView是Windows Forms中的一个数据网格控件,用于在表格形式中展示和编辑数据。它提供了丰富的功能和灵活的定制选项,可以轻松地与数据源进行绑定并进行常见的数据操作。它允许你以表格的形式展示和编辑数据。它可以帮助你轻松地展示和编辑数据。无论是简单的数据展示,还是复杂的数据操作,DataGridView都能提供很好的支持。

DataGridView控件的主要特点和使用方式:

  1. 数据绑定:
    DataGridView可以通过数据绑定将数据源与控件关联起来。它能够与多种数据源进行绑定,包括DataTable、DataSet、List和自定义的数据集合等。通过数据绑定,DataGridView可以自动显示和更新数据。

    //利用DataSource属性即可,下面代码是绑定到一个DataTable对象
    dataGridView1.DataSource = dataTable1;
    
  2. 列定义:
    DataGridView允许你自定义列的类型和外观。它提供了多种列类型,包括文本列、按钮列、复选框列、图片列等。你可以通过代码或设计器来定义列,并设置各种属性,如标题、宽度、格式、排序等。

  3. 数据编辑:
    用户可以直接在DataGridView中编辑单元格的值。可以通过设置ReadOnly属性来控制指定单元格、整行或整个控件是否可编辑。你还可以自定义编辑器来实现更复杂的编辑操作,例如日期选择器或下拉列表框。

  4. 排序和筛选:
    DataGridView支持对数据进行排序和筛选。你可以通过设置列的排序模式和使用内置的排序和筛选功能来实现这些操作。用户可以点击列标题来进行排序,并可以使用自定义的筛选器来筛选数据。

  5. 样式和外观定制:
    你可以通过设置DataGridView和其元素(如单元格、行、列、网格线等)的样式和外观属性来实现定制化。你可以调整颜色、字体、背景、边框等,以满足你的设计需求。

  6. 事件处理:
    DataGridView提供了多个事件来处理用户交互和数据操作。你可以订阅这些事件,例如CellClickCellValueChangedRowValidating等,以响应特定的用户操作和数据变化。

  7. 导出和打印:
    DataGridView支持将数据导出为其他文件格式,例如Excel、CSV等。你可以使用内置的ExportToExcel方法或第三方库来实现导出。此外,DataGridView还提供了打印功能,用于将数据打印为纸质文档。


布局容器

Panel(面板)

  • 其可以类比为做网页时的DIV标签一样,容器的作用。

  • 程序运行时面板的边界是看不到的。

在WinForms中,Panel是一个容器控件,用于容纳其他控件。它是一个可见的矩形区域,可以用来组织、布局和管理其他控件。

Panel通常用于创建自定义的用户界面或划分页面的区域。


以下是Panel控件的一些特点和用法

  1. 容器控件:Panel本身并没有显示任何可见内容,而是用于容纳其他控件。可以将其他控件(如按钮、文本框等)添加到Panel中,从而形成一组有序的控件组合。
  2. 布局和组织:Panel可以帮助将控件按照需要的布局进行组织。通过设置Panel的大小、位置和边距等属性,可以确定Panel内部控件的位置和相对关系。这样可以更灵活地管理界面元素的布局。
  3. 可滚动区域:Panel可以作为一个可滚动的区域,当Panel内的控件超过Panel的显示区域时,可以启用自动滚动功能,以便用户可以通过垂直或水平滚动条查看全部内容。
  4. 视觉效果:Panel可以设置背景颜色、边框样式以及背景图片等属性,以实现一些视觉效果。可以使用独立的图像或者渐变的颜色作为Panel的背景。
  5. 事件处理:Panel控件可以对鼠标和键盘事件进行响应,并且可以通过事件处理器进行自定义操作。例如,可以通过点击Panel上的按钮来触发事件,并执行相应的操作。

以下是Panel一些常用的属性:

  • Size:设置Panel的大小。
  • Location:设置Panel在容器中的位置。
  • BackColor:设置Panel的背景颜色。
  • BorderStyle:设置Panel的边框样式。
  • AutoScroll:设置是否启用Panel的自动滚动功能。
  • Controls:Panel的子控件集合,通过该集合添加或移除其他控件。

总结:Panel控件是WinForms中常用的容器控件,用于组织和管理其他控件。它提供了布局、滚动、背景设置等功能,使得界面的设计和布局更加灵活和易于管理。


GroupBox

GroupBox是一个容器控件,用于将其他相关的控件组合在一起,并提供一个可选的标题。

GroupBox常用于对相关的选项或功能进行分组,一起显示在界面上。


以下是GroupBox控件的一些特点和用法:

  1. 容器控件:GroupBox本身不会显示任何内容,而是用于容纳其他控件。可以将其他控件(如按钮、文本框等)添加到GroupBox中,将它们作为一组显示。

  2. 框架和标题:GroupBox提供一个可选的框架,以突出显示组合控件的区域,并使用标题标识该区域的目的或内容。

    可以通过设置GroupBox的Text属性来设置标题文本。

  3. 布局和组织:GroupBox可以帮助将相关的控件按照需要的布局进行组织。

    通过设置GroupBox的大小、位置和边距等属性,可以确定GroupBox内部控件的位置和相对关系。

  4. 可视化风格:GroupBox可以设置边框样式、边框颜色以及背景颜色等属性,以实现对GroupBox控件的视觉风格定制。可以根据需要选择不同的外观风格。

  5. 事件处理:GroupBox控件可以对鼠标和键盘事件进行响应,并且可以通过事件处理器进行自定义操作。例如,可以使用Click事件来处理GroupBox被点击时所触发的操作。


以下是一些常用的属性:

  • Size:设置GroupBox的大小。
  • Location:设置GroupBox在容器中的位置。
  • Text:设置GroupBox的标题文本。
  • BackColor:设置GroupBox的背景颜色。
  • BorderStyle:设置GroupBox的边框样式。
  • Controls:GroupBox的子控件集合,可以通过该集合添加或移除其他控件。

总结:GroupBox控件是C#中常用的容器控件,用于将相关的控件组合在一起,并提供一个标题文本。

它可以帮助组织界面上的控件,并提供一定的视觉风格和布局控制。


FlowLayoutPanel

FlowLayoutPanel是一个容器控件,用于在一个自动布局的面板中按照流动的方式排列其内部的子控件。


FlowLayoutPanel的主要特点和用法如下:

  1. 自动布局:FlowLayoutPanel会根据容纳的子控件的大小和内容进行自动布局,按照流动的方式从左到右、从上到下排列子控件。它会自动调整子控件的位置和大小,以适应面板的大小变化。
  2. 易于响应窗口调整:当FlowLayoutPanel的大小发生变化时,它会自动重新排列子控件,以适应新的布局。这使得用FlowLayoutPanel创建自适应布局的界面变得更加简单。
  3. 自定义布局:可通过设置FlowLayoutPanel的FlowDirection属性来指定子控件的排列方向,可选择水平(从左到右)或垂直(从上到下)排列。还可以通过设置Padding和Margins属性来指定子控件之间的间隔和边距。
  4. 容纳各种控件:FlowLayoutPanel可以容纳各种类型的控件,并可与其他布局控件(如按钮、文本框、标签等)组合使用。
  5. 动态控件添加和移除:可以通过FlowLayoutPanel的Controls集合添加或移除子控件。添加控件时,FlowLayoutPanel会自动调整布局,确保新控件正确的排列。

以下是一些常用的属性:

  • FlowDirection:获取或设置子控件的排列方向(水平或垂直)。
  • AutoScroll:获取或设置是否启用自动滚动功能。
  • WrapContents:获取或设置是否允许子控件在容器边界处换行。
  • Padding:获取或设置子控件之间的内边距。
  • Controls:FlowLayoutPanel控件的子控件集合,可以通过该集合添加或移除其他控件。

通过上述属性,可以根据需要创建和自定义FlowLayoutPanel控件,实现自动排列子控件的自适应布局。


总结:FlowLayoutPanel是C#中常用的容器控件,用于按照流动的方式自动布局其内部的子控件。它简化了界面布局的过程,使得创建自适应布局的界面变得更加容易和灵活。


TableLayoutPanel

用于以表格的形式排列和组织其内部的子控件。


TableLayoutPanel的主要特点和用法如下:

  1. 表格布局:TableLayoutPanel使用表格的形式来布局和组织子控件。可以指定行数和列数,并在特定的行和列位置放置子控件。
  2. 灵活的单元格布局:TableLayoutPanel的每个单元格可以根据需要调整大小,以适应其内部控件的大小。每个单元格可以独立设置列宽和行高,也可以使用百分比来调整单元格的大小。
  3. 控件位置和对齐:可以通过设置子控件的Row和Column属性,将其放置在TableLayoutPanel的指定单元格中。还可以使用Anchor和Dock属性来对齐子控件在单元格中的位置。
  4. 自动调整布局:TableLayoutPanel可以在窗口大小发生变化时自动调整子控件的布局。这使得TableLayoutPanel适用于创建自适应性强的窗体界面。
  5. 支持嵌套:TableLayoutPanel可以嵌套使用,即在一个单元格中放置另一个TableLayoutPanel。这样可以创建更复杂的布局结构。

使用TableLayoutPanel控件需要注意以下几点:

  • 配置行和列:通过TableLayoutPanel的RowCount和ColumnCount属性,可以设置表格的行数和列数。
  • 设置行高和列宽:通过调整TableLayoutPanel的RowStyles和ColumnStyles属性,可以设置每行和每列的高度和宽度。可以使用固定像素值、百分比或自动大小来设置。

实例化和使用TableLayoutPanel可以通过设计器进行配置,也可以通过编程方式进行设置。以下是一些常用的属性和方法:

  • RowCount和ColumnCount:获取或设置行数和列数。
  • RowStyles和ColumnStyles:获取或设置每行和每列的样式(高度和宽度)。
  • Controls:TableLayoutPanel的子控件集合,可以通过该集合添加或移除其他控件。

总结:TableLayoutPanel是WinForms中常用的容器控件,用于以表格的形式布局和组织子控件。它提供了灵活的表格布局功能,可以根据需要自定义行和列,并自动调整子控件的布局。使用TableLayoutPanel可以创建出结构清晰、自适应性强的窗体界面。


TabControl

TabControl是一个容器控件,用于在一个选项卡式的界面中切换和显示不同的子控件。


TabControl的主要特点和用法如下:

  1. 选项卡式界面:TabControl提供了一个选项卡控件,用于显示多个标签页。每个标签页可以关联一个子控件,并在用户选择相应的标签页时显示该子控件。
  2. 多标签页管理:TabControl允许在运行时添加和删除标签页。可以通过代码动态地添加和移除标签页,以便根据需要调整界面结构。
  3. 导航和切换:用户可以通过点击选项卡来切换显示不同的子控件。TabControl会自动切换当前显示的子控件,并触发一些相关事件,以便应用程序可以响应用户的操作。
  4. 定制样式:可以通过设置TabControl的外观相关属性,如背景颜色、字体、边框样式等,来定制TabControl的外观和风格。
  5. 事件处理:TabControl可以触发一些事件,如SelectedIndexChanged事件,可在切换标签页时执行自定义操作。

以下是一些常用的属性:

  • TabPages:TabControl的标签页集合,可以通过该集合添加、移除和操作标签页。
  • SelectedIndex:获取或设置当前选中的标签页的索引。
  • SelectedTab:获取或设置当前选中的标签页。
  • Alignment:获取或设置标签的对齐方式(顶部、底部、左侧或右侧)。
  • Multiline:获取或设置是否支持多行标签。

总结:TabControl是WinForms中常用的容器控件,用于实现一个选项卡式的界面,通过切换选项卡显示不同的子控件。它提供了多标签页管理、定制样式、导航和切换等功能,使界面切换和导航变得简单直观。


SplitContainer

在WinForms中,SplitContainer是一个容器控件,用于将窗体分割成两个可调整大小的面板。

SplitContainer的主要特点和用法如下:

  1. 分割面板:SplitContainer将窗体分割为两个面板,一个水平的或垂直的分割面板。可以通过拖动分隔条来调整面板的大小,从而控制它们的相对大小。
  2. 可调整大小:SplitContainer允许用户根据需要调整面板的大小。可以通过拖动分隔条来改变面板大小,以适应用户对界面布局的需求。
  3. 嵌套面板:SplitContainer可以嵌套使用,即在一个面板中放置另一个SplitContainer。这样可以创建更复杂的层级结构,实现更灵活的布局。
  4. 自动大小调整:SplitContainer可以根据窗体的大小调整其内部面板的大小。这使得创建自适应布局的界面变得更加简单。
  5. 事件处理:SplitContainer提供了一系列事件,如SplitterMoving、SplitterMoved等,用于处理分隔条的移动和调整大小的操作。可以通过事件处理器来自定义操作。

以下是一些常用的属性:

  • Orientation:获取或设置分割面板的方向(水平或垂直)。
  • FixedPanel:获取或设置一个固定大小的面板,不会随分隔条的移动而改变大小。
  • Panel1和Panel2:分割面板中的两个面板,可以通过这两个属性来访问和操作。
  • SplitterDistance:获取或设置分隔条离SplitContainer容器的边的距离。

总结:SplitContainer是WinForms中常用的容器控件,用于将窗体分割为两个可调整大小的面板。它提供了面板的分割和调整大小的功能,并支持嵌套使用。使用SplitContainer可以实现界面的分割布局和面板的自适应调整,使得界面布局更加灵活和可调整。


菜单和工具栏

  • MenuStrip: 菜单栏

  • StatusStrip:状态栏

  • ToolStrip:工具栏

  • ContextMenuStrip:上下文菜单栏(右键菜单)

    (不同位置右键出来的菜单不一样)

    注意:

    要让组件的ContextMenuStrip属性与此右键菜单进行绑定。

注意Note:

  1. 输入英文输入下的-符号可以插入一个分割横线。

  2. 菜单栏上小括号里的大写英文字母是助记符,利用Alt+英文字母的快捷键可以打开相应的菜单栏。

    在利用UI进行助记符的文本编辑时,除了直接输入(F),还需要在前面加上一个&符号,即: &(F)才可以。

    在这里插入图片描述

  3. 如果要在子菜单中增加快捷键的设置,可以在相应的菜单中右键选择属性,进入ShortcutKeys属性进行设置,如下:

    在这里插入图片描述

  4. 如果要在子菜单中增加一个图标,可以在相应的菜单中右键选择属性,进入Image属性进行设置,如下:

    在这里插入图片描述

  5. 添加一个关于菜单的窗体,可以不用直接新建窗体,而可以通过项目右键选择添加,再选择新建项,选择Windows Forms,选择关于Box即可新建,如下:

    在这里插入图片描述

    对于关于框中相关信息的修改,可以通过项目右键选择属性,再选择程序集信息,进入编辑即可。

    在这里插入图片描述


ADO.NET

.Net(framework)和ADO.Net

  1. 什么是ADO.Net?

    1. ADO.NET(ActiveX Data Objects .NET)是为Microsoft .NET平台提供的一组数据访问技术,用于在.NET应用程序中与各种数据源进行交互。ADO.NET是.NET Framework中的核心组件之一,用于连接和操作数据库。
    2. ADO.NET 开发阶段类似于Java中利用原生代码访问数据库的阶段。
    3. 它通过提供一组类和接口,允许开发人员使用统一的编程模型来访问和操作这些数据源。
    4. ADO.NET是.NET Framework中的数据访问技术,提供了用于连接、查询、更新和操作各种数据源的一组类和接口。它通过连接对象、命令对象、数据阅读器、数据适配器等组件,提供了灵活、高性能和可扩展的方式来处理数据库交互。ADO.NET的特点包括对多种数据源的支持、数据缓存、事务处理和参数化查询等功能,大大简化了.NET应用程序与数据库的交互过程。
    5. 在这里插入图片描述
  1. ADO.NET的主要组件和特点?

    1. 连接(Connection):ADO.NET提供了连接对象,用于与数据源建立连接。开发人员可以使用提供程序特定的连接对象(如SqlConnection、OracleConnection等)来创建和管理与数据库的连接。

    2. 命令(Command):ADO.NET的命令对象用于执行SQL语句或存储过程。通过命令对象,开发人员可以向数据源发送SQL查询或更新语句,并接收返回的结果。

    3. 数据阅读器(DataReader):DataReader是只进只读的结果集,用于高效地读取和处理大型数据集。当执行查询操作时,开发人员可以通过DataReader逐行读取结果,而无需将全部数据加载到内存中,这个对象不是new出来的,一般作为结果返回而间接创建的。

      如下:

      每次指向某一行数据,再根据索引取出其中某列数据。

      在这里插入图片描述

    4. 数据适配器(DataAdapter):数据适配器负责将数据库中的数据以DataSet(数据集)的形式缓存在客户端内存中。它通过填充DataSet中的DataTable对象,将数据库中的数据转换为应用程序可以操作的格式。

    5. 数据集(DataSet):DataSet是ADO.NET中的核心数据容器。它是一个内存中的数据集合,可以包含多个DataTable对象,并且支持数据之间的关系和约束。

      即: 不管数据源是什么,DataSet的作用是将其数据复制一份到内存中,其存储了多张数据表(DataTable),里面的行对象称为DataRow对象,里面的列对象称为DataColumn对象。

    6. 事务(Transaction):ADO.NET支持事务处理,用于执行一系列数据库操作的原子性提交或回滚。通过Transaction对象,可以管理多个命令或数据库操作的事务性。

    7. 参数化查询:ADO.NET提供了参数化查询的功能,可以安全地构建并执行包含参数的SQL语句。参数化查询可以防止SQL注入攻击,并提高性能和可维护性。

直连式

  1. 什么是直连式?

    即读取数据的过程中数据库的连接是不能关闭的,说明数据并不直接存在于内存,而是数据库。

  2. 有什么优劣?

    优点:

    • 速度快

    缺点:

    • 需要持续保持数据库的连接,如果并发高的情况下,则会保持很多的数据库连接,影响并发效果。
    • 读取数据的指针只能一个一个即一行一行的往下移。
步骤

一: 添加动态链接:

Visual Studio 中选择项目-> 管理NuGet程序包(N) -> 然后在浏览里面搜索 MySql.Data 并进行安装:

注意

因为 .Net 框架 和 MySQL 版本问题安装时可能要选用不同的版本

在这里插入图片描述
在这里插入图片描述

二: 测试连接

  1. 创建一个类来放数据库的连接和各种操作,我这里创建的是 Dao.cs
  2. 加入需要的头文件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySql.Data.MySqlClient; // 这个是必须的
  1. 连接数据库,并返回一个 MySqlConnection 对象;并实现基本操作;
namespace BookMS
{
    class Dao
    {
        MySqlConnection conn;
        // String sql = $"SELECT * FROM t_admin WHERE id = '{textBox1.Text}' and pwd = '{textBox2.Text}'";
      public MySqlConnection getConn()
        {
            string connstr = "server=127.0.0.1;port=3306;user=root;password=****;database=bookdb;Charset=utf8;";
          	// 其中server是数据库所在网络的IP地址,127.0.0.1代表本地,port是数据库设置的端口号,user用户名,password密码,database是要连接的数据库名,Charset=utf8主要是处理中文编码问题
            conn = new MySqlConnection(connstr);
            conn.Open(); // 打开数据库
            return conn; // 返回数据库对象
        }
        public MySqlCommand command(string sql)
        {
            MySqlCommand cmd = new MySqlCommand(sql, getConn());
            return cmd;
        }
        public int Execute(string sql) // 更新操作
        {
            return command(sql).ExecuteNonQuery();
        }
        public MySqlDataReader read(string sql) // 读取操作
        {
            return command(sql).ExecuteReader();
        }

        public void DaoClose() // 关闭数据库连接
        {
            conn.Close(); 
        }
    }
}
  1. 查询操作
MySqlConnection conn = getConn(); //连接数据库
conn.Open(); //打开数据库连接
string sql = "select * from user'" ;
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader mdr = cmd.ExecuteReader();
if (mdr.Read()) {
    string str = mdr["authority"].ToString();//接收一个返回值
    //对查询到数据进行相应的操作
}
conn.Close();
  1. 增删改操作类似,只是 sql 语句不相同,这里以插入操作为例
MySqlConnection conn = getConn(); //连接数据库
conn.Open(); //打开数据库连接
string sql = "insert into user values('123','123')";
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.ExecuteNonQuery();
conn.Close();

说明:在进行对数据库具体操作时建议在 Dao 类中直接写不同的函数来实现,在Form代码处创建 Dao 对象来引用对应的方法,这样可以使代码更加简洁,同时也方便维护

Demo

demo.cs

using MySql.Data.MySqlClient;//引入mysql连接客户端

private void Form1_Load(object sender, EventArgs e)
{
    //使用数据库中的数据填充listBox
    DataBindings();
}

/// <summary>
/// 连接数据库获取数据到ListBox中
/// </summary>
private void DataBindings()
{
    //1.创建数据库连接
    string connstr = "server=127.0.0.1;port=3306;user=root;password=root;database=dwiot_cloud;Charset=utf8;";
    // 其中server是数据库所在网络的IP地址,127.0.0.1代表本地,port是数据库设置的端口号,user用户名,password密码,database是要连接的数据库名,Charset=utf8主要是处理中文编码问题
    MySqlConnection conn = new MySqlConnection(connstr);
    try
    {
        //2. 打开数据库
        conn.Open();

        //3. 创建sql语句和执行命令的对象
        string sql = "select id,username from sys_user";
        MySqlCommand cmd = new MySqlCommand(sql, conn);

        //4. 执行查询语句,声明结果集对象,用于检索数据
        MySqlDataReader mdr = cmd.ExecuteReader();

        //遍历mdr数据,判断有无数据可读
        if (mdr.HasRows)
        {
            while (mdr.Read())
            {
                listBox1.Items.Add(mdr[1]);
            }
        }
        else
        {
            MessageBox.Show("根本没数据");
        }
    }catch(Exception e){
        MessageBox.Show("数据库操作遇到异常:{0}", e.Message);
    }
    finally
    {
        if(conn.State != ConnectionState.Closed)
        {
            //关闭连接
            conn.Close();
        }

    }

注意:

  • 利用直连式连接数据库,需要注意写:

    数据库连接对象的Open()方法

    数据库连接对象的Close()方法

  • 若直接式连接数据库,且使用了using语句,则可以不用手动写数据库连接的Close()方法。

断开式

即主要通过DataAdapter对象将数据copy到内存中DataSetDataTable中,数据就从DataTable中获取,而不是一直从数据库中获取。


注意:

  • 使用了DataAdapter对象,其会自动帮我们处理数据库连接对象的打开和关闭,所以我们在代码中不需要写关于连接对象的打开和连接对象关闭等的代码。
Demo

demo.cs:

using MySql.Data.MySqlClient;
using System.Configuration;

//读取配置文件连接字符串字段
private string strConn = ConfigurationManager.ConnectionStrings["DB"].ConnectionString;

//数据库数据放到DataTable,再将DataGridView的数据源绑定到DataTable
private void BindData()
{
    try
    {
        //创建数据库连接对象
        MySqlConnection conn = new MySqlConnection(strConn);

        //书写sql,创建命令对象并赋值
        string sql = "select id,username,realname,password,salt from sys_user";
        MySqlCommand cmd = new MySqlCommand(sql, conn);

        //创建DataAdapter对象,传递Command对象
        //DataAdapter对象可以自动控制数据库连接对象的开和关
        MySqlDataAdapter mda = new MySqlDataAdapter();
        mda.SelectCommand = cmd;

        //创建空白的DataTable对象,用于存储和copy数据库的数据
        DataTable db = new DataTable();


        //填充数据库数据到DataTable中

        mda.Fill(db);

        //将DataTable数据作为DataGridView的数据
        dataGridView1.DataSource = db;
    }catch(MySqlException e)
    {
        MessageBox.Show("error:" + e.Message);
    }

}

配置连接字符串到配置文件

  1. App.config配置文件中配置与数据库连接相关的连接字符串信息:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
	<!--数据库连接字符串,名字叫做DB-->
	<connectionStrings>
		<add name="DB" connectionString="server=127.0.0.1;port=3306;user=root;password=root;database=dwiot_cloud;Charset=utf8;" providerName="MySql.Data.MySqlClient" />
	</connectionStrings>
</configuration>
  1. cs文件中读取字符串信息:
//先确保项目目录下的引用文件夹下有这个类,否则这里using也白搭
using System.Configuration;//读取配置文件引用文件

//读取配置文件中名字叫做DB的字符串数据内容的ConnectionString字段的数据
private string strConn = ConfigurationManager.ConnectionStrings["DB"].ConnectionString;

参数化查询(防sql注入)

参数化查询是一种防止 SQL 注入攻击的重要技术,也可以提高查询性能。通过使用参数化查询,可以将输入的用户数据安全地传递给 SQL 查询语句,而不是直接将用户数据嵌入到 SQL 语句中。这样可以防止恶意用户输入恶意的 SQL 代码。

在 WinForms 中使用参数化查询,需要使用 ADO.NET 提供的 MySQL 数据库连接对象(MySqlConnection)、命令对象(MySqlCommand)以及参数对象(MySqlParameter)。

使用步骤:

步骤 1:添加引用和命名空间
在项目中的引用文件夹中添加引用,并在代码文件的顶部添加以下命名空间引用:

using MySql.Data.MySqlClient;

步骤 2:创建数据库连接
在代码中创建 MySqlConnection 对象来建立到 MySQL 数据库的连接。需要提供 MySQL 数据库的连接字符串,该字符串包含了数据库服务器的地址、用户名、密码和数据库名称等信息。

string connectionString = "server=127.0.0.1;port=3306;user=root;password=root;database=dwiot_cloud;Charset=utf8;";
MySqlConnection connection = new MySqlConnection(connectionString);

步骤 3:创建参数化查询
创建 MySqlCommand 对象,并设置 SQL 查询语句,其中使用 @parameter 形式的参数占位符来代替实际的参数值

//1.使用 `@parameter` 形式的参数占位符来代替实际的参数值
string query = "SELECT * FROM products WHERE name LIKE @searchTerm";
//2.创建MysqlCommand实例对象
MySqlCommand command = new MySqlCommand(query, connection);
//3.利用MysqlCommand对象.Parameters.AddWithValue方法
//   第一个参数是: 对应的@parameter占位符
//   第二个参数是: 这个占位符实际的取值
command.Parameters.AddWithValue("@searchTerm", "%" + searchTerm + "%");

步骤 4:查询数据库
执行查询语句并获取查询结果。

DataTable table = new DataTable();
MySqlDataAdapter adapter = new MySqlDataAdapter(command);
adapter.Fill(table);

步骤 5:处理查询结果
将查询结果作为数据源绑定到 WinForms 控件上,例如 DataGridView 控件,以显示查询结果。

//绑定数据
dataGridView1.DataSource = table;

完整示例代码如下:

using System;
using System.Data;
using System.Windows.Forms;
using MySql.Data.MySqlClient;



private void MainForm_Load(object sender, EventArgs e)
{
    string connectionString = "server=127.0.0.1;port=3306;user=root;password=root;database=dwiot_cloud;Charset=utf8;";
    connection = new MySqlConnection(connectionString);

    try
    {
        connection.Open(); // 打开数据库连接
    }
    catch (Exception ex)
    {
        MessageBox.Show("无法连接到数据库:" + ex.Message);
        return;
    }
}

private void btnSearch_Click(object sender, EventArgs e)
{
    string searchTerm = txtSearchTerm.Text;
	//参数化sql语句(格式:@+变量名)
    string query = "SELECT * FROM products WHERE name LIKE @searchTerm";

    MySqlCommand command = new MySqlCommand(query, connection);
    //参数化sql语句(格式:@+变量名)
    command.Parameters.AddWithValue("@searchTerm", "%" + searchTerm + "%");

    try
    {
        DataTable table = new DataTable();
        MySqlDataAdapter adapter = new MySqlDataAdapter(command);
        adapter.Fill(table);

        dataGridView1.DataSource = table; // 将查询结果显示在 DataGridView 控件中
    }
    catch (Exception ex)
    {
        MessageBox.Show("查询出错:" + ex.Message);
    }finally{
        connection.Close(); // 关闭数据库连接
    }
}

//在上述示例中,首先创建了一个 WinForms 应用程序,并在窗体加载时建立与 MySQL 数据库的连接。然后,在按钮点击事件中执行参数化查询,将查询结果绑定到 DataGridView 控件上。最后,在窗体关闭时关闭数据库连接。用户可以在文本框中输入查询条件,并点击按钮来进行查询操作。

//通过使用参数化查询,我们将用户输入的 searchTerm 值以参数的形式传递给查询语句,避免了 SQL 注入攻击的风险,并且保证了查询的安全性和性能。

winform项目打包exe

在Visual Studio中,创建WinForms应用的exe文件实际上是在编译过程中自动进行的。

编译成功后,exe文件位于项目路径的bin\Debug或bin\Release目录下(取决于编译输出模式的配置)。

以下是将WinForms项目打包为exe程序并供其他计算机使用的步骤:

  1. 在编写代码并测试完成后,确保你处在要打包的解决方案中。
  2. 点击vs菜单栏中的生成菜单选项,然后选择生成解决方案。这将开始Compile或包含在解决方案中的所有项目。确保编译选项是Release,而不是Debug,因为Release版本可以达到更好的性能。
  3. 编译完成后,找到你项目的输出目录。默认的输出目录通常在你的项目文件夹内的bin\Release子文件夹。
  4. 在目标计算机上,只需将这些所需的文件和文件夹复制过去(打成压缩包),然后解压运行其中的exe文件即可。

注意

在 .NET 开发中,执行文件(可执行文件)通常是带有 .exe 扩展名的二进制可执行文件。这些文件包含了程序的代码和所有运行所需的依赖项。在使用 .NET 技术进行开发时,这些 .exe 文件可以是基于 .NET Framework、.NET Core 或 .NET 5+ 的。

目标机器上需要安装正确版本的.NET Framework才能运行你的应用程序。

运行exe文件前,确保已经安装了所需的.NET Framework。

如果没有,你需要提供.NET Framework的安装程序或引导用户去下载安装。如果使用了.NET Core(现在是.NET 5及更新版本),可以选择发布为自包含的应用,这样无需单独安装.NET运行时环境。

对于较新的 Windows 系统,如 Windows 8、Windows 8.1、Windows 10,以及后续版本,通常会预装一些版本的 .NET Framework。这样,一些基于 .NET Framework 的应用程序可以直接运行,而不需要用户手动安装 .NET Framework。

一般来说,Windows 系统中的 .NET Framework 版本是通过 Windows 更新进行安装和更新的。例如,Windows 10 中的 “.NET Framework 3.5” 可以通过控制面板的 “程序和功能” -> “启用或关闭 Windows 功能” 中进行启用或禁用。此外,Windows 10 还可能会自动安装 .NET Core 运行时,以支持运行基于 .NET Core 的应用程序。

总的来说,较新版本的 Windows 系统中通常都预装了一些 .NET Framework 版本,但特定的应用程序可能需要特定版本的 .NET Framework,这可能需要用户手动安装或应用程序提供自包含的运行时。


The End!!创作不易,欢迎点赞/评论!!欢迎关注个人GZH!!

在这里插入图片描述

  • 13
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值