[Windows Forms 응용 with C#] 2.4 ListView 실습

이번에는 ListView 사용 방법을 알아봅시다. 앞으로 다양한 컨트롤들의 사용 방법을 알아보지만 각각의 컨트롤의 사용법은 매우 다양하기 때문에 모든 것을 다룰 수는 없습니다. 실제 여러분들도 모든 컨트롤의 모든 기능을 익혀야 하는 것도 아닙니다. 필요하면 원하는 컨트롤을 찾고 이를 사용하는 방법을 익힐 수 있게 노하우를 쌓는 것이 중요합니다.

보다 자세한 사항은 MSDN 사이트를 참고하세요.(MSDN의 ListView)

ListView 컨트롤은 컬럼을 지정하여 ListView의 스키마를 정의할 수 있습니다. 그리고 서브 아이템들로 구성한 ListViewItem 개체를 항목에 추가할 수 있습니다. 여기에서는 회원의 ID, 이름, 나이로 구성한 ListView를 디자인 한 후 회원 추가 기능과 삭제, 수정, 검색 기능을 구현하면서 ListView의 필요한 기능을 사용해 봅시다.

[그림 2.7] 실행화면 및 컨트롤 배치

 다음은 Form1의 자식 컨트롤 Name 및 형식입니다.

NoName컨트롤 형식설명
1ch_idColumnHeader아이디 컬럼 헤더
2ch_nameColumnHeader이름 컬럼 헤더
3ch_ageColumnHeader나이 컬럼 헤더
4lv_memberListView회원 리스트 뷰
5tbox_idTextBox아이디 입력 텍스트 박스
6btn_addButton회원 추가 버튼
7tbox_nameTextBox이름 입력 텍스트 박스
8nud_ageNumericUdDown나이 입력 NumericUdDown
9btn_removeButton삭제 버튼
10btn_modifyButton수정 버튼
11tbox_id2TextBox검색 아이디 입력 텍스트 박스
12btn_searchButton검색 버튼

리스트 뷰 컨트롤은 폴더처럼 다양한 보기 모드가 있습니다. 여기에서는 Details를 선택합시다.

[그림 2.8] ListView View 모드 선택

 그리고 열 편집을 선택하여 ListView 스키마를 정의합시다.

[그림 2.9] 열편집 선택
[그림 2.10] 열편집

 추가 버튼 클릭 이벤트 핸들러를 등록하세요.

private void btn_add_Click(object sender, EventArgs e)
{

먼저 입력 컨트롤에 있는 값을 가져오기 합니다.

    string id = tbox_id.Text;
    string name = tbox_name.Text;
    decimal age = nud_age.Value;

ListViewItem 개체를 만드는 방법은 매우 다양합니다. 여기에서는 ListViewItem을 구성할 문자열 배열을 이자로 생성하기로 할게요.

    string[] strs = new string[]{id,name,age.ToString()};
    ListViewItem lvi = new ListViewItem(strs);

이와 같이 생성한 ListView의 Items 컬렉션에 추가합니다.

    lview_member.Items.Add(lvi);

그리고 입력 컨트롤의 내용을 지워줍시다.

    ClearInputControl();
}

입력 컨트롤의 내용을 지워주는 ClearInputControl 메서드에서는 초기값으로 설정합니다.

private void ClearInputControl()
{
    tbox_id.Text = string.Empty;
    tbox_name.Text = string.Empty;
    nud_age.Value = 0;
}

리스트 뷰의 선택 항목 변경 이벤트 핸들러를 등록합니다.

private void lview_member_SelectedIndexChanged(object sender, EventArgs e)
{

리스트 뷰는 여러 개의 항목을 선택할 수도 있습니다. 하나의 항목만 선택하게 하려면 리스트 뷰의 MultiSelect 속성을 false로 지정하세요.

먼저 선택 항목의 개수가 0보다 큰 지 확인합니다.

    bool selected = lview_member.SelectedItems.Count>0;

그리고 선택 항목의 개수가 0보다 큰 지 여부에 따라 삭제 버튼과 수정 버튼의 활성화 여부를 설정합니다.

    btn_remove.Enabled = btn_modify.Enabled = selected;

그리고 선택 항목이 없다면 입력 컨트롤 속성을 지워주고 이벤트 핸들러를 종료합니다.

    if (selected == false)
    {
        ClearInputControl();
        return;
    }

이제 리스트 뷰의 선택 항목 중에 인덱스 0에 있는 항목을 얻어옵니다.

    ListViewItem lvi = lview_member.SelectedItems[0];

그리고 얻어온 리스트 뷰 아이템의 SubItems 컬렉션에서 인덱스 연산을 통해 입력 컨트롤의 속성을 설정합니다.

    tbox_id.Text = lvi.SubItems[0].Text;
    tbox_name.Text = lvi.SubItems[1].Text;
    nud_age.Value = decimal.Parse(lvi.SubItems[2].Text);
}

삭제 버튼의 클릭 이벤트 핸들러를 등록합니다.

private void btn_remove_Click(object sender, EventArgs e)
{

먼저 선택 항목의 개수가 0보다 큰지 확인합니다.

    bool selected = lview_member.SelectedItems.Count > 0;
    if (selected == false)
    {

프로그램 논리 상 선택 항목이 없을 때 삭제 버튼은 비활성화 상태여야 하므로 이 부분에 도달하였다면 어딘가 버그가 있는 것입니다. 개발 단계에서 빠르게 인지하여 수정할 수 있게 예외를 던져줍시다.

        throw new ApplicationException(
                 "선택 항목이 없는데 삭제 요청하였습니다.");
    }

선택 항목을 얻어와 리스트 뷰의 Items 컬렉션에서 제거합니다.

    ListViewItem lvi = lview_member.SelectedItems[0];
    lview_member.Items.Remove(lvi);

그리고 입력 컨트롤의 속성을 지워줍니다.

    ClearInputControl();
}

수정 버튼의 클릭 이벤트 핸들러를 등록하세요.

private void btn_modify_Click(object sender, EventArgs e)
{

선택 항목이 없다면 예외를 던져줍니다.

    bool selected = lview_member.SelectedItems.Count > 0;
    if (selected == false)
    {
        throw new ApplicationException(
             "선택 항목이 없는데 수정 요청하였습니다.");
    }

선택 항목의 ListViewItem 개체를 가져옵니다.

   ListViewItem lvi = lview_member.SelectedItems[0];

그리고 입력 컨트롤의 속성 값으로 ListViewItem 개체의 SubItems 항목을 설정합니다. id는 변경하지 않습니다.

    string name = tbox_name.Text;
    decimal age = nud_age.Value;
    lvi.SubItems[1].Text = name;
    lvi.SubItems[2].Text = age.ToString();

마지막으로 입력 컨트롤의 정보를 지워줍니다.

    ClearInputControl();
}

검색 버튼의 클릭 이벤트 핸들러를 등록하세요.

private void tbox_search_Click(object sender, EventArgs e)
{

검색할 id를 얻어옵니다.

    string id = tbox_id2.Text;

ListView의 Items 컬렉션의 ListViewItem 개체마다 id 값과 일치하는지 확인합니다.

    foreach (ListViewItem lvi in lview_member.Items)
    {
        if (id == lvi.SubItems[0].Text)
        {

일치하면 이름과 나이 정보를 얻어와서 컨트롤의 속성을 변경하고 이벤트 핸들러를 종료합니다.

            tbox_id.Text = id;
            tbox_name.Text = lvi.SubItems[1].Text;
            nud_age.Value = decimal.Parse(lvi.SubItems[2].Text);
            return;
        }
    }
    MessageBox.Show("존재하지 않는 ID입니다.");
}

▷Form1.cs

using System;
using System.Windows.Forms;

namespace Ex_ListView
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void btn_add_Click(object sender, EventArgs e)
        {
            string id = tbox_id.Text;
            string name = tbox_name.Text;
            decimal age = nud_age.Value;

            string[] strs = new string[]{id,name,age.ToString()};
            ListViewItem lvi = new ListViewItem(strs);
            lvi.Text = id;
            lview_member.Items.Add(lvi);
            ClearInputControl();
        }
        private void ClearInputControl()
        {
            tbox_id.Text = string.Empty;
            tbox_name.Text = string.Empty;
            nud_age.Value = 0;
        }

        void lview_member_SelectedIndexChanged(object sender, EventArgs e)
        {
            bool selected = lview_member.SelectedItems.Count>0;
            btn_remove.Enabled = btn_modify.Enabled = selected;
            if (selected == false)
            {
                ClearInputControl();
                return;
            }
            ListViewItem lvi = lview_member.SelectedItems[0];
            tbox_id.Text = lvi.SubItems[0].Text;
            tbox_name.Text = lvi.SubItems[1].Text;
            nud_age.Value = decimal.Parse(lvi.SubItems[2].Text);
        }
        private void btn_remove_Click(object sender, EventArgs e)
        {
            bool selected = lview_member.SelectedItems.Count > 0;            
            if (selected == false)
            {
                throw new ApplicationException(
                       "선택 항목이 없는데 삭제 요청하였습니다.");
            }
            ListViewItem lvi = lview_member.SelectedItems[0];
            lview_member.Items.Remove(lvi);
            ClearInputControl();
        }

        private void btn_modify_Click(object sender, EventArgs e)
        {
            bool selected = lview_member.SelectedItems.Count > 0;
            if (selected == false)
            {
                throw new ApplicationException(
                         "선택 항목이 없는데 수정 요청하였습니다.");
            }
            ListViewItem lvi = lview_member.SelectedItems[0];
            string name = tbox_name.Text;
            decimal age = nud_age.Value;
            lvi.SubItems[1].Text = name;
            lvi.SubItems[2].Text = age.ToString();
            ClearInputControl();
        }
        private void tbox_search_Click(object sender, EventArgs e)
        {
            string id = tbox_id2.Text;
            foreach (ListViewItem lvi in lview_member.Items)
            {
                if (id == lvi.SubItems[0].Text)
                {
                    tbox_id.Text = id;
                    tbox_name.Text = lvi.SubItems[1].Text;
                    nud_age.Value = decimal.Parse(lvi.SubItems[2].Text);
                    return;
                }
            }
            MessageBox.Show("존재하지 않는 ID입니다.");
        }
    }
}