ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C# Listview 오른쪽클릭 메뉴 만들기
    프로그래밍 2013. 7. 2. 14:50
    음.... 오랜만이네요.

    블로그에 코드가 코드처럼 보이는(?) SyntaxHighliter를 설치한 김에 얼마전 삽질한 삽질기를 간단하게 

    써보려고 합니다.

    간단하게 말하면 C# Window Form에서 Listview를 이용할 때, 오른쪽 클릭으로 선택된 아이템을 기준으로 한

    오른쪽 클릭 메뉴(?)를 만드는 방법입니다.


    글로 써놓으니 지저분하네요. 아래 스크린샷을 보시면 한번에 이해되실겁니다.


    사실 오른쪽 메뉴를 만드는건 어렵지 않습니다.


    Listview를 하나 만들고, 마우스 클릭 이벤트에서 Right Click이벤트를 걸러낸 뒤 해당 메뉴를 띄우면 

    되는것이기 때문이죠.


    문제는 Listview Item이 제대로 선택되지 않는다는데 있습니다.



    다시 한번 순서를 정리해보면


    ListView Item에 오른쪽 클릭 -> 메뉴가 뜬다 -> 메뉴에서 원하는 메뉴에 왼쪽 클릭.


    이런 과정이 될 것입니다. 무엇이 문제인가?


    상식적으로 오른쪽 클릭을 할 때에 ListView에 Item이 선택되겠지요.


    이 정보가 ListView.SelectedItem에 남아있게 됩니다.


    메뉴가 뜰 때 까지도 선택된 아이템(Selected Item)의 정보가 제대로 남아 있습니다.


    하지만 메뉴에 왼쪽 클릭을 하는 순간 그 정보는 날아갑니다. 클릭이 다른 컨트롤에 이루어졌기 때문이죠.


    이를 어떻게 해결할까 고민하다 아래와 같은 코드를 이용했습니다.



    선택된 아이템(친구 정보)을 오른쪽 클릭 해 친구 신청과 친구 정보를 보는 코드입니다.


    //ListView MouseClick 이벤트 핸들러
    void lvRecommend_MouseClick(object sender, MouseEventArgs e)
            {
                //오른쪽 클릭일 경우
                if(e.Button.Equals(MouseButtons.Right))
                {   
                    //선택된 아이템의 Text를 저장해 놓습니다. 중요한 부분.
                    string selectedNickname = lvRecommend.GetItemAt(e.X, e.Y).Text;
    
                    //오른쪽 메뉴를 만듭니다
                    ContextMenu m = new ContextMenu();
    
                    //메뉴에 들어갈 아이템을 만듭니다
                    MenuItem m1 = new MenuItem();
                    MenuItem m2 = new MenuItem();
    
                    m1.Text = "검색하기";                
                    m2.Text = "친구신청하기";
    
    
                    //각 메뉴를 선택했을 때의 이벤트 핸들러를 작성합니다. 람다식을 이용해 작성하는것이 해법입니다.
                    //검색 넣어줌
                    m1.Click += (senders, es) =>
                        {
                            //외부 함수에 아까 선택했던 아이템의 정보를 넘겨줍니다.
                            friendFeedSearch(selectedNickname);
                        };
    
                    //친구신청. 친구신청하게되면 그 사람의 피드로 이동 후 친구신청한다
                    m2.Click += (senders, es) =>
                        {
                            friendFeedSearch(selectedNickname);
                            string strSql = "insert into USER_FRIENDS(MyNo, FriendNo) values(@myNo, @friendNo)";
                            SqlCommand cmd = new SqlCommand(strSql, conn);
                            cmd.Parameters.AddWithValue("@myNo", UserNo);
                            cmd.Parameters.AddWithValue("@friendNo", ViewNo);
                            cmd.ExecuteNonQuery();
    
                            if (btnAskFriends.Text == "친구신청")
                            {
                                btnAskFriends.Text = "요청취소";
                            }
                        };
    
                   //메뉴에 메뉴 아이템을 등록해줍니다
                    m.MenuItems.Add(m1);
                    m.MenuItems.Add(m2);
    
                    //현재 마우스가 위치한 장소에 메뉴를 띄워줍니다
                    m.Show(lvRecommend, new Point(e.X, e.Y));
                    
                    GetRecommendFriends();
                }
            }
    
    코드 전문을 올렸습니다. 그대로 쓰면 당연히 (-_-;) 안 됩니다.

    정말 친절한 주석은 아니지만서도 읽으면서 이해해보시기 바랍니다.


    맨 처음 GetItemAt으로 선택된 아이템을 가져오는 부분이 키 포인트.

    (ListView.SelectedItem 대신 이 방식을 썼습니다)


    또한 Contextmenu의 동적 추가와 MenuItem의 동적 추가를 중점으로 보시고


    전역 변수를 사용하지 않고 람다식을 이용해 이벤트 핸들러에 Sender와 E가 아닌 text 변수를 넘겨주는걸 

    잘 보시면 됩니다. 이 text변수는 응용하기에 따라 ListViewItem으로 바꿀 수 있겠죠.



Designed by Tistory.