PROGRAMMING WORKSHOP

.Net FrameWork,VB.Net |DataTable,DataGridView,LINQ

BindingSource,BindingList,DataBinding,UserDefinedClass

BindingSource, DataBindings, Binding 등 헷갈리는 이야기를 많이 했다
좀더 헷갈리도록 BindingNavigator라는 것을 이번 페이지에서 또 추가 해보고..
더불어서..어쩔수 없이 나오게 되는 낯선작업들
ENUM 개체, 즉 열거상수를 사용하는 방법
DataTable대신에 사용자정의 개체, Class를 만들어 보자
사용자정의개체에서 만들어지는 것을 집합체에 모아서
집합체를 DataGridView의 DataSource속성에 사용해 보자
그리고 DataGridView의 열에는 다양한 형식이 제공된다
엑셀의 워크시트과는 좀더 다르 면이 있아, 이 부분을 살펴보자
크래스를 활용하는 것을 이해하기 쉽게 3개의 화일로 구성해보자

1)사용자정의 크래스의 잘못된 사용

아래의 그림과 같이 BindingNavigater개체를 만들어서
데이타의 이동과 편집을 원활하게 하는 컨트롤을 하나 추가했고...별 문제없고..
DataGridView의 열의 형식도 하나는 콤보상자, 다른 하나는 일반Text상자 ,
또다른 하는 CheckBox , 잘 구현이 되었는데
문제는 DataGridView에 데이타가 눈에 보이지 않는다
사용자정의개체를 만들어서 DataSource로 사용한 것에서 문제가 있었다



Public Class Form1
	...
	...
	Private oMembers As List(Of member)
    Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles MyBase.Load
        setUpDGV_1()
    End Sub
	
	Sub setUpDGV_1()
		....
		''사용자정의 타입개체 member를 담을 집합체를 외부변수에 담아 생성하고
        oMembers = New List(Of member)
		''DataGridView의 100개의 행이 될 member개체 100개를 oMembers에 생성하여 담는다
        For iX As Integer = 1 To 100
            Dim oX As New member
            oX.grade = Choose(Int(Rnd() * 6), Grade.A, Grade.B, Grade.C, Grade.E, Grade.F)
            oX.name = New String(Chr(Int(Rnd() * 26) + 65), Int(Rnd() * 5) + 2) & New String(Chr(Int(Rnd() * 26) + 90), Int(Rnd() * 5) + 2)
            oX.comeOrNot = IIf(Int(Rnd() * 2) = 0, True, False)
		oMembers.Add(oX)
		Next
		...
		...
		...
        oBS.DataSource = oMembers

        '' Binding Navigater 
        oBN.BindingSource = oBS
		
        DGV.DataSource = oBS
        Me.Controls.Add(DGV)		
		...
		...
		...
    End Sub
End Class
''사용자정의 크래스이다
''이것이 뭔가 잘못되었다

Public Class member
    Public grade As Grade
    Public name As String
    Public comeOrNot As Boolean
End Class	


Class는 외부적으로 하는 일을 외부에서 몰라야 하는 것이 원칙이다
외부적으로 접근하는 Class는 Property라는 즉 속성이라고 하는 것과
메소드라고 하는 것으로 감쌓야 한다(wrapping)
내부적으로 정보를 임시 보관하고 있는 것은 모두 Field라고 한다
위의 크래스에서
Public grade As Grade
라고 Public으로 외부에 노출시키는 것은 편법이다
아주 간단한 작업에서는 위와 같이 하여 임시 정보를 보관하는 역할을 하게 하여
활용하지만, 정식적으로 크래스의 역할을 할수 없다
특히 위와 같은 3개의 정보를 .NetFrame Work다양한 개체들과 연결하는 작업에서는
정상적인 작업을 기대 할수 없다
여기에서는 연결된 DataGridView가 이것을 읽을수 없는 것이다
위와 같은 경우를 정상적으로 다른 개체들고 일을 무난하게 하는
표현을 한다면 아래와 같이 하여야 한다

Public Class member
    Private grade_ As Grade
    Private name_ As String
    Private comeOrNot_ As Boolean
	''아래와 같이 Public이라고 한 Field를 죽이고
	''위와 같이 Private로 Field로 선언한후..
    ''Public name_ As String
    ''Public comeOrNot_ As Boolean
    ''Public sex_ As Sex
	''아래와 같이 각각 읽는 속성은 Get, 쓰는 속성은 Set 으로 구분하여
	''정식 속성(Property)로 표현하여
	''내부적인 관련된 변수(Field라고 부른다)와 소통시키는 것이다
    Public Property Name() As String
        Get
            Return name_
        End Get

        Set(ByVal Value As String)
            name_ = Value
        End Set
    End Property

    Public Property comeOrNot() As Boolean
        Get
            Return comeOrNot_
        End Get
        Set(ByVal Value As Boolean)
            comeOrNot_ = Value
        End Set
    End Property

    Public Property grade() As Grade
        Get
            Return grade_
        End Get
        Set(ByVal Value As Grade)
            grade_ = Value
        End Set
    End Property
End Class

위와 같이 하면 정상적으로 DataGridView 개체가 관련된 속성을
읽고 쓰고 할수 있게 된다
위에서 보면 속성작성이 복잡해 보이지만 비쥬얼스튜디어의 편집기능은 뛰어나서..



속성의 템프릿코드가 자동 작성된 것이다
이 상태에서 속성명하나와 속성의 타입만 고쳐주면
관련된 내용이 모두 같이 수정된다
첨부되는 화일에서는 이 속성없이 Field를 외부로 노출하는 Public으로 하였으니
각자 한번 위와 같이 수정해 보시고 실행해 보시면
아하!!!! 하실 것이다

또한 Sub,Function 이라고 치고 Tab키를 쳐도 템프릿이 자동작성되고..
직접 해보시는 것이 제일 좋다

또한 처음 소개하는 것이 Enum 타입, 즉 열거상수
DataGridView의 콤보상자열에 성적등급을 넣고 싶다고 치면
아래와 같이 Enum타입을 하나 선언하고

Public Enum Grade
    A
    B
    C
    D
    E
    F
End Enum
Public Class Form1
    Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles MyBase.Load
        setUpDGV_1()
    End Sub
    Sub setUpDGV_1()
        '' 데이타소스만들기, 사용자정의 크래스로 개체를 생성하여 만든다
        Dim oMembers As New List(Of member)
        For iX As Integer = 1 To 100
            Dim oX As New member
            oX.grade = Choose(Int(Rnd() * 6), Grade.A, Grade.B, Grade.C, Grade.E, Grade.F)
            oX.name = New String(Chr(Int(Rnd() * 26) + 65), Int(Rnd() * 5) + 2) & New String(Chr(Int(Rnd() * 26) + 90), Int(Rnd() * 5) + 2)
            oX.comeOrNot = IIf(Int(Rnd() * 2) = 0, True, False)
            oMembers.Add(oX)
        Next


        '' DataGridView 
        Dim DGV As New DataGridView
		'' ComboBox Type 열 만들기
		''이때 위의 Enum 타입을 읽어서 콤보상자에 넣는다
        Dim column As DataGridViewColumn = New DataGridViewComboBoxColumn
		'' 아래의 Enum.GetyValues(GetType(Grade))라고 입력하면
		'' Enum타입은 [] 괄호가 자동으로 입력된다, 자판으로 직접입력하는 것이 아니다..
        CType(column, DataGridViewComboBoxColumn).DataSource = [Enum].GetValues(GetType(Grade))
        column.DataPropertyName = "Grade"
        column.Name = "등급"
        DGV.Columns.Add(column)
		'' TextBox Type 열 만들기
        column = New DataGridViewTextBoxColumn()
        column.DataPropertyName = "Name"
        column.Name = "이름"
        DGV.Columns.Add(column)
		'' CheckBox Type 열 만들기
        column = New DataGridViewCheckBoxColumn()
        column.DataPropertyName = "comeOrNot"
        column.Name = "참석여부"
        DGV.Columns.Add(column)
		
        ...
		...
		
		'' BindingSource개체 만들고
		'' DataSource는 사용자정의 개체로 만든 집합체를 연결한다
        Dim oBS As New BindingSource
        oBS.DataSource = oMembers
		'' BindingNavigator개체를 만들고
		'' 이때 매개변수 True를 주지 않으면 BindingNavigator의 
		''각각의 버튼이 하나도 생기지 않고 빈탕이다
		'' 즉 필요한 버튼만 생성하여 추가하면 된다
		'' 다음 기회에 다양한 버튼을 별도로 추가하는 것을 해보도록 하자
        Dim oBN As New BindingNavigator(True)
        Me.Controls.Add(oBN)
		'' BindingNavigator의 BindingSource은 위에서 생성한 BindingSource를 연결하고
        oBN.BindingSource = oBS
		...
		...
		...
		''DataGridView의 DataSource도 위의 BindingSource로 연결하고
        DGV.DataSource = oBS
        Me.Controls.Add(DGV)
		...
		...
		...

    End Sub


End Class

***[LOG-IN]***

2) 크래스속성을 정식으로 넣고, BindingNavigator에 콤보상자를 하나더 달아보자

크래스속성을 정식으로 넣고 보니
아래의 그림과 같이 BindingNavigator와 연동이 잘되어 Navigation이 원활하고
행의 추가나 삭제도 자유롭게 된다
BindingNavigator에 콤보상자를 하나 추가하여 보자
BinidngNavigator는 실은 ToolStrip에 Navigation이나 삭제,추가등
데이타관련 ToolStripItem을 특별히 조합한 콘트롤이다
그래서 마음대로 원하는 콘트롤(ToolStripItem)을 추가할수도 있다




'' ToolStripItem 중의 하나인 ToolStripDropDownButton개체를 하나 만들어서
        Dim oDropDown As New ToolStripDropDownButton
        oDropDown.Text = "폰트목록"
''FontFamily개체의 Families배열을 순환하면서 
''DropDownButton의 목록으로 담는다		
        For Each i In System.Drawing.FontFamily.Families
            oDropDown.DropDownItems.Add(i.Name)
        Next
'' ToolStripDropDownButton 개체를 크릭하면 발생하는 이벤트프로시져를 지정하여
'' 크릭하면 DataGridView의 폰트가 바뀌도록 해보자
        AddHandler oDropDown.DropDownItemClicked, AddressOf ItemClicked
''BindingNavigator개체를 생성하여 
''이때 매개변수를 True로 주는 것은 BindingNavigator의 기본적으로 필요한
''이동버튼,삭제버튼,추가버튼등의 셋트가 자동구성된다
''만약 False로 하거나 매개변수를 주지 않으면 빈탕의 BindingNavigateor만
''만들어진다, 이때는 하나,하나 필요한 ToolStripItem을 추가하여야 한다		
        Dim oBN As New BindingNavigator(True)
''BindingNavigator에 위에서 만든 콤보상자(ToolStripDropDownButton)을 추가하고
        oBN.Items.Add(oDropDown)
''폼의 컨트롤에 추가한다
        Me.Controls.Add(oBN)
***[LOG-IN]***

3)Binding 개념을 위한 쌤플폼 하나더, 그리고 ENUM 열거상수타입의 활용

아래의 그림과 같이
어디에서 갖여왔던 정보를 DataTable에 담아 놓고..
BindingSource개체에 연결해 놓으면
DataTable은 잊어버리고 BindingSource하나로 다양한 콘트롤에
연결하면 모두 같이 움직인다..



더불어서..
VBA에서와는 달리, 지능이 빵빵한 ENUM열거상수..

Public Enum myNum
    one = 1
    two = 2
    three = 3
    four = 4
    five = 5
    six = 6
    seven = 7
    eight = 8
    nine = 9
    ten = 10
End Enum
...
Public Class moreAboutBinding
'' 새프로젝트를 사용하면 Form1이 항상 나타난다
'' 하지만 좀더 세련된 코딩을 하다 보면 Form을 없애버리고
'' 크래스모듈을 삽입하고 Form 크래스를 상속받아서 하는 것이 재미있고
'' 앞으로의 확장성이 좀더 좋아진다
'' 어떤 크래스모듈에서던 Inherits Form 이라고 하면 , Form의 모든 것이
'' 사용하는 크래스가 상속받게 된다
'' 아래의 Inherits 는 WindowForm을 사용하지 않고
'' Class모듈을 삽입하고 Form을 상속받아서 하였다
'' Class모듈을 항상 사용하는 습관이 좋다
'' 그래서 여기에서 Inhtrits Form을 지워버리면 안된다
    Inherits Form
'''VB.Net 이전의 Form화일은 항상 .Frm이라는 확장자가 붙었었으나
'''VB.Net에서는 .Frm확장자가 없고 모두 .vb 라는 확장자가 붙는다
'''
...
'' Enum열거상수를 사용하여 테이블의 정보를 만든다
'' Int16,Int32,Int64타입은 VBA에서 Integer타입을 더 분류하였다
'' VBA에서의 Integer에 해당하는것은 Int16, Long타입은 Int32
'' 그이상의 정수는 Int64타입...여기에서는 Int32
'' 그러니 Integer타입 보다는 Int16이나 Int32 타입을 사용하는 습관이 좋다
'' DataTable 의 Column 3개 만들고..
''
oTbl = New DataTable
oTbl.Columns.Add("Value", GetType(Int32))
oTbl.Columns.Add("Name", GetType(String))
oTbl.Columns.Add("Desc", GetType(String))
''데이타를 채운다
''Enum타입의 갯수만큼 순환하면서
''[Enum].GetValues(GetType(myNum)) 이라고 하면 
''Enum상수상의 값을 배열로 얻어온다, 즉 {1,2,3,4,5,6,7,8,9,10}이라는 배열
''그리고 ''[Enum].GetNames(GetType(myNum)) 이라고 하면 '' Enum상수상의 상수명을 배열로 얻어온다, 즉 {one,two,three,four,,,,,,,} 라는 배열
For iX As Int32 = 1 To [Enum].GetValues(GetType(myNum)).Length Dim oRow As DataRow = oTbl.NewRow oRow.Item(0) = iX oRow.Item(1) = [Enum].GetNames(GetType(myNum))(iX - 1) oRow.Item(2) = Chr(Int(Rnd() * 26) + 65) oTbl.Rows.Add(oRow) Next ... ...

BindingSource에 위의 DataTable을 연결하고
각 콘트롤에 연결하는 것은 화일에서 보시기를...

***[LOG-IN]***