VS操作快捷鍵
(說實(shí)話,我塊吐了)
這和VScode完全不在一個(gè)檔次,但無奈VSCode調(diào)試Winform程序不太可能,只能湊合
- VS代碼美化: ctrl + K + F
- 任何你看到的代碼提示都可以雙TAB輸入
- 類的無參構(gòu)造函數(shù) ctor +雙TAB
- 類的屬性 prop + 雙TAB
Tips
- 每個(gè)解決方案里可以放多個(gè)項(xiàng)目,但需要把一個(gè)項(xiàng)目設(shè)置為啟動(dòng)項(xiàng)目
- 窗體ICON圖標(biāo)一般大小 32*32
- 我們自己寫的初始化語句最好寫在窗體load方法中
- 有時(shí)候一些控件遮擋另一些控件,此時(shí)我們可以在對應(yīng)位置右鍵,在彈出框中選擇后面的控件

有些事件是有時(shí)態(tài)的,比如closing和closed;這跟英語的時(shí)態(tài)邏輯一樣. 在做清理、銷毀等程序時(shí),放在closing里比較適合
使用進(jìn)程管理器等外部工具關(guān)閉窗口時(shí),是不會觸發(fā)內(nèi)部的closing和closed方法的
下面這些事件可以讓程序互動(dòng)性更好,比如添加hover等效果

- 所有的控件均被this.Controls管理著
- 如果有超鏈接可以用LinkLabel來做,和label一樣,只是樣式更像鏈接
一、combox下拉列表控件
1. 外觀樣式
combox的外觀分為三種:

其中simple模式下不用下拉,直接展現(xiàn):

DropDown和DropDownList的區(qū)別是 DropDown的選中文字可以修改,DropDownList的選中項(xiàng)目不能修改


2. combox導(dǎo)入數(shù)據(jù)及級聯(lián)小例子

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
Dictionary<string, string> D1 = new Dictionary<string, string> { };
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
D1.Add("北京", "東城,西城,故宮");
D1.Add("上海", "閔行,寶山,陸家嘴");
D1.Add("濟(jì)南", "趵突泉,大明湖,英雄山");
foreach (var item in D1)
{
comboBox1.Items.Add( item.Key);
}
comboBox1.SelectedIndex = 0;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
comboBox2.Items.Clear();
comboBox2.Items.AddRange(D1[comboBox1.SelectedItem.ToString()].Split(','));
comboBox2.SelectedIndex = 0;
}
}
}
二. CheckBox復(fù)選框
1. CheckBox可以設(shè)置三種狀態(tài)
就像下面的例子. 想達(dá)到這種效果,我們只需要將需要三態(tài)的復(fù)選框的ThreeState屬性設(shè)為True
然后操作其CheckState屬性即可.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void ChildCheckBox_CheckedChanged(object sender, EventArgs e)
{
if (checkBox2.Checked & checkBox3.Checked)
checkBox1.CheckState = CheckState.Checked;
else if (!checkBox2.Checked & !checkBox3.Checked)
checkBox1.CheckState = CheckState.Unchecked;
else
checkBox1.CheckState = CheckState.Indeterminate;
}
}
}
三. 列表選擇框 ListBox

- ListBox中的元素可以通過屬性Items來添加或綁定
- ListBox中的多選與否可以用SelectionMode來選定

- 如果是單選, 可以用
listBox1.SelectedItem獲取被選擇對象, 也可以使用listBox1.SelectedIndex訪問被選中的項(xiàng)的索引. - 如果是多選, 可以用
listBox1.SelectedItems獲取被選擇對象集合, 用listBox1.SelectedIndex獲取被選中對象們的索引集合. (要遍歷) - 我們可以使用
listBox1.DataSource來指定列表框的數(shù)據(jù)源
List<int> list1 = new List<int>();
for (int i = 0; i < 10; i++)
{
list1.Add(i);
}
listBox1.DataSource = list1;
- 確定了DataSource,我們可以使用
listBox1.DisplayMember來指定顯示DataSource的哪個(gè)屬性作為listBox1.SelectedValue展示 - 同時(shí), 我們可以使用``
比如:
我們的DataSource是很多魚, 這些魚有自己的Name和No, 我們想再列表中展示它們的Name
魚的類定義如下:
class Fish
{
public Fish()
{
}
public string Name { get; set; }
public int No { get; set; }
}
我們做這么一個(gè)ListBox
public Form1()
{
InitializeComponent();
List<Fish> list1 = new List<Fish>();
for (int i = 0; i < 10; i++)
{
Fish fishTemp = new Fish {
Name = "??Fish"+i.ToString()+"??",
No = 0+i
};
list1.Add(fishTemp);
}
listBox1.DataSource = list1;
listBox1.DisplayMember = "Name";
listBox1.ValueMember = "No";// listBox1.SelectedValue以對象的No作為value
}
private void listBox1_SelectedValueChanged(object sender, EventArgs e)
{
Console.WriteLine(listBox1.SelectedValue);
}

注意: winforms里的數(shù)據(jù)不是雙向綁定的, 所以要更新數(shù)據(jù)源的內(nèi)容時(shí), ListBox的內(nèi)容并不會跟著刷新. 要自己刷新的
例: 點(diǎn)擊刷新列表
private void Reflash_BTN_Click(object sender, EventArgs e)
{
list1.Add(new Fish { Name = "?美人魚?", No=998});
listBox1.DataSource = null;
listBox1.DataSource = list1;
listBox1.DisplayMember = "Name";
listBox1.ValueMember = "No";
}

四. 打開文件對話框 openFileDialog

添加此控件會顯示在GUI設(shè)計(jì)界面底下

選擇好文件后會觸發(fā): FileOk事件

可以用OpenFileDialog1.FileName或者OpenFileDialog1.FileNames讀取文件路徑
同時(shí), 我們可以用以下格式為其添加格式篩選器
圖片文件|*.jpg;*.png|Excle文件|*.xls|所有文件|*.*

五. 時(shí)間日期選擇器 dateTimePicker

1. 我們可以調(diào)整控件的format屬性來調(diào)整顯示格式:
- long : 2020年 8月 3日
- short: 2020-08-03
- time: 14:41:16
-custom : 自定義. 選定此項(xiàng)后 在屬性customformat中定義格式.

2. 我們可以通過dateTimePicker.Value來獲取選擇
返回的是一個(gè)DateTime類型的數(shù)據(jù)
DateTime類型的數(shù)據(jù)有很多方法獲取此時(shí)間的信息. 請自行嘗試
3. 我們也可以通過dateTimePicker.Text來獲取選擇
返回的是一個(gè)string類型的數(shù)據(jù), 而且受格式設(shè)置影響
六. 進(jìn)度條 ProcessBar
關(guān)鍵屬性:
- MaxNum : 最大值
- MinNum : 最小值
- Step : 步進(jìn)幅度 調(diào)用
ProgressBar.PerformStep();時(shí)的步進(jìn) - value : 除了調(diào)用
ProgressBar.PerformStep();,我們也可以直接控制value的值,如
ProgressBar1.Value= ProgressBar1.Value+ ProgressBar1.Step;
- 我們分步驟完成某事時(shí)也可以用這種進(jìn)度條
例子:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void BTN2_Click(object sender, EventArgs e)
{
if (ProgressBar1.Value == ProgressBar1.Maximum)
{
Form2 form2 = new Form2();
form2.ShowDialog();
}
ProgressBar1.PerformStep();
label1.Text = ProgressBar1.Value.ToString()+ "%";
}
private void BTN1_Click(object sender, EventArgs e)
{
if (ProgressBar1.Value>0) ProgressBar1.Value = ProgressBar1.Value- ProgressBar1.Step;
label1.Text = ProgressBar1.Value.ToString();
}
}
}
七. 數(shù)字輸入框 numericUpDown
關(guān)鍵屬性:
- Maximum : 最大值
- Minimum : 最小值
- DecimalPlaces: 小數(shù)點(diǎn)后位數(shù)
- Increment: 增長步進(jìn)
- value : 當(dāng)前的值
- Hexadecimal : 是否用16進(jìn)制
- ThousandsSeparator : 是否有千位分割逗號

八. 氣泡提示 ToolTip
tooltip控件并不會放在窗體上,而是在窗體下的不可視控件區(qū)域里
重要屬性:
- AutoPopDelay : 氣泡彈出后的持續(xù)時(shí)間
- InitialDelay : 觸發(fā)前延時(shí)時(shí)間
- AutomaticDelay : 鼠標(biāo)懸停時(shí)間
- IsBalloon: 是否是氣泡風(fēng)格
- ToolTipIcon: 提示圖標(biāo). 可以是提示,警告 錯(cuò)誤
- ToolTipTitle : 提示的標(biāo)題
設(shè)置完成后, 我們點(diǎn)開其他控件, 在屬性欄里就能找到對應(yīng)的tooltip, 并可以設(shè)置具體提示內(nèi)容

如果用代碼添加:
toolTip1.SetToolTip(textBox3,"textbox3用代碼綁定了tooltip1,這是它的提示內(nèi)容");

tooltip.show()
九. 托盤 notifyIcon
- 一般的窗體最小化時(shí),會在任務(wù)欄上顯示, 如果想最小化到托盤, 我們可以先把窗體的ShowInTaskBar屬性false了
- notifyIcon必須設(shè)置自己的Icon圖標(biāo)才會在托盤中顯示
- 需要添加雙擊事件來還原窗口,最常見的是綁定它的鼠標(biāo)雙擊事件
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
this.WindowState = FormWindowState.Normal;
}
托盤圖標(biāo)上加上下文菜單可以實(shí)現(xiàn)更多內(nèi)容, 詳見下一節(jié)
十. 上下文菜單 contextMenuStrip

在菜單項(xiàng)上右鍵還有更多選項(xiàng)

和tooltip一樣, 這個(gè)控件要綁定在別的控件身上
比如,綁定在托盤上


十一. 節(jié)點(diǎn)樹控件 TreeView
關(guān)鍵屬性:
- node : 集合 在里面添加一級\二級\三級菜單 Nodes作為所有子項(xiàng)的集合


- checkboxs : 節(jié)點(diǎn)前是否有checkbox
- itemHeight : 條目高度
例: 代碼管理節(jié)點(diǎn)樹

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp3
{
public partial class Form1 : Form
{
int num = 0;
public Form1()
{
InitializeComponent();
}
private void BTN01_Click(object sender, EventArgs e)
{
TreeNodeCollection tv1 = this.treeView1.Nodes;
TreeNode tn1 = new TreeNode();
tn1.Name = "newNode" + num.ToString();
tn1.Text = "新的根節(jié)點(diǎn):" + num++.ToString();
tv1.Add(tn1);
}
private void BTN3_Click(object sender, EventArgs e)
{
TreeNodeCollection tv1 = this.treeView1.Nodes;
tv1.Remove(treeView1.SelectedNode);
}
private void treeView1_NodeMouseClick(object sender, TreeViewEventArgs e)
{
textBox1.Text = treeView1.SelectedNode.Text;
}
private void BTN02_Click(object sender, EventArgs e)
{
TreeNode tn1 = new TreeNode();
tn1.Name = "newNode" + num.ToString();
tn1.Text = "新的子根節(jié)點(diǎn)";
treeView1.SelectedNode.Nodes.Add(tn1);
}
}
}
十二. 列表視圖 ListView
其實(shí)每個(gè)控件上都有一個(gè)快捷擴(kuò)展箭頭用來進(jìn)行一些主要的設(shè)置


重要屬性:
- View : 視圖的形式, 一般選detail
- colums : 列的集合
可以在屬性欄選擇此屬性也可以用快捷方式選擇:編輯列

添加完成后:

- items : 集合 項(xiàng)的集合(每一行被稱為一個(gè)項(xiàng)). 第一列被自動(dòng)認(rèn)為是主鍵, 其他列的內(nèi)容作為數(shù)據(jù)(子項(xiàng))添加入集合subitems中, 如果設(shè)置了groups, 還可以對其進(jìn)行分組管理


groups : 對items進(jìn)行分組管理, 可以用ShowGroups屬性管理groups的顯示
CheckedItems : 是前面打勾的項(xiàng) //和SelectedItems不一樣
SelectedItems: 是被選擇的 //和CheckedItems 不一樣

例: 學(xué)生管理系統(tǒng)

我們創(chuàng)立了一個(gè)簡單的Student對象
student.cs
namespace WindowsFormsApp4
{
class Student
{
public Student()
{
}
public string Stu_No { get; set; }
public string Stu_Name { get; set; }
public string Stu_Sex { get; set; }
public int Stu_Chinese { get; set; }
public int Stu_Math { get; set; }
public int Stu_English { get; set; }
}
}
在主窗口中:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//創(chuàng)建一個(gè)學(xué)生,并初始化
Student stu1 = new Student();
stu1.Stu_No = textBox1.Text;
stu1.Stu_Name = textBox2.Text;
stu1.Stu_Sex = comboBox1.SelectedItem.ToString();
stu1.Stu_Chinese = (int) numericUpDown1.Value;
stu1.Stu_Math = (int) numericUpDown2.Value;
stu1.Stu_English = (int) numericUpDown3.Value;
//將學(xué)生添加到listView中
AddStu(stu1);
//一些善后工作
textBox1.Text = (listView1.Items.Count + 1).ToString("000");
textBox2.Text = "";
}
private void Form1_Load(object sender, EventArgs e)
{
textBox1.Text = (listView1.Items.Count + 1).ToString("000");
}
private void AddStu(Student stu)
{
//創(chuàng)建一個(gè)項(xiàng)目, 將傳入的學(xué)生的信息傳遞給他
ListViewItem listViewItem1 = new ListViewItem();
listViewItem1.Text = stu.Stu_No;
listViewItem1.SubItems.Add(stu.Stu_Name);
listViewItem1.SubItems.Add(stu.Stu_Sex);
listViewItem1.SubItems.Add(stu.Stu_Chinese.ToString());
listViewItem1.SubItems.Add(stu.Stu_Math.ToString());
listViewItem1.SubItems.Add(stu.Stu_English.ToString());
listView1.Items.Add(listViewItem1);
}
private void button2_Click(object sender, EventArgs e)
{
//遍歷check中的條目,刪除它們
foreach (ListViewItem item in listView1.CheckedItems)
{
listView1.Items.Remove(item);
textBox1.Text = (listView1.Items.Count + 1).ToString("000");
}
}
}
}
ListView顯示圖片
首先有三種顯示圖片的模式:

其次 數(shù)據(jù)源要使用一個(gè) ImageList 控件生成
然后綁定這個(gè)imageList

最后每一類都可以指定 imageIndex 來決定顯示哪一張圖片
十三. 面板 panel
panel相當(dāng)于div, 是一個(gè)容器
十四. 分隔容器 splitContainer
它的特點(diǎn)是可以將布局分為兩個(gè)panel, 且可以調(diào)整大小

這個(gè)控件不容易被選定, 可以通過這種方法選定

借用分隔容器 我們可以輕松的實(shí)現(xiàn)基本的分隔式布局

重要屬性:
- Orientation : 是水平分隔還是豎直分隔
- Panel1Collapsed : 折疊splitContainer的Panel1嗎?
- Panel2Collapsed : 折疊splitContainer的Panel2嗎?
利用這些屬性,可以方便的做成邊界可調(diào)的效果

十五. TabControl 標(biāo)簽控制器

關(guān)鍵屬性:
- TabPages : 集合. Tab頁面的集合

- Alignment : 標(biāo)簽顯示的位置