[Windows Forms 응용 with C#] 2.5 TreeView 사용 실습

이번에는 계층적으로 자료를 표시할 수 있는 TreeView 사용법을 알아봅시다.

이번 실습에서는 트리 뷰의 부모의 첫번째 자식, 마지막 자식으로 노드를 추가하는 방법과 선택한 노드의 이전, 이후로 추가하는 방법, 노드를 삭제하는 방법 및 트리의 항목을 펼치거나 축소하는 방법 등을 알아볼게요.

[그림 2.11] 실행화면 및 컨트롤 배치

 다음은 Form1의 자식 컨트롤 Name 및 형식입니다.

NoName컨트롤 형식설명
1tv_demoTreeView데모 트리 뷰
2tbox_parentTextBox부모 노드 텍스트 박스
3tbox_childTextBox자식 노드 텍스트 박스
4btn_add_firstButton부모의 첫번째 자식으로 추가 버튼
5btn_add_lastButton부모의 마지막 자식으로 추가 버튼
6lbox_brothersListBox선택한 노드의 자식 노드 목록
7btn_add_prevButton선택한 자식의 이전 노드로 추가 버튼
8btn_add_nextButton선택한 자식의 다음 노드로 추가 버튼
9btn_expandButton트리 뷰 펼치기
10btn_collapseButton트리 뷰 축소하기
11btn_removeButton선택 노드 제거하기

트리 뷰의 AfterSelect 이벤트 핸들러를 등록합니다.

private void tv_demo_AfterSelect(object sender, TreeViewEventArgs e)
{

선택 항목의 자식들을 표시할 lbox_brothers의 아이템 항목을 지워줍니다.

    lbox_brothers.Items.Clear();

트리 뷰에는 선택한 노드를 SelectedNode 속성으로 가져오기 할 수 있습니다.

    TreeNode node = tv_demo.SelectedNode;
    if (node == null)
    {

선택한 노드가 없을 때 tbox_parent의 Text 속성을 비워줍니다.

        tbox_parent.Text = string.Empty;

그리고 tbox_paretn의 Tag에는 트리 뷰의 TopNode로 설정합시다.

        tbox_parent.Tag = tv_demo.TopNode;

선택한 노드가 없으므로 삭제 버튼은 비활성화 합니다.

        btn_remove.Enabled = false;
        return;
    }

선택한 노드가 있다면 tbox_parent의 Text 속성과 Tag 속성을 선택한 노드로 설정합니다.

    tbox_parent.Text = node.Text;
    tbox_parent.Tag = node;

선택한 노드가 있기 때문에 삭제 버튼을 활성화합니다.

    btn_remove.Enabled = true;

그리고 선택한 노드의 Nodes 컬렉션에 있는 자식 노드들을 lbox_brothers 항목에 추가합니다. 여기서 lbox_brothers라고 명명한 이유는 추가할 노드의 형제들이라는 의미입니다. 물론 선택한 노드의 자식들이죠.

    foreach (TreeNode snode in node.Nodes)
    {
        lbox_brothers.Items.Add(snode);
    }
}

첫번째 자식으로 추가 버튼의 클릭 이벤트 핸들러를 등록합니다.

private void btn_add_first_Click(object sender, EventArgs e)
{

tbox_parent.Tag에 설정해 두었던 TreeNode를 참조합니다.

    TreeNode node = tbox_parent.Tag as TreeNode;

만약 node가 null이면 트리 뷰의 Nodes 컬렉션에 추가합니다. 원하는 위치에 추가할 때는 Insert 메서드를 사용합니다.

    if (node == null)
    {
        tv_demo.Nodes.Insert(0, tbox_child.Text);
    }

node가 null이 아니면 node의 Nodes 컬렉션에 추가하고 노드를 펼칩니다.

    else
    {
        node.Nodes.Insert(0,tbox_child.Text);
        node.Expand();
    }

tbox_childe의 Text 속성을 빈 문자열로 설정합니다.

    tbox_child.Text = string.Empty;
}

마지막 자식으로 추가 버튼의 클릭 이벤트 핸들러를 등록합시다.

private void btn_add_last_Click(object sender, EventArgs e)
{

tbox_parent의 Tag 속성에 설정한 TreeNode를 참조합니다.

    TreeNode node = tbox_parent.Tag as TreeNode;

마지막 자식으로 추가할 때는 Add 메서드를 호출합니다.

    if (node == null)
    {
        tv_demo.Nodes.Add(tbox_child.Text);
    }
    else
    {
        node.Nodes.Add(tbox_child.Text);
        node.Expand();
    }
    tbox_child.Text = string.Empty;
}

lbox_brothers 리스트 박스의 선택 항목 변경 이벤트 핸들러를 등록합시다.

private void lbox_brothers_SelectedIndexChanged(object sender, EventArgs e)
{

선택 항목이 있는지 여부에 따라 이전 자식으로 추가 버튼과 다음 자식으로 추가 버튼의 활성화 및 비활성화 여부를 설정합니다.

    bool selected = (lbox_brothers.SelectedIndex != -1);
    btn_add_prev.Enabled = selected;
    btn_add_next.Enabled = selected;
}

이전 자식으로 추가 버튼의 클릭 이벤트 핸들러를 등록합시다.

private void btn_add_prev_Click(object sender, EventArgs e)
{

lbox_brothers의 선택 항목을 TreeNode 형식으로 참조합니다.

    TreeNode tn = lbox_brothers.SelectedItem as TreeNode;

트리 노드에는 Parent 속성으로 부모 노드를 가져오기할 수 있습니다.

    TreeNode pn = tn.Parent;

부노 모드의 Nodes 컬렉션에 선택한 형재 노드의 Index에 추가합니다.

    pn.Nodes.Insert(tn.Index, tbox_child.Text);
    tbox_child.Text = string.Empty;
}

다음 자식으로 추가 버튼의 클릭 이벤트 핸들러를 등록합시다.

private void btn_add_next_Click(object sender, EventArgs e)
{

다음 자식으로 추가하기 위해 선택한 형재 노드의 Index+1 위치에 추가합니다.

    TreeNode tn = lbox_brothers.SelectedItem as TreeNode;
    TreeNode pn = tn.Parent;
    pn.Nodes.Insert(tn.Index+1, tbox_child.Text);
    tbox_child.Text = string.Empty;
}

펼기기와 축소하기 버튼의 클릭 이벤트 핸들러를 등록합시다. 펼치기와 축소하기를 위해 트리 뷰에서는 ExpandAll 메서드와 CollapseAll 메서드를 제공합니다.

private void btn_expand_Click(object sender, EventArgs e)
{
    tv_demo.ExpandAll();
}
private void btn_collapse_Click(object sender, EventArgs e)
{
    tv_demo.CollapseAll();
}

삭제 버튼의 클릭 이벤트 핸들러를 등록합시다.

private void btn_remove_Click(object sender, EventArgs e)
{

노드를 제거할 때는 노드 자신의 Remove 메서드를 사용합니다. 여기서는 선택한 노드를 제거할 것이므로 SelectedNode 속성에 있는 노드 개체를 Remove 합니다.

    tv_demo.SelectedNode.Remove();

선택한 노드를 제거했으니 tbox_parent의 Tag 속성과 Text 속성을 지워줍니다.

    tbox_parent.Tag = null;
    tbox_parent.Text = string.Empty;
}

▷Form1.cs

using System;
using System.Windows.Forms;

namespace Ex_TreeView
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void tv_demo_AfterSelect(object sender, TreeViewEventArgs e)
        {
            lbox_brothers.Items.Clear();
            TreeNode node = tv_demo.SelectedNode; 

            if (node == null)
            {
                tbox_parent.Text = string.Empty;
                tbox_parent.Tag = tv_demo.TopNode;
                btn_remove.Enabled = false;
                return;
            }
            tbox_parent.Text = node.Text;
            tbox_parent.Tag = node;
            btn_remove.Enabled = true;
            foreach (TreeNode snode in node.Nodes)
            {
                lbox_brothers.Items.Add(snode);
            }
        }
        private void btn_add_first_Click(object sender, EventArgs e)
        {
            TreeNode node = tbox_parent.Tag as TreeNode;
            if (node == null)
            {
                tv_demo.Nodes.Insert(0, tbox_child.Text);
            }
            else
            {
                node.Nodes.Insert(0,tbox_child.Text);
                node.Expand();
            }
            tbox_child.Text = string.Empty;
        }


        private void btn_add_last_Click(object sender, EventArgs e)
        {
            TreeNode node = tbox_parent.Tag as TreeNode;
            if (node == null)
            {
                tv_demo.Nodes.Add(tbox_child.Text);
            }
            else
            {
                node.Nodes.Add(tbox_child.Text);
                node.Expand();
            }

            tbox_child.Text = string.Empty;
        }

        void lbox_brothers_SelectedIndexChanged(object sender, EventArgs e)
        {
            bool selected = (lbox_brothers.SelectedIndex != -1);
            btn_add_prev.Enabled = selected;
            btn_add_next.Enabled = selected;
        }

        private void btn_add_prev_Click(object sender, EventArgs e)
        {
            TreeNode tn = lbox_brothers.SelectedItem as TreeNode;
            TreeNode pn = tn.Parent;
            pn.Nodes.Insert(tn.Index, tbox_child.Text);
            tbox_child.Text = string.Empty;
        }

        private void btn_add_next_Click(object sender, EventArgs e)
        {
            TreeNode tn = lbox_brothers.SelectedItem as TreeNode;
            TreeNode pn = tn.Parent;
            pn.Nodes.Insert(tn.Index+1, tbox_child.Text);
            tbox_child.Text = string.Empty;
        }

        private void btn_expand_Click(object sender, EventArgs e)
        {
            tv_demo.ExpandAll();
        }

        private void btn_collapse_Click(object sender, EventArgs e)
        {
            tv_demo.CollapseAll();
        }

        private void btn_remove_Click(object sender, EventArgs e)
        {
            tv_demo.SelectedNode.Remove();
            tbox_parent.Tag = null;
            tbox_parent.Text = string.Empty;
        }
    }
}