블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2797)
Unity3D (853)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (61)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

프로그래밍, C#, Web, TreeViewNode 검색, 카테고리 구현

갓 C#을 접하게된 어설픈 프로그래머 입니다. C#을 하면서 익힌 스킬을 공유하고자 합니다. 만약, 고쳐야할 부분이 있으면 알려주시면 감사하겠습니다. 

이번에 다룰 부분은 TreeView 입니다.

TreeView(트리뷰)는 가장 쉽게 얘기해서 Tistory의 카테고리를 표현하는 것처럼 그룹들을 보기 좋게 트리형태로 표현해 주는 컴포넌트입니다. 즉, 부모가 있고 부모 밑에는 자식이 있고 다시 손자가 있는 일종의 계층구조를 표시해 주는 것입니다.

Tistory의 카테고리를 표현하는 것도 일종의 TreeView 형태입니다. 당연히 C#에서 TreeView를 지원합니다. 

그럼 사용해봐야겠네요. (WebControls.TreeView 기준입니다.)

TrewView를 웹 폼에 추가를 합니다.(여기서는 이름을 trvGroup이라 명명하였습니다.)
//최상위 그룹을 생성합니다.  4Cs라고 가정합니다.
TreeNode trvNode = new TreeNode();
trvNode.Text ="4Cs";
trvNode.Value = "0";

// 4Cs라는 트리의 하부에 표현할 IT,종이접기,사는이야기 를 구성합니다.

//IT 항목 추가
TreeNode trvNodeIT = new TreeNode(); // TreeNode 인스턴스를 생성합니다. 이름은 trvNodeIT라고 하였습니다.
trvNodeIT.Text = "IT";                           // 트리뷰 상에 표시할 이름
trvNodeIT.Value = "01";                         // 구분할 값(프로그램을 내부에 사용할 값)
trvNode.ChildNodes.Add(trvNodeIT);     // 4Cs하부의 자식노드에 추가합니다.

// 종이접기 항목 추가
TreeNode trvNodeOrigami = new TreeNode();
trvNodeOrigami.Text = "종이접기";
trvNodeOrigami.Value = "02";
trvNode.ChildNodes.Add(trvNodeOrigami);

//사는이야기 항목 추가
TreeNode trvNodeLife = new TreeNode();
trvNodeLife.Text = "사는이야기";
trvNodeLife.Value = "03";
trvNode.ChildNodes.Add(trvNodeLife);

// 최종적으로 TreeView에 추가를 합니다.
trvGroup.Nodes.Add(trvNode);

위와 같이 한 후 실행을 하면 다음과 같이 표시됩니다. 

그런데 위와 같은 경우는 구조를 알고 있는 관계로 부모를 지정하고 추가를 하면 되지만 표현해야할 구조가 Database 등에서 읽어서 자동으로 표시해야할 경우는 사용할 수가 없습니다.

예로 Tistory의 개발자가 프로그램을 위와 같이 했다면, 프로그래머는 Tistory를 사용하는 블로그의 모든 구조를 확인하고 일일이 표시해야하는(?) 난감한 문제가 발생합니다.

물론, Microsoft사도 C#을 만들면서 자동으로 추가할 수 있는 무언가를 만들어 놓았겠죠. 찾아보시면 FindNode(string valuePath)라는 함수가 있습니다. 그런데 자세히 보시면 FindNode의 인자값이 valuePath라고 되어있습니다. valuePath는 TreeView에서 특정 Node가 위치한 일종의 경로를 나타냅니다. 

Default 구분자로 "/"를 사용합니다. 위의 예에서 종이접기라는 노드의 valuePath는 "부모의 value/종이접기의 value"로 구성되어 "0/02"가 됩니다. 즉, 종이접기 노드 하부에 자식 노드를 추가하기 위해서는 종이접기의 Value 뿐만 아니라 종이접기 부모의 value까지 알아야 한다는 결론입니다. 

낭패죠, FindNode를 사용하려면 미리 데이터 구조를 FindNode에 맞게 구성이 되어져야합니다.

결론은 함수를 만들어야합니다. 그것도 재귀호출함수를 만들어야 제대로 구성할 수가 있습니다. (물론, 데이터량이 많을 경우 속도에 문제가 발생할 수 있습니다.)

        // 최초 SearchNode를 호출합니다.
        // 오버로드 함수는 이름이 같으나 파라미터 등으로 구분해서 사용합니다.
        public void Disply_Tree(){
            string strParentKey;

            // 레코드에서 부모 Key를 가져옴
            strParentKey = rdr.GetInt32(0).ToString();   
            //Nodes 콜렉션과 부모 Key를 가지고 함수 호출
            TreeNode trParent = SearchNode(objTreeView.Nodes, strParantKey);  

            TreeNode trChild = new TreeNode(); 
             // 레코드에서 자신의 Key를 가져옴 (예, "02")
             trChild.Value = rdr.GetInt32(1).ToString();

             // 레코드에서 자신의 Node 이름을 가져옴 (예, "종이접기")
             trChild.Text = rdr.GetInt32(2).ToString();

             // 부모노드에 추가
             trParent.ChildNodes.Add(trChild);
        }

 //Tree 검색 - 재귀 호출 함수 (TreeView.Nodes,Key)
        public TreeNode SearchNode(TreeNodeCollection objNodes, string strKey)
        {
            // Nodes의 node를 가지고 찾을 때까지 반복합니다.
            foreach ( TreeNodnode in objNodes )
            {
                // 해당 Node를 찾을 경우 Node를 리턴합니다.
                if (node.Value == strKey) return node;

                // 없을 경우 하위 Nodes를 가지고 다시 SearchNode를 호출합니다.
                TreeNode findNode = SearchNode(node.ChildNodes,strKey);

                // 하위노드 검색 결과를 비교하여 Null이 아닐경우(찾은 경우) node를 리턴합니다.
                if ( findNode != null )
                        return findNode;
            }
            // 검색 결과 조건에 맞는 Node가 없을 경우 Null을 리턴합니다.
            return null;
        }

위와 같이 재귀함수를 통해서 아래와 같이 자동으로 트리를 구성할 수 있습니다.


프로그래밍에 도움이 되시길 바랍니다.

(알려드리지만 위의 방법은 본인의 주관적인 방법이며 만약, 다른 효과적인 방법이 있을 경우 공유해 주시면 감사하겠습니다.)

 
출처 : 
http://all4cs.tistory.com/31 
반응형
Posted by blueasa
, |

- 테이블에 자신의 키와 자기 부모의 키를 가지고 있는경우 재귀함수를 이용해 트리뷰를 구성

 

 

RwNm : 노드이름

RwCd : 노드키

PrntRw : 자신의 부모키

 

#region 트리뷰구성
private TreeNode CreateNode(string RwNm,string RwCd)
{
    //자신의 하위노드가 없을때까지 찾는다   

    TreeNode node = new TreeNode();
    node.Name = RwCd;
    node.Text = RwNm;

    foreach (DataRow r in RwCdTable.Rows)
    {
          if (RwCd == r["PrntRw"].ToString()) //자신의 키를 부모키로 갖고있는 노드검색
          {
              //System.Diagnostics.Debug.WriteLine(RwCd+ "->"+r["RwCd"].ToString());

              

              //재귀호출
              node.Nodes.Add(CreateNode(r["RwNm"].ToString(),

                                                        r["RwCd"].ToString()));                      
           }
     }
     return node; //자신의 하위노드를 다찾은 노드를 반환
}
#endregion

 

//함수사용

trvRw.Nodes.Add(CreateNode(strRwLevlNm,"00000000"));

 

자료구조시간에 배운 재귀함수를 회사에서 써먹게될줄이야...


출처 : http://blog.naver.com/tjr0807?Redirect=Log&logNo=150005240319

반응형
Posted by blueasa
, |