WPF 팁

Form Designer 프로젝트 #2 - TreeView 노드 추가 안떠니 평점: 10.0/10 (1명 참여) 조회: 5670

이번에는 프로젝트 관리 화면의 중단에 위치한 TreeView 를 구성해 보겠습니다.
이 Treeview 는 지난 글에 언급했듯이 BOS 어플리케이션의 메뉴를 트리 구조로 만들려고 사용한 것입니다.

 

처음 어플리케이션을 시작하면, 기본적으로 빈 공간이죠.
여기서 [New Prj] 를 클릭한거랑 같죠. 비우고 처음부터 다시 시작~
물론, [Open Prj] 를 클릭하면, 저장된 TreeView 구조를 불러와서 보여주면 되겠구요.
 

지금은 우선 TreeView 에 아이템을 추가하고 삭제하는 것을 하겠습니다.
 

지난 글에서 작업했던, 하단의 버튼들 있죠? 그중 [Add Item] 을 클릭했을 때를 처리하죠.
이 버튼을 클릭했을 때, TreeView 의 상태는 크게 2가지입니다.
 

1. 빈공간. 즉 TreeView 에 아이템이 한개도 없을때.
2. 한개 이상이 있을때.
 

그럼, 1번 상태인지 2번 상태인지를 확인하기 위해, TreeView 의 아이템 갯수를 확인하고.
1번 상태이면, 어플리케이션의 첫페이지는 항상 로그인이므로, 그냥 하드코딩으로 박아버립니다.
2번 상태이면, 먼저 아이템의 이름을 사용자로 부터 받습니다.
 

여기서 좀 골때리는 상황이 오는데요. C# 에는 VB 의 InputBox 같은게 없다고 합니다.
구글링 해본 결과, 사용자 입력을 달랑 하나 받는데에도, 사용자 정의 윈도우를 만들어야 한다고 하네요.
모...이런 XXX 같은 경우가 다 있는지...겨우 달랑...이름 하나 받는데...
 

그래서...찾아보니, 아래와 같은 글을 발견....
 

http://stackoverflow.com/questions/97097/what-is-the-c-sharp-version-of-vb-nets-inputdialog
 

요점은 솔루션 탐색기에 현재 프로젝트의 References 에 Microsoft.VisualBasic 을 추가하라는겁니다.
추가하고 나면, 아래와 같이 VB 의 InputBox 를 불러다 쓸수 있다는 겁니다.
추가하고 나면 이렇게 보입니다. 아래 "Microsft.VisualBasic" 이 추가된 겁니다.
 

 

즉, VB 에서 InputBox 가 구현되어 있는 DLL 을 불러다 쓰는거죠...몇번의 클릭으로 복잡한
DLL import 가 해결되고...좋네요...쓰기 편한데요...이기종의 함수를 이렇게 쉽게 불러다 쓰고....ㅋㅋㅋ
 


zItemName = Microsoft.VisualBasic.Interaction.InputBox("Enter a new name", "Add", "", -1, -1);

위의 코드로 사용자에게 새로 추가할 아이템의 이름을 받아옵니다.
Treeview 의 아이템 중 어느 아이템은 포커스가 있는 상태이니까,
포커스가 있는 (선택된) 아이템의 객체를 private 변수로 보관해둔 (SelectedItemChanged 이벤트에서),
그 보관된 변수, 즉 그 아이템의 자식으로 아이템을 추가하는 겁니다.
 

이때 주의할 것은 사용자가 입력한 값이 valid 한지 점검하는 코드를 추가하고
(왜냐면, 그냥 취소 버튼 누르거나, 입력상자를 그냥 닫아버리거나, 그냥 아무것도 안넣고 엔터키를 치는 경우는
아이템의 제목 없이 유령 아이템이 생깁니다...ㅎㅎ),
 

포커스가 갔을때 담아두었던, TreeViewItem 객체, tvSelectedItem 이 null 인지 아닌지를 확인합니다.
포커스가 한번도 안갔으면, 이 객체는 널 상태였겠죠. 그러니 확인을~~~
 

그래서, 여기까지의 코드가 아래와 같습니다.

 

private TreeViewItem tvSelectedItem; // 아이템이 선택됐을때, 해당 아이템을 보관할 용도

private void Button_Click_1(object sender, RoutedEventArgs e)

{

// 추가할 아이템의 이름을 받아두는 변수입니다.
String zItemName;

// 추가할 아이템을 미리 만들어 둡니다.
TreeViewItem
newChild = new TreeViewItem();

if (BOS.Items.Count == 0)
{

 

// TreeView is blank.
newChild.Header = "Login";
BOS.Items.Add(newChild);

}
else
{

 

// Add a new item as child to the selected item.

zItemName = Microsoft.VisualBasic.Interaction.InputBox("Enter a new name", "Add", "", -1, -1);

zItemName = zItemName.Trim();

if ((zItemName.Length > 0) && (tvSelectedItem != null))

{

newChild.Header = zItemName;

tvSelectedItem.Items.Add(newChild);
 

}

}

}


 

위의 코드를 잘 보면, newChild 가 생성해 놓고 한번도 참조가 안되는 경우가 발생하죠?
사용자가 아이템 이름을 안넣는 경우, newChild 는 한번도 사용이 안되죠.
그럼, 개발자가 임의로 free 를 시켜야 하나? 구글에서 사람들이 그러네요, 이런것 때문에 C# 쓴다구요.
어느 시점에 garbage collector 가 free 시켜주니까요.
 

그럼, 이제 언제 tvSelectedItem 이 선택된 아이템 객체를 보관하는지 알아보죠.
이것 때문에 몇시간 낭비했습니다. 아직도 이유는 모릅니다.
그냥. 이 이벤트가 아니라 저 이벤트를 써라~

 

처음 구글링 해보니...현재 선택된 아이템을 어떻게 확인하는지...이렇게 하라고 써있네요.
 

XAML 에서,
 

<TreeView TreeViewItem.Selected="OnItemSelected"
 

그리고 cs 에서,
 

private void OnItemSelected(object sender, RoutedEventArgs e)

{

tvSelectedItem = (sender as TreeViewItem);

if ((sender as TreeViewItem) == null) MessageBox.Show("null!!!!");

}

 

했습니다. 그랬더니...이게 null 로 나오네요....헐.....
이렇게 저렇게 해봐도 계속 null 로 나옵니다.

 

이벤트는 잘잡히구요. 아이템을 클릭하면, 위의 이벤트가 실행은 되는데 sender 가 널로 나와요..
참 답답할 노릇이죠... 왜 그러지.. 그래서, 결국 데브피아의 질답에 물어보니, 답변을 받았습니다.


 

<TreeView Name="BOS" SelectedItemChanged="SelectionChanged"

SelectedItemChanged 라는 이벤트를 쓰라고요. 근데, 이벤트를 지정하는 방식이 제가 처음한거랑,다르네요. 문법의 차이인지...모 여튼...다르지만..이유는 나중에 시간나면...찾아보고요..
 

일단..위의 방법이 작동을 하네요. 아래와 같이요.

 

private void SelectionChanged(object sender, RoutedPropertyChangedEventArgs<Object> e)

{

//Perform actions when SelectedItem changes
//MessageBox.Show(((TreeViewItem)e.NewValue).Header.ToString());

tvSelectedItem = (TreeViewItem)(sender as TreeView).SelectedItem;

}


여기까지 해서 빈공간의 Treeview 에 아이템을 사용자에게 받은 이름으로 추가하는것을 완성했습니다.
별거 아닌데..참 길게 느껴지네요.
 

 

-------------------------------------------------------------------------

위에 까지는 제가 잘 몰라서 삽질한 코드이구요 이런 이벤트도 있다는 걸 알아두는 것으로 하죠.
왜냐하면, 위에 처럼 이벤트를 이용하지 않았도 된다는 것을 알게 되었습니다.


아래처럼요,


        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            String zItemName;
            TreeViewItem newChild = new TreeViewItem();
            if (BOS.Items.Count == 0)
            {
                newChild.Header = "Login";
                BOS.Items.Add(newChild);
            }
            else
            {
                if (BOS.SelectedItem != null)
                {
                    zItemName = Microsoft.VisualBasic.Interaction.InputBox("Enter a new name", "Add", "", -1, -1);
                    zItemName = zItemName.Trim();
                    if (zItemName.Length > 0)
                    {
                        newChild.Header = zItemName;
                        //tvSelectedItem.Items.Add(newChild);  // 이렇게 할 필요가 X
                        (BOS.SelectedItem as TreeViewItem).Items.Add(newChild);
                    }
                }
            }         
        }

 


위에 코드를 보면 아시겠지만, TreeView 에 SelectedItem 속성으로 현재 선택된 노드의 객체를 접근할 수 있네요.
그래서, tvSelectedItem 가 더이상 필요 없네요.
 


위의 코드가 완성된 코드이구요, 다음은 아이템 삭제를 해 봅시다.

 

 

 

 

 

{

태그 : C# TreeView WFP
작성자 정보
안떠니
Level 28
 [EXP.46/50]

메일:  비공개
글등록 +12 444 덧글등록 +3 246
자기소개
회사에서 WPF C# 으로 프로그램을 만들라고 하네요 ^^;
글 공유하기 |
  tweet facebook
2013-02-09 오전 5:03:45
나도한마디
사용자
동굴아저씨            [2013-03-29]
Level 7
 [EXP.8/14]
이런식의 강좌 신선하네여 몰입력이 생기네여 ㅋ
태그로 엮인글
[C#.NET Q&A] Toolstripmenuitem 질문이에요 [1]+1  밀키스
[C#.NET Q&A] Cannot find type System.Resources.ResourceSet 오류   뭉게구름
[구인&교육정보] [수원]C#, Silverlight 고급 개발자 모집(4/3~)  인텍솔루션(주)
[구인&교육정보] C#,Nexacro(고급)모십니다  장자방
[구인&교육정보] [서울역/운영] SCM시스템(C#) 운영  인포젠
[C#.NET Q&A] mysql DB로 텍스트파일 저장 [1]+3  밀키스
[구인&교육정보] [상암동] 은행 기업인터넷뱅킹 유지보수 개발자 모집(c#, .net, Winform)  essoft
[C#.NET Q&A] C# Ultra Grid 헤더 열고정에 관해서 문의드립니다.  꼬니복이
[C#.NET Q&A] 비활성 창의 화면을 캡쳐해서 표시하는데 자꾸만 특이한 에러가 납니다 [1]  P군군군
[C#.NET Q&A] 프로그램 실행시 갑자기 오류가 뜹니다..[2]+1  용서니
글리스트
CheckBox ListBox 샘플[1] 파일첨부 이재웅
RadioButton ListBox 샘플 파일첨부 이재웅
UniformGrid ListBox 샘플 파일첨부 이재웅
Horizontal ListBox 샘플 파일첨부 이재웅
Vertical ListBox 샘플[2] 파일첨부 이재웅
Form Designer 프로젝트 #7 - Tool Window (콘트롤 속성 지정/변경) - 완료![1]+1  안떠니
Form Designer 프로젝트 #6 - Tool Window (콘트롤 추가/삭제) - 완료![3]+1  안떠니
Form Designer 프로젝트 #5 - TreeView Manager  안떠니
Form Designer 프로젝트 #4 - TreeView + XML [1]  안떠니
Form Designer 프로젝트 #3 - TreeView 삭제 / 이름변경[2]+2  안떠니
 ★현재글->   Form Designer 프로젝트 #2 - TreeView 노드 추가[1]  안떠니
Form Designer 프로젝트 #1 - 프로젝트 관리 화면[4]+1  안떠니
실행파일에서 config 파일 변경하기[1]+3  킴언어
계산기[3]  sa2랑
WPF 성능관리  sa2랑
[RE] WPF Performance Suite  sa2랑
WPF에서 내부에서 작업한 내용을 UI에 올릴때 Dispatcher 클래스 사용[1]  지유니
VS와 Blend에서 화면구조 보기 파일첨부 깜디
Canvas 의 Preview 기능 구현하기[1] 파일첨부 깊은물
[Command] 하나의 컨트롤에 여러 커맨드를 등록하는 법[1]  깜디
[UX 스터디 자료] WPF 자료[4] 파일첨부 sky