PROGRAMMING WORKSHOP

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

Binding의 이해와 활용..BindingSource,BindingList,DataBinding

아래의 그림과 DataGridView의 어떤 행을 선택하면
다른 콘트롤에도 정보가 연동이 되게 하고 싶은 것은 프로그래밍의 코딩작업의 수고를
아주 많이 덜어준다
주어진 기능을 얼마나 잘 알고 활용하느냐에 따라서
지루한 코딩을 한두줄로 처리할수 있을 것이다



그림과 같이 DataGridView콘트롤의 행의 선택을 바꿀때마다
지정한 어떤 콘트롤의 값도 같은 값이 표현되게 하고 싶다면
VBA를 하였던 상식으로 생각해 보면
DataGridView콘트롤의 행을 선택할때발생하는 이벤트를 찾아서
이벤트프로시져에 코딩을 하여 원하는 콘트롤의 값을 바꿔주는 코딩을 해주면 되겠지
라고 생각하는 것이 당연할 것이다
하지만 WinForm의 프로그래밍에서는 좀더 편리한 Binding이라는 개념이 있다

아래의 그림과 같이 폼에 아무 콘트롤이나 그려 넣고 속성창을 보면 처음 나타나는 것이
DataBindings이라는 속성명이 있다



엑셀 VBA에서 UserForm의 콘트롤에서는 볼수 없었던 속성이다
뭣을 바인딩한다는 것이지????
이것을 알면 된다
그리고 속성명의 끝에 s자가 붙은 것을 보니, 집합체라는 모양인데
DataBinding을 여러게 할수 있다는 소린가?? 그렇다..
예를 들면 TextBox개체는 Text속성과 Tag속성이 있다
그러니 Text속성에도 뭔가 다른 곳의 정보와 바인딩할수 있고
Tag속성에도 다른 곳에 정보와 바인딩할수 있다는 소리다..
이것을 이해하기 위하여 DataBindings속성이 없다고 치고 어떤 개체의 정보가
변할때마다 어떤 콘트롤의 정보가 따라서 변하게 하고 싶다면!! 이라는 컨셉으로 코딩을 한다면
DataGridView의 행을 선택할때마다 다른 텍스트박스의 Text값이 바뀌게 한다면
전역변수로..

WithEvents oDGV As Windows.Forms.DataGridView = Nothing

라고 선언하면
해당 DataGridView의 이벤트목록이 나타난다..WithEvents라는 키워드때문에 나타난다
물론 AddHandler로 프로시져를 만들수도 있지만
간단한 경우 WithEvents로 선언하여도 편리하다
이벤트목록에서 적당한 이벤트프로시져를 찾아서 아래와 같이 작성할수 있을 것이다
여기에서는 DataGridView의 열머리를 크릭하면 발생하는
RowHeaderMouseClick 이벤트프로시져에 작성하자

Private Sub oDGV_RowHeaderMouseClick(sender As Object, e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles oDGV.RowHeaderMouseClick
Dim iIndex As Integer = e.RowIndex
Dim oListOfTextbox As New List(Of TextBox)

'' FlowLayoutPanel에 TextBox콘트롤이 콤보상자와 섞여있다..
'' 그중에서 TextBox만 모아놓는다
For Each oCtl As Control In Me.Controls(0).Controls(0).Controls
	If TypeName(oCtl) = "TextBox" Then
		oListOfTextbox.Add(oCtl)
	End If
Next

'' 각텍스트박스에 순서대로 DataGridView의 선택된 행의 각 Cell의 값을 전달한다
For iCol As Integer = 0 To 4
	oListOfTextbox(iCol).Text = oDGV.Rows(iIndex).Cells(iCol + 1).Value
Next

End Sub

위와 같이 하는 것이 삽질인 것이다
위와 같은 코딩없이
그냥 DataGridView의 어떤 값과 어떤 콘트롤의 어떤 속성과 값을 묶어 놓으면(Binding)
되지 않을까???그런 아이디어에서 만들어진것이 Binding이라고 하는 것이고
앞으로 많이 활용하게 될 것이다

아래와 같이 활용해보자..
텍스트박스를 순환문으로 순환하면서 만들면서 각각의 텍스트박스의 DataBindings속성에
어떻게 Bining을 해주는지 보자..


'' 폼이 로딩될때 텍스트상자를 5개 만들면서
'' 각각의 텍스트상자개체의 DataBindings 속성에 Add 시켜나간다..
For iX As Integer = 1 To 5
	Dim oTxt As New Windows.Forms.TextBox
	oTxt.AutoSize = True
	oTxt.BackColor = Color.Aqua
	oTxt.ReadOnly = True

	oFlow.Controls.Add(oTxt)

	''아래와 같이 DataTable의 원본과 Binding을 한다
	
	oTxt.DataBindings.Add("Text", oTable, oTable.Columns(iX).ColumnName)

Next

위와 같이 하면 DataTable을 원본으로 사용하는 DataGridView의 행이 활성화(선택)될때마다
위의 5개의 텍스트상자의 Text속성이 같이 자동으로 바뀌게 되는 것
실은 위의

oTxt.DataBindings.Add("Text", oTable, oTable.Columns(iX).ColumnName)

는 정식으로 하면 아래와 같다

oTxt.DataBindings.Add(New Binding("Text", oTable, oTable.Columns(iX).ColumnName))

아하...NetFrame Work는 죄다 개체투성이라고 하더니..
역시 이것도 Binding이라는 개체를 만들어서 콘트롤의 DataBindings라는 Binding개체를
집합적으로 관리하는 집합체에 추가할수 있다는 것이로구나..
마치 엑셀 VBA에서 Shape(도형)을 만들어서 Shapes(도형집합체)에 Add 하듯이..
맞다..!!
이개체가 Data를 제공해주는 원본과 콘트롤의 연결고리 역할을 해주는 것
원본의 변화를 스스로 읽어서, 어라..원본의 바뀌었네..재빨리 연결된 콘트롤의 속성의 값을 바꿔준다

아래의 그림과 같이 메인폼을 하나 만들어서
3개의 쌤플폼을 만들어서 보면 이해하시는데 도움이 될 것이다
첫째폼은 바인딩없이 전통적 방식으로 DataGridView의 행의 위치가 변하는 이벤트에서 각콘트롤에 값을 주는 전통적방식..
둘째폼은 DataTable+BindingSource+DataGridView와 같이 중간에 BindingSource를 넣고..
셋째폼은 BindingSoure를 중간에 넣으면 왜 편리한지를 보기 위한 것..



DataTable을 DataGridView의 DataSource에 직접 연결하고
각각의 콘트롤의 DataBindings에 아래와 같이 연결해도 된다

Dim oBinding As New Binding("연결하려는 콘트롤의 속성명",DataTable, "원본의 열머리명")
TextBox.DataBindings.Add(oBinding)


와 같이 하여도 되지만

Dim oBindingSource As New BindingSource
oBindingSource.DataSource=DataTable
DataGridView.DataSource=oBindingSource
Dim oBinding As New Binding("연결하려는 콘트롤의 속성명",oBindingSource, "원본의 열머리명")


와 같이 중간에 BindingSource라는 것을 넣어서 하는 것이 더 좋은 방법이다
중간에 머리 좋은 놈을 하나 더 장착시키는 셈이다
왜냐면 BindingSource는 많은 메소드와 속성을 제공해주니까...
그것을 활용해 보는 것이 세번째폼쌤플이다
그런 내용의 쌤플화일을 잘 관찰해보시기 바란다

***[LOG-IN]***

콘트롤에 연결고리 역할을 해주는 Binding개체를 좀더 살펴보자..
모든 개체라고 하는 것은 메소드,속성은 당연한 것이고 [이벤트]라고 하는 것이 제공됨을
잊으면 안된다..

아래의 그림과 같이 개체만 만들고..
개체간의 Binding만 하면 모두 서로,서로의 정보를 공유하게 된다
DataGridView의 행을 선택할때마다 모두 연동된다



별 특별한 코딩없이
DataGridView의 행을 선택할때마다 버튼의 Left,Top 속성에 연결된(Binding)
DataGridView의 정보(실은 원본인 DataTable에 연결된 BindingSource개체)를 읽고
버튼의 위치가 바뀐다
엑셀 VBA에서의 프로그램의 개념에서 훌쩍 도약하는 개념이 된다

binding 개체를 WithEvents로 선언하여,
DataGridView에 연결된 BindingSource개체와 콘트롤을 연결하여
Binding개체의 이벤트를 활용하여 아래와 같이 컨트롤에 나타나는 정보의 서식을 할수 있다

Public Class Form1
    WithEvents oTxtBinding1 As Binding
    WithEvents oTxtBinding2 As Binding
''위와 같이 WithEvents로 개체를 선언하면 해당 개체의 이벤트프로시져 템프릿을 볼수 있는 것은
''엑셀 VBA의 워크시트나 통합문서개체의 프로시져를 볼수 있는 것이나 마찬가지..
    Private Sub oTxtBinding1_Format(sender As Object, e As System.Windows.Forms.ConvertEventArgs) Handles oTxtBinding1.Format
        e.Value = Format(e.Value, "X-0000")
    End Sub
    Private Sub oTxtBinding2_Format(sender As Object, e As System.Windows.Forms.ConvertEventArgs) Handles oTxtBinding2.Format
        e.Value = Format(e.Value, "Y-0000")
    End Sub

'' 폼의 Load이벤트에서 런타임으로 컨트롤을 생성하고, Binding개체를 생성하여 연결..	
    Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
'' DataTable 만들고 ..데이타 만들어서 채우기 	
        Dim oTable As New DataTable
        Dim oCol As New DataColumn("Name", GetType(String))
        Dim oCol1 As New DataColumn("X", GetType(Integer))
        Dim oCol2 As New DataColumn("Y", GetType(Integer))

        oTable.Columns.Add(oCol)
        oTable.Columns.Add(oCol1)
        oTable.Columns.Add(oCol2)

        For iX As Integer = 1 To 26
            Dim oRow As DataRow = oTable.NewRow
            oRow.Item(0) = Chr(iX + 64)
            oRow.Item(1) = Int(Rnd() * 100) + 260
            oRow.Item(2) = Int(Rnd() * 100) + 10
            oTable.Rows.Add(oRow)
        Next
'' DataGridView 만들고 .. 	
        Dim oDGV As New DataGridView
        oDGV.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
        oDGV.AllowUserToAddRows = False
'' BindingSource개체 만들고 .. 	
        Dim oBS As New BindingSource
'' DataTable개체를 BindingSource에 담고 .. 	
        oBS.DataSource = oTable
        oDGV.DataSource = oBS
        oDGV.Width = 250
        Me.Controls.Add(oDGV)
'' Button 개체 만들고 .. 	
        Dim oBtn As New Button
'' Button개체의 속성 Left,Top,Text에 BindingSource의 해당값을 Binding개체를 만들어서 연결한다 	
        oBtn.DataBindings.Add(New Binding("Left", oBS, "X"))
        oBtn.DataBindings.Add(New Binding("Top", oBS, "Y"))
        oBtn.DataBindings.Add(New Binding("Text", oBS, "Name"))
        oBtn.Font = New Font("맑은 고딕", 12, FontStyle.Bold)
        oBtn.AutoSize = True
        oBtn.Left = 260
'' TextBox 개체 만들고 .. 	
        Dim oTxt As New TextBox
        oTxt.AutoSize = True
'' Text상자개체의 Text속성과 BindingSource의 해당값과 연결 			
        oTxtBinding1 = New Binding("Text", oBS, "X")
        oTxt.DataBindings.Add(oTxtBinding1)
        oTxt.Top = oDGV.Top + oDGV.Height + 20
        oTxt.Left = 20
        Dim oTxt1 As New TextBox
        oTxt1.AutoSize = True
'' 두번째 Text상자개체의 Text속성과 BindingSource의 해당값과 연결 		
        oTxtBinding2 = New Binding("Text", oBS, "Y")
        oTxt1.DataBindings.Add(oTxtBinding2)
        oTxt1.Top = oDGV.Top + oDGV.Height + 20
        oTxt1.Left = oTxt.Left + oTxt.Width + 10

        Me.Controls.Add(oTxt)
        Me.Controls.Add(oTxt1)
        Me.Controls.Add(oBtn)

        Me.Font = New Font("맑은 고딕", 9)
'' 폼의 Text속성과 BindingSource의 해당값과 연결 		
        Me.DataBindings.Add(New Binding("Text", oBtn, "Text"))
        Me.Width = 500
        Me.Height = 300
    End Sub

End Class
***[LOG-IN]***