PROGRAMMING WORKSHOP

.Net FrameWork,VB.Net |TreeView

재귀프로시져를 사용하지 말고 TreeView채우기...

DataTable,DataView,Sort

Hierarchy 형식의 데이타는 몇단계까지 계층이 구성될지 알수 없다
이때 필요한 것이 재귀프로시져(Recursive Procedure)이다
하지만 레벨이 깊이 들어가면 재귀프로시져도 맥을 못춘다
시간이 너무 걸리고, 효율적이지 않다
좋은 방법이 없을까?
앞페이지에서 화일시스템뷰에서 사용했던 방법을 사용하면 될 것이다
그러면서..
DataTable의 성질머리를 좀더 파악하는 기회가 될 것이다
아래와 같이 하면 DataTable이 만들어지고

Sub fillDataTable()
	Try
		oTbl = New DataTable
		For iX As Integer = 1 To 7
			Dim oCol As New DataColumn("data_" & iX, IIf(iX = 7, GetType(Double), GetType(String)))
			oTbl.Columns.Add(oCol)
		Next
		For iRow As Integer = 1 To 500
			Dim oRow As DataRow = oTbl.NewRow
			For iCol As Integer = 1 To 7
''New String(Chr(Int(Rnd() * 5) + 65), iCol) 은
''VBA 함수의 String(3, "A") 즉 A라는 문자를 3개 만들라는 것과 같은 표현이다
				oRow.Item(iCol - 1) = IIf(iCol = 7, Int(Rnd() * 1000) + 1000, New String(Chr(Int(Rnd() * 5) + 65), iCol))
			Next
			oTbl.Rows.Add(oRow)
		Next

	Catch ex As Exception

	End Try
End Sub	
	

이것을 DataGridView의 DataSource로 사용하고..
그런데 DataGridView의 여러개의 열을 정렬을 하고 싶다면 어떻게 할까?

여러행을 한꺼번에 정렬하여 DataGridView에 보이게..

DataGridView의 정렬은 하나의 열밖에 못한다
여러개의 열을 차례대로 한번에 정렬하려면
DataTable의 복사본인 DataView로 정렬을 하면 된다

아래와 같이 하여 DataGridView의 DataSource속성에 사용한다

Sub setDataGridView()
	Try
''DataGridView개체를 만들어서 원하는 위치,크기와 기능을 갖춘 속성을 세팅하고
''DataTable은 항상 기본 DataView를 갖고 있고 이것을 DefaultView속성으로 얻어낸다
''DataView를 사용하는 이유는 여러열의 정렬을 할수 있는 기능을 갖고 있기 때문
		Dim oView As DataView = oTbl.DefaultView
''DataView개체의 Sort속성에 여러열을 정렬을 하려면 아래와 같이 하나의 문자열정보를 만들어 준다
''oView.Sort = "열_1 ASC,열_2 ASC,열_3 ASC,열_4 ASC,열_5 ASC, 열_6 ASC,,,,,,,"
''그래서 아래와 같이 전체열을 모두 정렬하기 위하여..
''순환하면서 정렬조건 문자열을 만든다
		Dim sSort As String = ""
		For Each oCol As DataColumn In oTbl.Columns
			sSort &= oCol.ColumnName & " ASC,"
		Next
		sSort = sSort.Substring(0, sSort.Length - 1)
		oView.Sort = sSort
''DataGridView의 DataSource에 DataView를 주면된다		
		oDGV.DataSource = oView

		Me.Controls.Add(oDGV)
	 
	Catch ex As Exception

	End Try
End Sub



재귀용법사용하지 않고 TreeView채우기..LINQ의 활용

이제 DataTable의 내용을 TreeView에 표현해 보자
재귀용법을 사용하여 전체를 죄다 한꺼번에 TreeView에 불러 들이려면..
실행속도와 효율에 무리가 있다
그러니, 첫째 상위 아이템만 폼이 로딩될때 채워넣고 TreeNode를 크릭하여
확장, 축소 할때마다 해당 TreeNode의 자식 TreeNode들을 채웠다,지웠다
하는 것이 경제적이고 바람직한 방법이다
아래와 같이 DataTable을 만들고, DataGridView에 담은후..
TreeView에 채우자

 Sub fillTreeView()
	Try
		oTV = New TreeView
		''LINQ를 사용하여 얻어오고 싶은 것을 집합체로 얻어오자...
		'' oTbl로 하면..AsEnumerable 속성을 사용하여 LINQ가 이해하는 집합체로 만들어야 한다
		'Dim oItems = From X In oTbl.AsEnumerable
		'            Select X.Item(0)
		'            Distinct

		'' DefaultView를 사용하면 DefaultView에서 만들어지는 DataView는 LINQ가 이해하는 개체
		'' 그래서 그냥사용해도 된다
		'' 첫째열의 값만 뽑아 오는데 유일한값(Distict) 뽑아온다
		
		Dim oItems = From X In oTbl.DefaultView
					Select X.Item(0)
					Distinct

		'' oItems는 첫째열의 유일한 값만 모아놓은 배열이다..
		'' 이것을 순환하면서 
		For Each sItem As String In oItems
			Dim oTopNode As New TreeNode
			oTopNode.Text = sItem
			'' 하위 TreeNode가 하나라도 있어야 +버튼이 나타난다..
			'' 그래서 빈 TreeNode를 하나만들어 달아준다
			Dim oNextNode As New TreeNode
			oNextNode.Text = "Dummy"
			oTopNode.Nodes.Add(oNextNode)
			oTV.Nodes.Add(oTopNode)
		Next

		'' 일반적인 TreeView 속성주고
		Me.Controls.Add(oTV)
		oTV.Left = oDGV.Left + oDGV.Width + 6
		oTV.Top = oDGV.Top
		oTV.Size = New Size(300, 300)

	Catch ex As Exception

	End Try
End Sub



이제 각 TreeNode개체를 크릭하여 확장할때와 축소할때에
해당하는 프로시져를 BeforeCollapse, BeforeExpand TreeView이벤트 프로시져에
작성하면 되는 것
아래의 두개의 프로시져에 앞페이지에서 TreeView의 이벤트를 응용하여
코딩해보시기를...

    Private Sub oTV_BeforeCollapse(sender As Object, e As System.Windows.Forms.TreeViewCancelEventArgs) Handles oTV.BeforeCollapse
		....
		....
    End Sub

    Private Sub oTV_BeforeExpand(sender As Object, e As System.Windows.Forms.TreeViewCancelEventArgs) Handles oTV.BeforeExpand
		....
		....
    End Sub
***[LOG-IN]***

DataRow배열을 CopyToTable메소드로 테이블만들기

본래의 원본테이블에서 Select를 하여 얻어진 결과는
DataRow개체로 구성된 배열이다..
이 배열을 다시 별도의 DataTable로 만들수 있다
CopyToDataTable메소드..
이것으로 별도의 DataGridView를 TreeView 콘트롤의 TreeNode가 열릴때마다
실행시키면 현재 선택된 정보의 작은 테이블을 보게 할수 있을 것이다





***[LOG-IN]***