第七章:TreeView控件

本章目标

  1. 使用TreeView制作静态菜单
  2. 使用TreeView动态加载菜单功能

本章内容

TreeView控件(树形菜单)

  1. 常见的树形菜单

    1716532276789

  2. TreeView树形菜单的主要属性

    属性 说明
    ImageIndex 节点默认图片索引
    ImageList 存放节点图像的ImageList控件
    Nodes 所有节点(节点的集合)
    PathSeparator 路径字符串分隔符
    ShowLines 是否显示连接线

    1716532333652

  3. 编辑树的节点Nodes

    1716533114515

TreeView控件(动态菜单)

  1. TreeNode节点对象

    1. 创建TreeNode节点对象

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      //创建根节点
      TreeNode treeNode = new TreeNode();
      treeNode.Text = "全部";//节点显示文本
      treeNode.SelectedImageIndex = 0;//选中节点显示的图片索引
      treeNode.ImageIndex = 1;//默认图片显示索引

      //创建对象,指定默认图片索引和选中节点后图片索引
      TreeNode treeNode2=new TreeNode("全部",0,1);

      tvGrade.Nodes.Add(treeNode);//将节点添加到树形菜单中
    2. 添加子节点或子节点集合

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      //创建根节点
      TreeNode treeNode = new TreeNode();
      treeNode.Text = "全部";
      treeNode.SelectedImageIndex = 0;
      treeNode.ImageIndex = 0;

      tvGrade.Nodes.Add(treeNode);

      //创建对象,指定默认图片索引和选中节点后图片索引
      //TreeNode treeNode2=new TreeNode("全部",0,1);

      //创建子节点
      TreeNode childNode1 = new TreeNode("AI-01");
      treeNode.Nodes.Add(childNode1);//添加子节点

      //创建节点集合
      TreeNode[] childNodes =
      {
      new TreeNode("AI-01"),new TreeNode("AI-02"),new TreeNode("AI-03")
      };
      treeNode.Nodes.AddRange(childNodes);//添加子节点集合

      tvGrade.ExpandAll();//展开节点方法
    3. 综合案例,实现动态加载树形菜单,效果如下:

      1716535843303

      1. 实现添加根节点:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        private void button1_Click(object sender, EventArgs e)
        {
        TreeNode treeNode = new TreeNode(txtContext.Text);

        tvGrade.Nodes.Add(treeNode);

        //或直接添加文本
        tvGrade.Nodes.Add(txtContext.Text.Trim());
        }
      2. 实现添加指定节点的子节点

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        private void button2_Click(object sender, EventArgs e)
        {
        if(tvGrade.SelectedNode == null)
        {
        MessageBox.Show("请选择节点!");
        return;
        }

        //创建节点
        TreeNode treeNode = new TreeNode(txtContext.Text);
        tvGrade.SelectedNode.Nodes.Add(treeNode);//给选中节点添加子节点

        }
      3. 移除指定节点

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        private void button3_Click(object sender, EventArgs e)
        {
        if (tvGrade.SelectedNode == null)
        {
        MessageBox.Show("请选择节点!");
        return;
        }

        tvGrade.SelectedNode.Remove();//移除选中节点
        }
      4. 展开所有节点

        1
        2
        3
        4
        private void button4_Click(object sender, EventArgs e)
        {
        tvGrade.ExpandAll();
        }
      5. 获取节点深度

        1
        2
        3
        4
        5
        private void button5_Click(object sender, EventArgs e)
        {
        int level = tvGrade.SelectedNode.Level;
        MessageBox.Show("你选择的节点深度为:" + level);
        }

演示案例:树形信息展示

  1. 案例说明:将年级和性别做成树状菜单,初始显示所有学生信息,年级是从数据库查出动态展示在树形菜单,效果如下:

    1716538073141

  2. 代码演示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    string sqlConnstring = "server=.;database=MySchool;uid=sa;pwd=sa;";
    DataSet ds=new DataSet();
    SqlDataAdapter sda = null;
    public FrmStudentByTree()
    {
    InitializeComponent();
    }

    private void FrmStudentByTree_Load(object sender, EventArgs e)
    {
    LoadGradeNode();
    }
    /// <summary>
    /// 加载Node节点
    /// </summary>
    public void LoadGradeNode()
    {
    //添加根节点
    TreeNode treeNode = new TreeNode("全部");
    tvGrade.Nodes.Add(treeNode);

    //查询年级
    string sql = "select GradeId,GradeName from Grade";
    sda=new SqlDataAdapter(sql,sqlConnstring);
    sda.Fill(ds, "Grade");

    foreach (DataRow dataRow in ds.Tables["Grade"].Rows)
    {
    TreeNode tn = new TreeNode(dataRow["GradeName"].ToString());
    tn.Tag = dataRow["GradeId"];//保存GradeId,方便查询

    TreeNode[] trSex =
    {
    new TreeNode("男"),new TreeNode("女")
    };
    tn.Nodes.AddRange(trSex);//添加性别节点

    treeNode.Nodes.Add(tn);//添加到根节点
    }
    }

    效果图如下:

    1716540771379

  3. 数据筛选操作代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    private void tvGrade_AfterSelect(object sender, TreeViewEventArgs e)
    {
    //清空操作
    if (ds.Tables["Student"] != null)
    {
    ds.Tables["Student"].Clear();
    }
    string sql = "select studentNo,studentName,sex,gradeName,phone from Student s join Grade g on s.gradeId=g.gradeId where 1=1 ";
    if (e.Node.Level == 1)
    {
    sql += " and s.gradeId=" + e.Node.Tag;//获取gradeId
    }
    else if (e.Node.Level==2)
    {
    sql += " and s.gradeId=" + e.Node.Parent.Tag+" and Sex='"+e.Node.Text+"'";
    }

    sda=new SqlDataAdapter(sql,sqlConnstring);
    sda.Fill(ds, "Student");

    dgvData.DataSource = ds.Tables["Student"];

    }

DataView控件(数据筛选)

  1. 问题,上面案例代码存在的问题有那些?

    1. 组合查询条件
    1
    2
    3
    4
    5
    6
    7
    8
    if (e.Node.Level == 1)
    {
    sql += " and s.gradeId=" + e.Node.Tag;//获取gradeId
    }
    else if (e.Node.Level==2)
    {
    sql += " and s.gradeId=" + e.Node.Parent.Tag+" and Sex='"+e.Node.Text+"'";
    }
    1. 重新查询数据
    2. 重新填充数据集
    1
    2
    sda=new SqlDataAdapter(sql,sqlConnstring);
    sda.Fill(ds, "Student");
  2. 更好的做法:直接在已有数据中筛选,不必重新检索数据,使用数据视图DataView实现,具体步骤如下:

    1. 创建数据视图对象

      语法:

      1
      DataView 对象名 = new DataView(数据表);
    2. 实现数据筛选

      1. 使用 RowFilter 属性筛选的条件,类似查询语句中 WHERE 后面部分

      2. 示例如下:

        1
        2
        3
        DataView dv = new DataView(ds.Tables["Student"]);
        dv.RowFilter = " StudentName like '李%' ";
        dgvList.DataSource = dv; // 将数据视图作为数据源
    3. 数据排序

      使用 Sort 属性

      排序的条件,类似查询语句中 ORDER BY 后面部分

      示例代码如下 :

      1
      2
      3
      DataView dv = new DataView(ds.Tables["Student"]);
      dv.Sort = "StudentName desc";
      dgvList.DataSource = dv; // 将数据视图作为数据源
    4. 注意事项:

      1. 使用DataView dv = new DataView(ds.Tables["Student"]);频繁创建DataView对象会浪费内存空间,可以使用别一种方式实现,代码如下:

        1
        DataView dv = ds.Tables["Student"].DefaultView;

        为减少实例化DataView对象的步骤,也可使用DataTable的DefaultView属性得到DataView

本章总结

1716605312749

ADO.NET总结:

1716605359298

本章作业

  1. 将年级和性别做成树状菜单,初始显示所有学生信息:

    1716605436987

  2. 通过数据库查询年级,动态加载上图树形菜单效果

  3. 实现学生信息的筛选和排序,需求说明如下:

    1. 默认显示所有 学生的信息

    2. 选择树型菜单的节点,显示相应的数据

    3. 按照学号升序排列

      1716605535915

  4. 实现科目信息的筛选和排序,需求如下:

    1. 默认显示所有科目的信息

    2. 选择树型菜单的节点,显示相应的数据

    3. 按照科目名称升序排列

      1716605583504

  5. 删除学生信息,需求说明:

    1. 选中某个学生行

    2. 右键菜单获得该学生的学号

    3. 从数据库中删除该学生的信息

      1716605660175

  6. 整合贯穿案例MySchool,通过演示项目,实现全部功能:

    1. 运行整个MySchool
    2. 测试每个功能,并修改完善
    3. 实现扩展功能