WinForm入门(三) 常用控件

VS操作快捷键

(说实话,我块吐了)
这和VScode完全不在一个档次,但无奈VSCode调试Winform程序不太可能,只能凑合

  • VS代码美化: ctrl + K + F
  • 任何你看到的代码提示都可以双TAB输入
  • 类的无参构造函数 ctor +双TAB
  • 类的属性 prop + 双TAB

Tips

  • 每个解决方案里可以放多个项目,但需要把一个项目设置为启动项目
  • 窗体ICON图标一般大小 32*32
  • 我们自己写的初始化语句最好写在窗体load方法中
  • 有时候一些控件遮挡另一些控件,此时我们可以在对应位置右键,在弹出框中选择后面的控件
  • 有些事件是有时态的,比如closing和closed;这跟英语的时态逻辑一样. 在做清理、销毁等程序时,放在closing里比较适合

  • 使用进程管理器等外部工具关闭窗口时,是不会触发内部的closing和closed方法的

  • 下面这些事件可以让程序互动性更好,比如添加hover等效果

  • 所有的控件均被this.Controls管理着
  • 如果有超链接可以用LinkLabel来做,和label一样,只是样式更像链接

一、combox下拉列表控件

1. 外观样式

combox的外观分为三种:

其中simple模式下不用下拉,直接展现:

DropDown和DropDownList的区别是 DropDown的选中文字可以修改,DropDownList的选中项目不能修改

DropDown可以修改
DropDownList不能修改

2. combox导入数据及级联小例子

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("济南", "趵突泉,大明湖,英雄山");
            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复选框

1. CheckBox可以设置三种状态

就像下面的例子. 想达到这种效果,我们只需要将需要三态的复选框的ThreeState属性设为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访问被选中的项的索引.
  • 如果是多选, 可以用listBox1.SelectedItems获取被选择对象集合, 用listBox1.SelectedIndex获取被选中对象们的索引集合. (要遍历)
  • 我们可以使用listBox1.DataSource来指定列表框的数据源
            List<int> list1 = new List<int>();
            for (int i = 0; i < 10; i++)
            {
                list1.Add(i);
            }
            listBox1.DataSource = list1;
  • 确定了DataSource,我们可以使用listBox1.DisplayMember来指定显示DataSource的哪个属性作为listBox1.SelectedValue展示
  • 同时, 我们可以使用``
    比如:
    我们的DataSource是很多鱼, 这些鱼有自己的Name和No, 我们想再列表中展示它们的Name

鱼的类定义如下:

    class Fish
    {
        public Fish()
        {

        }
        public string Name { get; set; }
        public int No { get; set; }       
    }

我们做这么一个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里的数据不是双向绑定的, 所以要更新数据源的内容时, ListBox的内容并不会跟着刷新. 要自己刷新的

例: 点击刷新列表

        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设计界面底下

选择好文件后会触发: FileOk事件

可以用OpenFileDialog1.FileName或者OpenFileDialog1.FileNames读取文件路径

同时, 我们可以用以下格式为其添加格式筛选器

图片文件|*.jpg;*.png|Excle文件|*.xls|所有文件|*.*

五. 时间日期选择器 dateTimePicker

1. 我们可以调整控件的format属性来调整显示格式:

  • long : 2020年 8月 3日
  • short: 2020-08-03
  • time: 14:41:16
    -custom : 自定义. 选定此项后 在属性customformat中定义格式.

2. 我们可以通过dateTimePicker.Value来获取选择

返回的是一个DateTime类型的数据

DateTime类型的数据有很多方法获取此时间的信息. 请自行尝试

3. 我们也可以通过dateTimePicker.Text来获取选择

返回的是一个string类型的数据, 而且受格式设置影响

六. 进度条 ProcessBar

关键属性:

  • MaxNum : 最大值
  • MinNum : 最小值
  • Step : 步进幅度 调用ProgressBar.PerformStep();时的步进
  • value : 除了调用ProgressBar.PerformStep();,我们也可以直接控制value的值,如
ProgressBar1.Value= ProgressBar1.Value+ ProgressBar1.Step;
  • 我们分步骤完成某事时也可以用这种进度条

例子:

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();
        }
    }
}

七. 数字输入框 numericUpDown

关键属性:

  • Maximum : 最大值
  • Minimum : 最小值
  • DecimalPlaces: 小数点后位数
  • Increment: 增长步进
  • value : 当前的值
  • Hexadecimal : 是否用16进制
  • ThousandsSeparator : 是否有千位分割逗号

八. 气泡提示 ToolTip

tooltip控件并不会放在窗体上,而是在窗体下的不可视控件区域里
重要属性:

  • AutoPopDelay : 气泡弹出后的持续时间
  • InitialDelay : 触发前延时时间
  • AutomaticDelay : 鼠标悬停时间
  • IsBalloon: 是否是气泡风格
  • ToolTipIcon: 提示图标. 可以是提示,警告 错误
  • ToolTipTitle : 提示的标题

设置完成后, 我们点开其他控件, 在属性栏里就能找到对应的tooltip, 并可以设置具体提示内容

如果用代码添加:

toolTip1.SetToolTip(textBox3,"textbox3用代码绑定了tooltip1,这是它的提示内容");

tooltip.show()

九. 托盘 notifyIcon

  • 一般的窗体最小化时,会在任务栏上显示, 如果想最小化到托盘, 我们可以先把窗体的ShowInTaskBar属性false了
  • notifyIcon必须设置自己的Icon图标才会在托盘中显示
  • 需要添加双击事件来还原窗口,最常见的是绑定它的鼠标双击事件
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.WindowState = FormWindowState.Normal;
        }

托盘图标上加上下文菜单可以实现更多内容, 详见下一节

十. 上下文菜单 contextMenuStrip

在菜单项上右键还有更多选项

和tooltip一样, 这个控件要绑定在别的控件身上

比如,绑定在托盘上

十一. 节点树控件 TreeView

关键属性:

  • node : 集合 在里面添加一级\二级\三级菜单 Nodes作为所有子项的集合
  • checkboxs : 节点前是否有checkbox
  • itemHeight : 条目高度

例: 代码管理节点树

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 = "新的根节点:" + 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();![Video_20200805162148.gif](https://upload-images.jianshu.io/upload_images/16670204-5619641eae3a1d77.gif?imageMogr2/auto-orient/strip)

            tn1.Name = "newNode" + num.ToString();
            tn1.Text = "新的子根节点";
            treeView1.SelectedNode.Nodes.Add(tn1);
        }
    }
}

十二. 列表视图 ListView

其实每个控件上都有一个快捷扩展箭头用来进行一些主要的设置

重要属性:

  • View : 视图的形式, 一般选detail
  • colums : 列的集合

可以在属性栏选择此属性也可以用快捷方式选择:编辑列

添加完成后:

  • items : 集合 项的集合(每一行被称为一个项). 第一列被自动认为是主键, 其他列的内容作为数据(子项)添加入集合subitems中, 如果设置了groups, 还可以对其进行分组管理
  • groups : 对items进行分组管理, 可以用ShowGroups属性管理groups的显示

  • CheckedItems : 是前面打勾的项 //和SelectedItems不一样

  • SelectedItems: 是被选择的 //和CheckedItems 不一样

例: 学生管理系统

我们创立了一个简单的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)
        {
            //创建一个学生,并初始化
            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;
            //将学生添加到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)
        {
            //创建一个项目, 将传入的学生的信息传递给他
            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显示图片

首先有三种显示图片的模式:

其次 数据源要使用一个 ImageList 控件生成

然后绑定这个imageList

最后每一类都可以指定 imageIndex 来决定显示哪一张图片

十三. 面板 panel

panel相当于div, 是一个容器

十四. 分隔容器 splitContainer

它的特点是可以将布局分为两个panel, 且可以调整大小

这个控件不容易被选定, 可以通过这种方法选定

借用分隔容器 我们可以轻松的实现基本的分隔式布局

重要属性:

  • Orientation : 是水平分隔还是竖直分隔
  • Panel1Collapsed : 折叠splitContainer的Panel1吗?
  • Panel2Collapsed : 折叠splitContainer的Panel2吗?

利用这些属性,可以方便的做成边界可调的效果

十五. TabControl 标签控制器

关键属性:

  • TabPages : 集合. Tab页面的集合
  • Alignment : 标签显示的位置
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353