PROGRAMMING WORKSHOP

.Net FrameWork,VB.Net | UserControl,Timer

폼상에서 이미 만들어졌던 콘트롤 지우기

앞페이지에서 실행된 폼에서는 문제를 한 셋트풀고 나면
더이상 진행할수 없다
다시 껐다가 켜야 하는 바보같은 프로그램이다
앞페이지의 것을 수정하여 계속 반복하여 다음 문제셋트를
풀어나가게 하는 것이 바람직한 프로그램일 것이다
코딩내공이 출중하였다면 이미 처리하셨을수도 있고
이 페이지에서는 계속 무한대로 버튼을 크릭할때마다 새로운 문제가
나열되게 해보고..
점수도 누적된 값을 계산하여 보여주도록 하자

또한 코딩방법도 VB.Net의 특징을 좀더 익숙하게 하는 방법으로 바꿔보자

한번 하였던 테스트가 끝나서 다음 문제를 내려면 이전 문제를
만들었던 myControl개체를 모두 없애야 한다
그래서 아래와 같이 하면


'' 아래와 같이 하거나
	For Each oX As Control In Me.Controls
	    If TypeOf oX Is myControl Then
	        Me.Controls.Remove(oX)
	    End If
	Next
''아래와 같이 하면..
	For Each oX As Control In Me.Controls.OfType(Of myControl)
	    Me.Controls.Remove(oX)
	Next	

어떤 것은 삭제가 되고 어떤 것은 삭제가 되지 않는다..
왜냐면 집합체가 삭제 되면 다시 구성되어 버리니
다음 개체는 빼먹게 된다
아래와 같이 뒤에서 부터 삭제하여 올라가야 한다
순환방법을 뒤에서 부터 위로 가려면 For~Next 순환을 하여..


''이렇게 하거나..
	For iX As Integer = Me.Controls.Count - 1 To 0 Step -1
		If TypeOf Me.Controls(iX) Is myControl Then
			Me.Controls.Remove(Me.Controls(iX))
		End If
	Next

''아래와 같이 OfType메소드를 사용하여 조건에 맞는 것을 한꺼번에 모아서 하던가..
	Dim oDels As IEnumerable(Of myControl) = Me.Controls.OfType(Of myControl)
	For iX As Integer = oDels.Count - 1 To 0 Step -1
	    Me.Controls.Remove(oDels(iX))
	Next

OfType은 VB.Net의 대개의 집합체(Enumable)에서 지원하는 메소드이기도 하고
LINQ언어에서도 사용되는 메소드이다..
여러개의 다양한 타입이 집합되어 있는 것에서 특정한 타입을 순환하지 않고
간단히 가져오는 것이다
아래와 같은 예문을 한번 실행시켜보시면..


Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
''집합체에 배열을 담고..
Dim oArray = {1, 2, 3, "x", "y", "z"}
''위의 것은 실은 아래의 것을 약식으로 표현한것..그러니 아래와 같이 해도 되고
''Dim oArray As IEnumerable(Of Object) = {1, 2, 3, "x", "y", "z"}
''집합체의 OfType() 메소드를 사용하여 간단히 문자열타입만 뽑아내어 다른 집합체에 담는다
Dim oEnum As IEnumerable(Of String) = oArray.OfType(Of String)
''집합체를 ToArray메소드로 하여 배열화하여 배열을 콤마로 연결된 문자열(Join 메소드)로 만든다
MsgBox(String.Join(",", oEnum.ToArray))
End Sub

프로그래밍언어의 발전은 될수있는한 코딩자판때리는 시간을
단축시킬까를 노력하는 것..
그래서 VB.Net에서는 최대한 순환문을 돌리지 않으려는
다양한 집합체에 속한 메소드와 또다른 파워훌한 LINQ언어들이 제공되는것이다
위의
Dim oEnum As IEnumerable(Of String) = oArray.OfType(Of String)
자체가 LINQ문의 표현이라고 보셔도 된다

또하나 순환문으로 처리된 내용을 LINQ로 바꿔보자
아래는 myControl의 계산결과가 True인지 False인지를 확인하기 위하여
myControl을 모두 순환하면서 처리했었다

Dim oMC As myControl
Dim bOK As Boolean = False
''순환하면서 False가 하나라도 있으면 문제를 아직 정상적으로
''풀지 못한 상태라는 것을 확인하는 순환...
For Each oX As Control In Me.Controls
    If TypeOf oX Is myControl Then
        oMC = oX
        If Not oMC.isOK Then
            bOK = False
            Exit For
        Else
            bOK = True
        End If
    End If
Next

위의 내용을 아래와 같이 딱 한줄로 처리할수 있는 것이 LINQ
언어의 활용이다

Dim bOK As Boolean = False
''위의 순환문에서도 최종목표는 bOK값을 무엇인지 확인하는 것이였다
''아래와 같이 LINQ문으로 bOK 값을 얻을수 있는 것
bOK = (From x In Me.Controls.OfType(Of myControl) Where x.isOK = False Select x).Count = 0
''혹은 같은 LINQ라도 다르게 표현할수도 있다..아래와 같이
bOK = (Aggregate x In Me.Controls.OfType(Of myControl) Into Count(x.isOK = False)) = 0

LINQ문은 우리가 대화하듯이 풀어가는 언어다

(From x In Me.Controls.OfType(Of myControl) Where x.isOK = False Select x).Count = 0

라는 것을 풀어보면..
Me.Controls.OfType(Of myControl) 이라고 함은
현재 윈도우폼(Me)의 콘트롤중(Controls)에서
.OfType(Of myControl)의 OfType(Of Type)은 집합체의 확장메소드라고 한다(Extension Method)
즉 myControl 타입의 콘트롤만 집합시켜라!!
그 집합중에서 From x 즉 하나,하나의 myControl개체가 x라는 변수에 담아서
x.isOK=False 는 우리가 만든 UserControl의 메소드 isOK를 호출하여 값이 False인것만
다시 집합을 하는 것...그러니 myControl이라는 개체의 isOK의 결과값이
False는 답이 틀린경우이다..
이것이 0개이면 모두 맞았다는 것이 된다..
그래서 순환문을 돌리지 않아도 LINQ엔진이 알아서 안보이는 곳에서
자신이 순환하는 것이고, 개발자는 몇개의 명령어를 주면 되는것이다

아래 화일을 차근차근 보시면서 내공을 쌓아가시기를..

***[LOG-IN]***