[그림 1] ListBox의 빈 공간


ListBox에서 항목을 더블 클릭하여 선택된 항목에 대한 이벤트를 처리하고 싶은데,

MouseDoubleClick 이벤트나 DoubleClick 이벤트를 이용하면 [그림 1]의 하늘색으로 표시한 곳과 같이 

리스트 박스 내 항목이 없는 빈공간에서 더블클릭을 해도 이벤트가 발생합니다.

보통은 빈 공간에 더블클릭을 했을 때는 이벤트가 발생하지 않기를 원하겠죠?


이를 해결하기 위해서는 ListBox의 IndexFromPoint 메서드를 사용하면 됩니다.


메서드 시그너쳐는 다음과 같습니다.


  • int IndexFromPoint(Point p)
    • Point 타입의 p 좌표에 위치한 항목의 인덱스 반환

  • int IndexFromPoint(int x, int y)
    • x, y 좌표에 위치한 항목의 인덱스 반환


위 메서드는 매개변수로 전달된 좌표에 항목이 존재하면 해당 항목의 인덱스를 반환하고,

빈 공간인 경우는 -1을 반환합니다.


이벤트 핸들러로 전달된 MouseDoubleClick 객체에는 이벤트가 발생한 마우스의 좌표값을 가지고 있으므로

이 좌표값과 IndexFromPoint 메서드를 이용하면 더블클릭한 항목을 알 수 있습니다.



[그림 1]의 폼을 이용하여 리스트 박스에서 더블클릭한 항목을 얻는 예를 보겠습니다.

먼저 [그림 1]과 같이 리스트 박스와 텍스트 박스를 배치하고, 리스트 박스에 적당한 항목을 추가합니다.

'언어 목록'에서 더블클릭한 항목을 '선택한 언어'란에 표시하도록 해보겠습니다.


리스트 박스를 선택한 후 속성 창에서  모양을 눌러 이벤트 연결 탭으로 이동 후

MouseDoubleClick 항목의 오른쪽 빈 공간을 더블클릭 해서 이벤트 핸들러를 생성해 줍니다.

(리스트 박스를 더블클릭 하면 리스트 박스의 기본 이벤트인 SelectedIndexChanged 핸들러가 생성됩니다.)


[그림 2] MouseDoubleClick 이벤트 핸들러 추가



[그림 3] 생성된 MouseDoubleClick 이벤트 핸들러



이벤트 핸들러가 생성되면 아래와 같이 코드를 입력합니다.

여기서 제가 만든 리스트 박스의 이름은 lbLanguages 이고 텍스트 박스는 tbSelectedLanguage 입니다.


private void lbLanguages_MouseDoubleClick(object sender, MouseEventArgs e)
{
      // 인덱스를 저장할 변수
      int selectedIndex = -1;

      // 마우스 포인터의 위치
      Point point = e.Location;

      // 리스트 박스의 IndexFromPoint 메서드 호출
      selectedIndex = lbLanguages.IndexFromPoint(point);

      if(selectedIndex != -1) // 빈 공간이 아닌 곳을 더블클릭 했을 때.
      {
          // 선택된 항목 저장
          string selectedItem = lbLanguages.Items[selectedIndex] as string;

          // 선택한 항목으로 텍스트 대입
          tbSelectedLanguage.Text = selectedItem;
      }
 }


소스 코드를 다 쓰신 후 Ctrl + F5 키를 눌러 실행해서 리스트 박스에서 더블클릭 해 보면

빈 공간에서는 아무런 처리를 하지 않고, 항목이 있는 곳에서만 해당 항목을 텍스트 박스에 표시합니다.


[그림 4] 실행 결과



'밤을 지새다' 카테고리의 다른 글

Google Drive를 이용한 파일 버전 관리  (0) 2013.05.24
Linux Kernel Map  (0) 2013.03.24
네이트온 광고와 팝업 없애기  (3) 2012.05.16
파일의 확장자를 보는 방법  (0) 2012.05.16
Gmail 실행파일 첨부 문제  (0) 2012.05.16
외주 때문에 Visual C#에서 DataGridView에 데이터 소스로 DB를 바로 연결했는데,

이상하게도 소스의 레코드 개수와 상관없이 1개만 나타나거나 제대로 보이질 않는다.

(에러가 있으면 차라리 바로 잡기야 하겠는데 그것도 아니니 당시엔 답이 안나온다)

처음엔 꼼수를 써서 다른 방법으로 뷰에 보이는 내용을 다시금 불러오게 했지만 몹시 비효율적이다.

다른 부분에서도 똑같은 현상이 발생하길래  코드를 부분부분 돌려보니,

CellEnter이벤트가 발생하면서 바로 그와 관련된 DB를 바로 읽어와서 다른 뷰에 뿌려주도록 했는데

동시에 뿌려주는 경우 DB는 제대로 읽어오지만,

CellEnter이벤트는 내용이 갱신된 직후 바로 발생하므로 데이터를 뿌리는 동시에 다른 DB도 읽어오게 되어

뷰에 뿌리는 과정 중간에 지나가버리게 된다.

그럼에도 불구하고 뷰의 Rows의 요소 수를 보면 정상적으로 되어있으니, 그냥 보기엔

대체 왜 그런지 알 수가 없다.


어쨌거나 DB를 사용하는 방법이 잘못되었는지, 그 부분을 바로잡진 못하고 돌아가는 방향을 택했다.

CellEnter 이벤트 대신에 CellClick이벤트를 통해 사용자가 직접 클릭한 경우에만

서브 뷰를 보여주도록 했다. 바꿔놓고 보니 너무 불편하다.. 대안책을 찾아야겠다. 

'마음이 뛰다' 카테고리의 다른 글

모난 돌  (0) 2012.01.26
못난 놈  (0) 2012.01.25
김해 희망서포터즈 2기 모집~!  (0) 2011.11.25
청춘콘서트 2.0 희망서포터즈 2기를 모집합니다!  (0) 2011.10.12
인생은 재밌다.  (0) 2011.09.10

+ Recent posts