이 문서에서는 TreeView 컨트롤을 사용하는 방법에 중점을 둡니다. TreeView 컨트롤은 풍부한 기능을 갖고 있어 다양한 상황에서 사용할 수 있습니다. 요약: TreeView 컨트롤에 데이터 바인딩 기능을 추가하는 방법을 설명합니다. 이는 일련의 Microsoft Windows 컨트롤 개발 예제 중 하나입니다. 관련 개요 기사와 함께 이 기사를 읽을 수 있습니다.
소개
가능하다면 기성 컨트롤로 시작해야 합니다. 제공된 Microsoft® Windows® Forms 컨트롤에는 너무 많은 코딩과 테스트가 포함되어 있으므로 이를 버리고 처음부터 시작하는 것은 낭비입니다. 이를 바탕으로 이 예제에서는 기존 Windows Forms 컨트롤인 TreeView를 상속한 다음 이를 사용자 지정하겠습니다. TreeView 컨트롤에 대한 코드를 다운로드하면 추가 컨트롤 개발 예제뿐만 아니라 다른 데이터 바인딩된 컨트롤과 함께 향상된 TreeView를 사용하는 방법을 보여 주는 샘플 응용 프로그램도 얻을 수 있습니다.
데이터 바인딩 트리 보기 디자인
Windows 개발자의 경우 TreeView 컨트롤에 데이터 바인딩을 추가하는 것이 일반적인 문제이지만 TreeView 와 다른 컨트롤(예: ListBox 또는 DataGrid ) 사이에는 한 가지 큰 차이점이 있으므로(즉, TreeView는 계층적 데이터를 표시함) 기본 컨트롤은 다음과 같습니다. 아직 지원되지 않습니다(즉, 계속 사용해야 합니다). 데이터 테이블이 주어지면 해당 정보를 ListBox 또는 DataGrid 에 표시하는 방법은 분명하지만 TreeView 의 계층적 특성을 사용하여 동일한 데이터를 표시하는 것은 덜 간단합니다. 개인적으로 TreeView 를 사용하여 데이터를 표시할 때 다양한 방법을 적용했지만 가장 일반적으로 사용되는 방법이 하나 있습니다. 그림 1과 같이 테이블의 데이터를 특정 필드별로 그룹화하는 것입니다.
그림 1: TreeView에 데이터 표시
이 예에서는 일반 데이터 세트(그림 2 참조)를 전달하고 그림 1에 표시된 결과를 쉽게 생성할 수 있는 TreeView 컨트롤을 만듭니다.
그림 2: 그림 1에 표시된 트리를 생성하는 데 필요한 모든 정보가 포함된 평면 결과 집합
코딩을 시작하기 전에 저는 이 특정 데이터 세트를 처리할 새로운 컨트롤에 대한 디자인을 생각해 냈고, 이것이 다른 많은 유사한 상황에서도 작동할 수 있기를 바랍니다. 각 계층 수준에 대한 그룹화 필드, 표시 필드 및 값 필드를 지정하는 대부분의 단순 데이터를 사용하여 계층 구조를 생성할 수 있을 만큼 충분히 큰 그룹 컬렉션을 추가합니다(모든 필드는 동일해야 함). 그림 2에 표시된 데이터를 그림 1에 표시된 TreeView 로 변환하려면 새 컨트롤을 사용하려면 두 그룹화 수준인 게시자와 제목을 정의하고 pub_id를 게시자 그룹의 그룹화 필드로, title_id를 그룹화 필드로 정의해야 합니다. 제목 그룹의 필드입니다. 그룹화 필드 외에도 각 그룹에 대한 표시 및 값 필드를 지정하여 해당 그룹 노드에 표시되는 텍스트와 특정 그룹을 고유하게 식별하는 값을 결정해야 합니다. 이런 종류의 데이터가 나타나면 pub_name/pub_id 및 title/title_id를 이 두 그룹의 표시/값 필드로 사용하세요. 작성자 정보는 트리의 리프 노드(그룹화 계층의 끝에 있는 노드)가 되며, 이러한 노드에 대한 ID( au_id ) 및 표시( au_lname ) 필드도 지정해야 합니다.
사용자 정의 컨트롤을 구축할 때 코딩을 시작하기 전에 프로그래머가 컨트롤을 어떻게 사용할지 결정하면 컨트롤을 더욱 효율적으로 만드는 데 도움이 됩니다. 이 경우 프로그래머가 (앞서 표시된 데이터와 원하는 결과를 고려하여) 다음과 같은 몇 줄의 코드를 사용하여 그룹화를 수행할 수 있기를 바랍니다.
| DbTreeControl 사용 .ValueMember = au_id .DisplayMember = au_lname .DataSource = myDataTable.DefaultView .AddGroup(게시자, pub_id, pub_name, pub_id) .AddGroup(제목, title_id, 제목, title_id) 끝 |
참고: 이것은 제가 작성한 코드의 마지막 줄은 아니지만 비슷합니다. 컨트롤을 개발하는 동안 TreeView 와 연결된 ImageList 의 이미지 인덱스를 각 그룹화 수준과 연결해야 하므로 AddGroup 메서드에 추가 매개 변수를 추가해야 한다는 것을 깨달았습니다.
실제로 트리를 구축하기 위해 데이터를 살펴보고 필드(각 그룹화에 대한 그룹화 값으로 지정됨)에 대한 변경 사항을 찾는 동시에 필요한 경우 새 그룹화 노드와 각 데이터 항목에 대한 리프 노드를 생성합니다. 그룹화 노드로 인해 총 노드 수는 데이터 원본의 항목 수보다 크지만 기본 데이터의 각 항목에 대해 정확히 하나의 리프 노드가 있습니다.
그림 3: 그룹 노드 및 리프 노드
리프 노드와 그룹 노드(그림 3 참조) 간의 차이점은 이 기사의 나머지 부분에서 중요합니다. 저는 이 두 가지 유형의 노드를 다르게 처리하고, 각 노드 유형에 대한 사용자 정의 노드를 생성하고, 선택한 노드 유형에 따라 서로 다른 이벤트를 발생시키기로 결정했습니다.
데이터 바인딩 구현
이 컨트롤에 대한 코드를 작성하는 첫 번째 단계는 프로젝트와 해당 시작 클래스를 만드는 것입니다. 이 예제에서는 먼저 새 Windows 컨트롤 라이브러리를 만든 다음 기본 UserControl 클래스를 삭제하고 이를 TreeView 컨트롤에서 상속하는 새 클래스로 바꿉니다.
공용 클래스 dbTreeControl
System.Windows.Forms.TreeView를 상속받습니다.
이제부터 폼에 배치할 수 있고 일반 TreeView 의 모양과 기능을 갖춘 컨트롤을 디자인하겠습니다. 다음 단계는 TreeView 에 추가되는 새로운 기능, 즉 데이터 바인딩 및 데이터 그룹화를 처리하는 데 필요한 코드 추가를 시작하는 것입니다.
DataSource 속성 추가
새 컨트롤의 모든 기능은 중요하지만 복잡한 데이터 바인딩 컨트롤을 구축할 때 두 가지 주요 문제는 DataSource 속성을 처리하고 데이터 소스의 각 개체에서 개별 항목을 검색하는 것입니다.
속성 루틴 생성
첫째, 복잡한 데이터 바인딩을 구현하는 데 사용되는 모든 컨트롤은 DataSource 속성 루틴을 구현하고 적절한 멤버 변수를 유지 관리해야 합니다.
| 비공개 m_DataSource를 객체로 _ 공용 속성 DataSource()를 개체로 사용 얻다 m_DataSource 반환 종료 종료 Set(ByVal 값을 개체로) 가치가 아무것도 아니라면 cm = 아무것도 그룹화변경됨() 또 다른 그렇지 않은 경우(TypeOf 값이 IList 또는 _임) TypeOf 값은 IListSource임) 그런 다음 '은(는) 이 목적에 적합한 데이터 소스가 아닙니다. 새로운 System.Exception 발생(잘못된 데이터 소스) 또 다른 TypeOf 값이 IListSource인 경우 myListSource를 IListSource로 흐리게 설정 myListSource = CType(값, IListSource) myListSource.ContainsListCollection = True이면 다음 새로운 System.Exception 발생(잘못된 데이터 소스) 또 다른 '예, 그렇습니다. 유효한 데이터 소스입니다 m_DataSource = 값 cm = CType(Me.BindingContext(값), _ 통화관리자) 그룹화변경됨() 종료 조건 또 다른 m_DataSource = 값 cm = CType(Me.BindingContext(값), _ 통화관리자) 그룹화변경됨() 종료 조건 종료 조건 종료 조건 최종 세트 끝 속성 |
복잡한 데이터 바인딩을 위한 데이터 소스로 사용할 수 있는 개체가 일반적으로 지원됩니다. 이 인터페이스는 데이터를 개체 컬렉션으로 노출하고 Count 와 같은 몇 가지 유용한 속성을 제공합니다. 새 TreeView 컨트롤에는 바인딩에 IList 지원 개체가 필요하지만 다른 인터페이스를 사용하면 IList 개체( GetList )를 가져오는 편리한 방법을 제공하므로 문제가 없습니다. DataSource 속성을 설정할 때 먼저 유효한 개체, 즉 IList 또는 IListSource 를 지원하는 개체가 제공되었는지 확인합니다. 내가 정말로 원하는 것은 IList 입니다. 따라서 개체가 IListSource (예: DataTable )만 지원하는 경우 해당 인터페이스의 GetList() 메서드를 사용하여 올바른 개체를 가져옵니다.
IListSource를 구현하는 일부 개체(예: DataSet )에는 실제로 ContainsListCollection 속성으로 표시되는 여러 목록이 포함되어 있습니다. 이 속성이 True 이면 GetList는 목록(여러 목록 포함)을 나타내는 IList 개체를 반환합니다. 내 예에서는 IList 객체 또는 IList 객체가 하나만 포함된 IListSource 객체에 대한 직접 연결을 지원하고 DataSet 과 같이 데이터 소스를 지정하기 위해 추가 작업이 필요한 객체는 무시하기로 결정했습니다.
참고: 이러한 개체( DataSet 또는 이와 유사한 개체)를 지원하려는 경우 추가 속성(예: DataMember )을 추가하여 바인딩을 위한 특정 하위 목록을 지정할 수 있습니다.
제공된 데이터 소스가 유효한 경우 최종 결과는 생성된 인스턴스( cm = Me.BindingContext(Value) )입니다. 이 인스턴스는 기본 데이터 소스, 개체 속성 및 위치 정보에 액세스하는 데 사용되므로 지역 변수에 저장됩니다.
표시 및 값 멤버 속성 추가
DataSource를 갖는 것은 복잡한 데이터 바인딩을 구현하는 첫 번째 단계이지만 컨트롤은 표시 및 값 멤버로 사용될 데이터의 특정 필드 또는 속성을 알아야 합니다. Display 멤버는 트리 노드의 제목으로 사용되는 반면 Value 멤버는 노드의 Value 속성을 통해 액세스할 수 있습니다. 이러한 속성은 모두 필드 또는 속성 이름을 나타내는 문자열이며 컨트롤에 쉽게 추가할 수 있습니다.
| 비공개 m_ValueMember를 문자열로 문자열로 개인 m_DisplayMember _ 공용 속성 ValueMember() As String 얻다 m_ValueMember를 반환합니다. 종료 종료 Set(ByVal 값을 문자열로) m_ValueMember = 값 최종 세트 끝 속성 _ 공용 속성 DisplayMember()를 문자열로 사용 얻다 m_DisplayMember 반환 종료 종료 Set(ByVal 값을 문자열로) m_DisplayMember = 값 최종 세트 끝 속성 |
이 TreeView 에서 이러한 속성은 리프 노드의 표시 및 값 멤버만 나타내며 각 그룹화 수준에 대한 해당 정보는 AddGroup 메서드에 지정됩니다.
CurrentManager 개체 사용
앞에서 설명한 DataSource 속성에서 통화 관리자 클래스의 인스턴스가 생성되어 클래스 수준 변수에 저장됩니다. 이 개체를 통해 액세스되는 통화 관리자 클래스는 다음 기능을 활성화하는 속성, 메서드 및 이벤트를 포함하므로 데이터 바인딩 구현의 핵심 부분입니다.
속성/필드 값 검색
CurrentManager 개체를 사용하면 GetItemProperties 메서드를 통해 데이터 소스의 개별 항목에서 DisplayMember 또는 ValueMember 필드 값과 같은 속성 또는 필드 값을 검색할 수 있습니다. 그런 다음 PropertyDescriptor 개체를 사용하여 특정 목록 항목의 특정 필드 또는 속성 값을 가져옵니다. 다음 코드 조각에서는 이러한 PropertyDescriptor 개체를 만드는 방법과 GetValue 함수를 사용하여 기본 데이터 소스에 있는 항목의 속성 값을 얻는 방법을 보여줍니다. 통화 관리자 개체의 List 속성을 참고하세요. 이 속성은 컨트롤이 바인딩된 IList 인스턴스에 대한 액세스를 제공합니다.
| myNewLeafNode를 TreeLeafNode로 흐리게 표시 currObject를 객체로 희미하게 표시 currObject = cm.List(currentListIndex) Me.DisplayMember <> AndAlso Me.ValueMember <> 그렇다면 '리프 노드를 추가하시겠습니까? pdValue를 System.ComponentModel.PropertyDescriptor로 희미하게 표시 pdDisplay를 System.ComponentModel.PropertyDescriptor로 희미하게 표시 pdValue = cm.GetItemProperties()(Me.ValueMember) pdDisplay = cm.GetItemProperties()(Me.DisplayMember) myNewLeafNode = _ 새 TreeLeafNode(CStr(pdDisplay.GetValue(currObject)), _ 현재 개체, _ pdValue.GetValue(currObject), _ 현재목록인덱스) |
GetValue는 개체를 반환할 때 속성의 기본 데이터 형식을 무시하므로 반환 값을 사용하기 전에 변환해야 합니다.
데이터 바인딩된 컨트롤을 동기화 상태로 유지
CurrentManager에는 바인딩된 데이터 소스 및 항목 속성에 대한 액세스를 제공하는 것 외에도 동일한 DataSource를 사용하여 이 컨트롤과 다른 컨트롤 간의 데이터 바인딩을 조정할 수 있다는 주요 기능이 하나 더 있습니다. 이 지원을 사용하면 동일한 데이터 소스에 동시에 바인딩된 여러 컨트롤이 데이터 소스의 동일한 항목에 유지되도록 할 수 있습니다. 내 컨트롤의 경우 트리에서 항목을 선택할 때 동일한 데이터 소스에 바인딩된 다른 모든 컨트롤이 동일한 항목(원하는 경우 동일한 레코드, 행 또는 배열)을 가리키는지 확인하고 싶습니다. 데이터베이스의 관점에서 생각하는 것). 이를 위해 기본 TreeView 에서 OnAfterSelect 메서드를 재정의합니다. 트리 노드를 선택한 후 호출되는 해당 메서드에서 저는 CurrentManager 개체의 Position 속성을 현재 선택한 항목의 인덱스로 설정했습니다. TreeView 컨트롤과 함께 제공되는 샘플 응용 프로그램은 동기화 컨트롤을 통해 데이터 바인딩된 사용자 인터페이스를 보다 쉽게 구축하는 방법을 보여줍니다. 현재 선택된 항목의 목록 위치를 더 쉽게 결정할 수 있도록 사용자 정의 TreeNode 클래스( TreeLeafNode 또는 TreeGroupNode )를 사용하고 각 노드의 목록 인덱스를 내가 만든 Position 속성에 저장했습니다.
| 보호된 재정의 Sub OnAfterSelect _ (ByVal 및 System.Windows.Forms.TreeViewEventArgs) Dim tln As TreeLeafNode TypeOf e.Node가 TreeGroupNode인 경우 tln = FindFirstLeafNode(e.Node) Dim groupArgs를 새 groupTreeViewEventArgs(e)로 사용 raiseEvent AfterGroupSelect(groupArgs) ElseIf TypeOf e.Node가 TreeLeafNode인 경우 희미한 leafArgs를 새 leafTreeViewEventArgs(e)로 사용 raiseEvent AfterLeafSelect(leafArgs) tln = CType(e.Node, TreeLeafNode) 종료 조건 그렇지 않다면 아무것도 아니다. cm.Position <> tln.Position이면 cm.위치 = tln.위치 종료 조건 종료 조건 MyBase.OnAfterSelect(e) 서브 끝 |
이전 코드 조각에서 FindFirstLeafNode 라는 함수를 보셨을 것인데, 여기서 간단히 소개하고 싶습니다. 내 TreeView 에서는 리프 노드(계층 구조의 마지막 노드)만 DataSource 의 항목에 해당하고 다른 모든 노드는 그룹화 구조를 만드는 데만 사용됩니다. 제대로 수행되는 데이터 바인딩된 컨트롤을 만들려면 항상 DataSource 에 해당하는 항목을 선택해야 하므로 그룹 노드를 선택할 때마다 마치 이 노드가 현재 선택. 실제 예제를 확인할 수 있지만 지금은 자유롭게 사용해도 됩니다.
| 개인 함수 FindFirstLeafNode(ByVal currNode As TreeNode) _ TreeLeafNode로 TypeOf currNode가 TreeLeafNode인 경우 CType(currNode, TreeLeafNode) 반환 또 다른 currNode.Nodes.Count > 0이면 FindFirstLeafNode(currNode.Nodes(0)) 반환 또 다른 아무것도 반환하지 않음 종료 조건 종료 조건 기능 종료 |
통화 관리자 개체의 위치 속성을 설정하면 다른 컨트롤이 현재 선택 항목과 동기화되지만, 다른 컨트롤의 위치가 변경되면 그에 따라 선택 항목도 변경되도록 통화 관리자 도 이벤트를 생성합니다. 좋은 데이터 바인딩 구성 요소가 되려면 데이터 소스의 위치가 변경됨에 따라 선택 항목이 이동해야 하며 항목의 데이터가 수정될 때 표시가 업데이트되어야 합니다. CurrentChanged , ItemChanged 및 PositionChanged 의 세 가지 이벤트가 CurrentChanged 에 의해 발생됩니다. 마지막 이벤트는 매우 간단합니다. 통화 관리자 의 목적 중 하나는 여러 바인딩된 컨트롤이 모두 동일한 레코드 또는 목록 항목을 표시할 수 있도록 데이터 소스에 대한 현재 위치 표시기를 유지하는 것입니다. 이 이벤트는 위치가 변경될 때마다 발생합니다. 다른 두 사건은 때때로 겹쳐서 구분이 덜 명확합니다. 다음은 사용자 정의 컨트롤에서 이러한 이벤트를 사용하는 방법에 대해 설명합니다. PositionChanged 는 비교적 간단한 이벤트이므로 여기서는 설명하지 않습니다. 복잡한 데이터 바인딩 컨트롤(예: Tree)에서 현재 선택한 항목을 조정하려면 다음을 사용하세요. 이벤트. ItemChanged 이벤트는 데이터 소스의 항목이 수정될 때마다 발생하는 반면 CurrentChanged 는 현재 항목이 수정될 때만 발생합니다.
내 TreeView 에서는 새 항목을 선택할 때마다 세 가지 이벤트가 모두 발생한다는 것을 알았으므로 현재 선택된 항목을 변경하여 PositionChanged 이벤트를 처리하고 나머지 두 항목에는 아무 작업도 수행하지 않기로 결정했습니다. 데이터 소스를 IBindingList (데이터 소스가 IBindingList 를 지원하는 경우)로 캐스팅하고 대신 ListChanged 이벤트를 사용하는 것이 좋지만 이 기능은 구현하지 않았습니다.
| 개인 하위 cm_PositionChanged(ByVal 보낸 사람 개체로, _ ByVal e As System.EventArgs)는 cm.PositionChanged를 처리합니다. TreeLeafNode로 희미한 tln TypeOf Me.SelectedNode가 TreeLeafNode인 경우 tln = CType(Me.SelectedNode, TreeLeafNode) 또 다른 tln = FindFirstLeafNode(Me.SelectedNode) 종료 조건 tln.Position <> cm.Position이면 Me.SelectedNode = FindNodeByPosition(cm.Position) 종료 조건 서브 끝 개인용 오버로드 함수 FindNodeByPosition(ByVal index As Integer) _ 트리노드로서 FindNodeByPosition(index, Me.Nodes) 반환 기능 종료 개인용 오버로드 함수 FindNodeByPosition(ByVal index As Integer, _ ByVal NodesToSearch As TreeNodeCollection) As TreeNode Dim i를 정수로 = 0 Dim currNode를 TreeNode로 사용 TreeLeafNode로 희미한 tln i < NodesToSearch.Count 동안 수행 currNode = NodesToSearch(i) 나는 += 1 TypeOf currNode가 TreeLeafNode인 경우 tln = CType(currNode, TreeLeafNode) tln.Position = index인 경우 그러면 currNode 반환 종료 조건 또 다른 currNode = FindNodeByPosition(index, currNode.Nodes) currNode가 아무것도 아닌 경우 currNode 반환 종료 조건 종료 조건 고리 아무것도 반환하지 않음 기능 종료 |
DataSource를 트리로 변환
데이터 바인딩 코드를 작성한 후 그룹화 수준을 관리하는 코드를 추가하고 그에 따라 트리를 구축한 다음 일부 사용자 지정 이벤트, 메서드 및 속성을 추가할 수 있습니다.
관리 그룹
그룹 컬렉션을 구성하려면 프로그래머는 AddGroup , RemoveGroup 및 ClearGroups 기능을 생성해야 합니다. 그룹 컬렉션이 수정될 때마다 (새 구성을 반영하기 위해) 트리를 다시 그려야 하므로 상황이 변경되고 트리가 강제로 변경되어야 할 때 컨트롤의 다양한 코드에서 호출할 수 있는 일반 프로시저인 GroupingChanged를 만들었습니다. 재건축되다:
| 개인 treeGroup을 새 ArrayList()로 사용 Public Sub RemoveGroup(ByVal 그룹을 그룹으로) treeGroups.Contains(group)이 아닌 경우 treeGroups.Remove(그룹) 그룹화변경됨() 종료 조건 서브 끝 공용 오버로드 Sub AddGroup(ByVal 그룹을 그룹으로) 노력하다 treeGroups.Add(그룹) 그룹화변경됨() 잡다 시도 종료 서브 끝 공용 오버로드 Sub AddGroup(ByVal 이름을 문자열로, _ ByVal 그룹By As String, _ ByVal displayMember As String, _ ByVal valueMember As String, _ ByVal imageIndex As Integer, _ ByVal selectedImageIndex를 정수로) myNewGroup을 새 그룹으로 Dim(이름, groupBy, _ 디스플레이멤버, 값멤버, _ 이미지 인덱스, 선택된이미지 인덱스) 나.AddGroup(myNewGroup) 서브 끝 공용 함수 GetGroups() As Group() CType(treeGroups.ToArray(GetType(그룹)), 그룹()) 반환 기능 종료 |
스패닝 트리
트리의 실제 재구성은 BuildTree 및 AddNodes 프로세스 쌍에 의해 수행됩니다. 이 두 프로세스의 코드가 너무 길기 때문에 이 문서에서는 프로세스를 모두 나열하지는 않지만 해당 동작을 요약하려고 합니다(물론 원하는 경우 전체 코드를 다운로드할 수 있습니다). 앞서 언급했듯이 프로그래머는 일련의 그룹을 설정한 다음 BuildTree 에서 이러한 그룹을 사용하여 트리 노드 설정 방법을 결정함으로써 이 컨트롤과 상호 작용할 수 있습니다. BuildTree는 현재 노드 컬렉션을 지운 다음 전체 데이터 소스를 반복하여 첫 번째 수준 그룹화(이 문서 앞부분의 예제 및 그림에서 언급한 게시자)를 처리하고, 각각의 다른 그룹화 값에 대해 노드를 추가합니다(예제의 데이터 사용, 각각에 대해 pub_id 값으로 노드를 추가한 다음 AddNodes를 호출하여 첫 번째 수준 그룹화 아래의 모든 노드를 채웁니다. AddNodes는 자신을 재귀적으로 호출하여 필요한 만큼의 수준을 처리하고 필요에 따라 그룹 노드와 리프 노드를 추가합니다. TreeNode를 기반으로 하는 두 개의 사용자 정의 클래스를 사용하여 그룹 노드와 리프 노드를 구별하고 두 가지 유형의 노드에 해당 속성을 제공합니다.
사용자 정의 TreeView 이벤트
노드가 선택될 때마다 TreeView는 BeforeSelect 및 AfterSelect라는 두 가지 이벤트를 발생시킵니다. 하지만 내 제어에서는 그룹 노드와 리프 노드의 이벤트를 다르게 만들고 싶었기 때문에 자체 이벤트 BeforeGroupSelect/AfterGroupSelect 및 BeforeLeafSelect/AfterLeafSelect 를 추가했으며, 기본 이벤트 외에도 사용자 정의 이벤트 매개변수 클래스도 트리거했습니다.
| 공개 이벤트 BeforeGroupSelect _ (ByVal 보낸 사람이 개체로, ByVal e가 groupTreeViewCancelEventArgs로) 공개 이벤트 AfterGroupSelect _ (ByVal 발신자 개체, ByVal e As groupTreeViewEventArgs) 공개 이벤트BeforeLeafSelect _ (ByVal 보낸 사람을 개체로, ByVal e를 leafTreeViewCancelEventArgs로) 공개 이벤트 AfterLeafSelect _ (ByVal 보낸 사람을 개체로, ByVal e를 leafTreeViewEventArgs로) 보호된 재정의 하위 OnBeforeSelect _ (ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) TypeOf e.Node가 TreeGroupNode인 경우 Dim groupArgs를 새 groupTreeViewCancelEventArgs(e)로 사용 raiseEvent BeforeGroupSelect(CObj(Me), groupArgs) ElseIf TypeOf e.Node가 TreeLeafNode이면 희미한 leafArgs를 새 leafTreeViewCancelEventArgs(e)로 사용 raiseEvent BeforeLeafSelect(CObj(Me), leafArgs) 종료 조건 MyBase.OnBeforeSelect(e) 서브 끝 보호된 재정의 Sub OnAfterSelect _ (ByVal 및 System.Windows.Forms.TreeViewEventArgs) Dim tln As TreeLeafNode TypeOf e.Node가 TreeGroupNode인 경우 tln = FindFirstLeafNode(e.Node) Dim groupArgs를 새 groupTreeViewEventArgs(e)로 사용 raiseEvent AfterGroupSelect(CObj(Me), groupArgs) ElseIf TypeOf e.Node가 TreeLeafNode이면 희미한 leafArgs를 새 leafTreeViewEventArgs(e)로 사용 raiseEvent AfterLeafSelect(CObj(Me), leafArgs) tln = CType(e.Node, TreeLeafNode) 종료 조건 그렇지 않다면 아무것도 아니다. cm.Position <> tln.Position이면 cm.위치 = tln.위치 종료 조건 종료 조건 MyBase.OnAfterSelect(e) 서브 끝 |
사용자 정의 노드 클래스( TreeLeafNode 및 TreeGroupNode ) 및 사용자 정의 이벤트 매개변수 클래스가 다운로드 가능한 코드에 포함되어 있습니다.
샘플 애플리케이션
이 샘플 컨트롤의 모든 코드를 완전히 이해하려면 해당 코드가 애플리케이션에서 어떻게 작동하는지 이해해야 합니다. 포함된 샘플 응용 프로그램은 pubs.mdb Access 데이터베이스를 사용하며 Tree 컨트롤을 다른 데이터 바인딩 컨트롤과 함께 사용하여 Windows 응용 프로그램을 만드는 방법을 보여줍니다. 이 경우 특히 주목해야 할 주요 기능에는 트리를 다른 바인딩된 컨트롤과 동기화하고 데이터 소스에서 검색을 수행할 때 트리 노드를 자동으로 선택하는 기능이 포함됩니다.
참고: 이 샘플 애플리케이션(TheSample이라는 이름)이 이 기사의 다운로드에 포함되어 있습니다.
그림 4: 데이터 바인딩된 TreeView의 데모 애플리케이션
요약
이 문서에 설명된 데이터 바인딩된 Tree 컨트롤은 데이터베이스 정보를 표시하기 위해 Tree 컨트롤이 필요한 모든 프로젝트에 적합하지 않지만 개인적인 목적으로 컨트롤을 사용자 지정하는 방법을 소개합니다. 구축하려는 복잡한 데이터 바인딩된 컨트롤은 Tree 컨트롤과 동일한 코드를 많이 갖게 되며 기존 코드를 수정하여 향후 컨트롤 개발을 단순화할 수 있습니다.