利用TreeView控件,建立一颗树。程序带有保存文本和二进制的功能。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
using System.Runtime.Serialization.Formatters.Binary;
// 知识点:
// TreeView控件的应用:添加、修改、删除节点
// 得到当前节点、父节点的值
// 响应节点选择事件
// 节点存储数据
namespace Ch0602_学生成绩_二进制文件_
{
public partial class FrmGrade : Form
{
public FrmGrade()
{
InitializeComponent();
}
private void btnAddSC_Click(object sender, EventArgs e)
{
if (cboType.SelectedIndex == 0)
{
// 添加学校节点,并指定该节点为当前节点
if (txtNameSC.Text.Length > 0)
{
TreeNode node = tvSC.Nodes.Add(txtNameSC.Text);
tvSC.SelectedNode = node;
}
else
MessageBox.Show("请指定学校的名称");
}
else
{
if (tvSC.SelectedNode == null || tvSC.SelectedNode.Level >= 1)
MessageBox.Show("先选择学校,然后再创建班级节点");
else
{
// 添加班级节点,并展开学校节点
if (txtNameSC.Text.Length > 0)
{
tvSC.SelectedNode.Nodes.Add(txtNameSC.Text);
tvSC.SelectedNode.Expand();
}
else
MessageBox.Show("请指定班级的名称");
}
}
}
private void btnAddStud_Click(object sender, EventArgs e)
{
if (tvSC.SelectedNode == null || tvSC.SelectedNode.Level != 1)
{
MessageBox.Show("请指定班级");
return;
}
string sname = tvSC.SelectedNode.Parent.Text;
string cname = tvSC.SelectedNode.Text;
Student stud = new Student(sname, cname);
stud.No = txtNo.Text;
stud.Name = txtName.Text;
stud.Sex = cboSex.Text;
stud.Birth = DateTime.Parse(dtpBirth.Text);
stud.Grade = int.Parse(txtGrade.Text);
stud.Addr = txtAddr.Text;
TreeNode node = tvSC.SelectedNode.Nodes.Add(stud.No);
// 给添加的节点绑定数据
node.Tag = stud;
// 展开班级节点
tvSC.SelectedNode.Expand();
}
private void tvSC_AfterSelect(object sender, TreeViewEventArgs e)
{
// 显示当前节点内容
if (tvSC.SelectedNode != null && tvSC.SelectedNode.Level == 2 && tvSC.SelectedNode.Tag != null)
{
Student stud = (Student)tvSC.SelectedNode.Tag;
lboStudent.Items.Add(stud.ToString());
txtNo.Text = stud.No;
txtName.Text = stud.Name;
cboSex.Text = stud.Sex;
dtpBirth.Text = stud.Birth.ToString();
txtGrade.Text = stud.Grade.ToString();
txtAddr.Text = stud.Addr;
}
}
private void tvSC_AfterSelect(object sender, TreeViewEventArgs e)
{
// 显示当前节点内容
if (tvSC.SelectedNode != null && tvSC.SelectedNode.Level == 2 && tvSC.SelectedNode.Tag != null)
{
Student stud = (Student)tvSC.SelectedNode.Tag;
lboStudent.Items.Add(stud.ToString());
txtNo.Text = stud.No;
txtName.Text = stud.Name;
cboSex.Text = stud.Sex;
dtpBirth.Text = stud.Birth.ToString();
txtGrade.Text = stud.Grade.ToString();
txtAddr.Text = stud.Addr;
}
}
private void cboType_SelectedIndexChanged(object sender, EventArgs e)
{
txtNameSC.Clear();
}
private void btnModStud_Click(object sender, EventArgs e)
{
if (tvSC.SelectedNode == null || tvSC.SelectedNode.Level != 2)
{
MessageBox.Show("请指定学生");
return;
}
string sname = tvSC.SelectedNode.Parent.Parent.Text;
string cname = tvSC.SelectedNode.Parent.Text;
Student stud = new Student(sname, cname);
stud.No = txtNo.Text;
stud.Name = txtName.Text;
stud.Sex = cboSex.Text;
stud.Birth = DateTime.Parse(dtpBirth.Text);
stud.Grade = int.Parse(txtGrade.Text);
stud.Addr = txtAddr.Text;
// 修改节点信息
tvSC.SelectedNode.Text = stud.No;
// 修改节点的绑定数据
tvSC.SelectedNode.Tag = stud;
}
private void btnDelStud_Click(object sender, EventArgs e)
{
// 删除节点数据
tvSC.SelectedNode.Remove();
}
// 读文本文件,生成树结构
private void miFileRead_Click(object sender, EventArgs e)
{
// 显示打开文件对话框
OpenFileDialog dlgOpen = new OpenFileDialog();
if (dlgOpen.ShowDialog() != DialogResult.OK)
return;
// 以指定文件和编码格式打开文件,准备读
StreamReader sr = new StreamReader(dlgOpen.FileName, Encoding.Default);
tvSC.Nodes.Clear();
string pattern = @"\s*,\s*|\s+"; // “\s”表示空格,“\s*”表示0个或多个空格,“\s+”表示1个或多个空格
string sname0 = "", cname0 = "";
// 读取一行文本
string line;
string[] fields;
while ((line = sr.ReadLine()) != null)
{
//fields = line.Split(' ', '\t');
fields = Regex.Split(line, pattern);
string sname = fields[0];
string cname = fields[1];
Student stud = new Student(sname, cname);
stud.No = fields[2];
stud.Name = fields[3];
stud.Sex = fields[4];
stud.Birth = Convert.ToDateTime(fields[5]);
stud.Grade = int.Parse(fields[6]);
stud.Addr = fields[7];
// 如果学校名改变了,添加学校节点
if (sname != sname0)
{
tvSC.SelectedNode = tvSC.Nodes.Add(sname);
sname0 = sname;
}
// 如果班级名改变了,添加班级节点
if (cname != cname0)
{
// 调整当前节点
if (tvSC.SelectedNode.Level == 1)
tvSC.SelectedNode = tvSC.SelectedNode.Parent;
tvSC.SelectedNode = tvSC.SelectedNode.Nodes.Add(cname);
cname0 = cname;
}
// 添加学生节点
TreeNode node = tvSC.SelectedNode.Nodes.Add(stud.No);
node.Tag = stud;
}
// 关闭文件
sr.Close();
}
// 遍历树结构,写文本文件
private void miFileWrite_Click(object sender, EventArgs e)
{
// 显示保存文件对话框
SaveFileDialog dlgSave = new SaveFileDialog();
if (dlgSave.ShowDialog() != DialogResult.OK)
return;
// 指定文件和编码格式打开指定文件准备写
StreamWriter sw = new StreamWriter(dlgSave.FileName, false, Encoding.Default);
// 遍历树结构,写文本文件
WriteTxtFile(sw, tvSC.Nodes);
// 关闭文件
sw.Close();
}
// 用递归遍历一棵树所有节点
private void WriteTxtFile(StreamWriter sw, TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
if (node.Level == 2)
{
Student stud = node.Tag as Student;
string line = string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5:yyyy-MM-dd}\t{6}\t{7}",
stud.Sname, stud.Cname, stud.No, stud.Name, stud.Sex, stud.Birth, stud.Grade, stud.Addr);
sw.WriteLine(line);
}
if (node.Nodes.Count > 0)
WriteTxtFile(sw, node.Nodes);
}
}
private void miFileReadBin_Click(object sender, EventArgs e)
{
OpenFileDialog dlgOpen = new OpenFileDialog();
if (dlgOpen.ShowDialog() != DialogResult.OK)
return;
FileStream fs = new FileStream(dlgOpen.FileName, FileMode.Open, FileAccess.Read);
tvSC.Nodes.Clear();
// 建立一个读流的类br
BinaryReader br = new BinaryReader(fs);
// 初始化变量
string sname0 = "", cname0 = "";
// 文件指针指向文件头
br.BaseStream.Seek(0, SeekOrigin.Begin);
// 循环读,直到文件指针指向文件尾
while (br.BaseStream.Position < br.BaseStream.Length)
{
// 按字段读出每个学生的记录
Student stud = new Student();
stud.Sname = br.ReadString();
stud.Cname = br.ReadString();
stud.No = br.ReadString();
stud.Name = br.ReadString();
stud.Sex = br.ReadString();
stud.Birth = Convert.ToDateTime(br.ReadString());
stud.Grade = br.ReadInt32();
stud.Addr = br.ReadString();
// 添加到树形节点
// 如果学校名改变了,添加学校节点
if (stud.Sname != sname0)
{
tvSC.SelectedNode = tvSC.Nodes.Add(stud.Sname);
sname0 = stud.Sname;
}
// 如果班级名改变了,添加班级节点
if (stud.Cname != cname0)
{
// 调整当前节点
if (tvSC.SelectedNode.Level == 1)
tvSC.SelectedNode = tvSC.SelectedNode.Parent;
tvSC.SelectedNode = tvSC.SelectedNode.Nodes.Add(stud.Cname);
cname0 = stud.Cname;
}
// 添加学生节点
TreeNode node = tvSC.SelectedNode.Nodes.Add(stud.No);
node.Tag = stud;
}
br.Close();
fs.Close();
}
private void miFileWriteBin_Click(object sender, EventArgs e)
{
// 显示保存文件对话框
SaveFileDialog dlgSave = new SaveFileDialog();
if (dlgSave.ShowDialog() != DialogResult.OK)
return;
// 建立一个写文件流fs
FileStream fs = new FileStream(dlgSave.FileName, FileMode.Create, FileAccess.Write);
// 建立一个写流的类bw
BinaryWriter bw = new BinaryWriter(fs);
// 遍历树结构,写文本文件
WriteBinFile(bw, tvSC.Nodes);
// 关闭写流类和文件流
bw.Close();
fs.Close();
}
// 用递归遍历一棵树所有节点
private void WriteBinFile(BinaryWriter bw, TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
if (node.Level == 2)
{
Student stud = node.Tag as Student;
bw.Write(stud.Sname);
bw.Write(stud.Cname);
bw.Write(stud.No);
bw.Write(stud.Name);
bw.Write(stud.Sex);
bw.Write(stud.Birth.ToString("yyyy-MM-dd"));
bw.Write(stud.Grade);
bw.Write(stud.Addr);
}
if (node.Nodes.Count > 0)
WriteBinFile(bw, node.Nodes);
}
}
private void miFileReadBin2_Click(object sender, EventArgs e)
{
OpenFileDialog dlgOpen = new OpenFileDialog();
if (dlgOpen.ShowDialog() != DialogResult.OK)
return;
FileStream fs = new FileStream(dlgOpen.FileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
tvSC.Nodes.Clear();
// 初始化变量
string sname0 = "", cname0 = "";
// 文件指针指向文件头
fs.Seek(0, SeekOrigin.Begin);
// 循环读,直到文件指针指向文件尾
while (fs.Position < fs.Length)
{
// 按字段读出每个学生的记录
int length = br.ReadInt32();
byte[] buffer = new byte[length];
buffer = br.ReadBytes(length);
Student stud = (Student)BytesToObject(buffer);
// 添加到树形节点
// 如果学校名改变了,添加学校节点
if (stud.Sname != sname0)
{
tvSC.SelectedNode = tvSC.Nodes.Add(stud.Sname);
sname0 = stud.Sname;
}
// 如果班级名改变了,添加班级节点
if (stud.Cname != cname0)
{
// 调整当前节点
if (tvSC.SelectedNode.Level == 1)
tvSC.SelectedNode = tvSC.SelectedNode.Parent;
tvSC.SelectedNode = tvSC.SelectedNode.Nodes.Add(stud.Cname);
cname0 = stud.Cname;
}
// 添加学生节点
TreeNode node = tvSC.SelectedNode.Nodes.Add(stud.No);
node.Tag = stud;
}
br.Close();
fs.Close();
}
private void miFileWriteBin2_Click(object sender, EventArgs e)
{
// 显示保存文件对话框
SaveFileDialog dlgSave = new SaveFileDialog();
if (dlgSave.ShowDialog() != DialogResult.OK)
return;
// 建立一个写文件流fs
FileStream fs = new FileStream(dlgSave.FileName, FileMode.Create, FileAccess.Write);
BinaryWriter bw = new BinaryWriter(fs);
// 遍历树结构,写文本文件
WriteBinFile2(bw, tvSC.Nodes);
// 关闭写流类和文件流
bw.Close();
fs.Close();
}
private void WriteBinFile2(BinaryWriter bw, TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
if (node.Level == 2)
{
Student stud = node.Tag as Student;
byte[] buffer = ObjectToBytes(stud);
bw.Write(buffer.Length);
bw.Write(buffer);
}
if (node.Nodes.Count > 0)
WriteBinFile2(bw, node.Nodes);
}
}
// 对象序列化为字节数组
public static byte[] ObjectToBytes(Object obj)
{
MemoryStream ms = new MemoryStream();
byte[] bytes = null;
try
{
// 序列化
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
bytes = ms.ToArray();
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
finally
{
ms.Close();
}
return bytes;
}
// 字节数组反序列化为对象
public static Object BytesToObject(byte[] bytes)
{
MemoryStream ms = new MemoryStream(bytes);
Object obj = new Object();
try
{
// 反序列化
ms.Position = 0;
BinaryFormatter formatter = new BinaryFormatter();
obj = formatter.Deserialize(ms);
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
finally
{
ms.Close();
}
return obj;
}
private void miClear_Click(object sender, EventArgs e)
{
tvSC.Nodes.Clear();
}
}
}
下面是类的定义。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Ch0602_学生成绩_二进制文件_
{
[Serializable]
public class Student
{
public string Sname { get; set; }
public string Cname { get; set; }
public string No { get; set; }
public string Name { get; set; }
public string Sex { get; set; }
public DateTime Birth { get; set; }
public int Grade { get; set; }
public string Addr { get; set; }
public Student()
{
}
public Student(string sname, string cname)
{
Sname = sname;
Cname = cname;
}
public new string ToString()
{
return string.Format("{0}:{1},{2},{3:yyyy-MM-dd},{4},{5}", No, Name, Sex, Birth, Grade, Addr);
}
}
}