관리 메뉴

IT 쟁이

DataGrid컨트롤 -1 -출처 태요.net 본문

ASP.NET/서버컨트롤

DataGrid컨트롤 -1 -출처 태요.net

클라인STR 2008. 1. 16. 16:13

Taeyo's ASP.NET

   강좌 최초 작성일 : 2004년 12월 20일
   강좌 최종 수정일 : 2004년 08월 09일

   강좌 읽음 수 : 36168 회

   작성자 : Taeyo(김 태영)
   편집자 : Taeyo(김 태영)

   강좌 제목 : DataGrid Control (1)

강좌 전 태오의 잡담>

요즘 ASP.NET 2.0을 준비하다 보니, ASP.NET 1.x 시절의 DataGrid가 GridView라는 이름으로 업그레이드 되어 등장한다는 사실이 재미있더라구요. 그러면서, 느껴지는 것 하나는... DataGrid에 그다지 친숙하지 못했던 ASP.NET 개발자들은 조금 더 피곤하겠다... 라는 생각이 들었습니다.. 왜냐하면, 새로운 ASP.NET 2.0의 GridView는 그 사용방법이 기존의 DataGrid와 상당히 유사하기 때문이지요 ^^ 유사한데, 기능적으로 더 풍부합니다.

이 말은 기존 DataGrid에 친숙할 사용자일수록, 새로운 기술에 적응하는데 더 적은 시간이 든다는 것을 의미하는 것이기도 하겠죠? 해서, 강좌 올립니다.!!!! 정말 쉽게 풀어쓴 데이터 그리드 다루기~~~~ 히힛..

또한, 오늘은 제 생일이거든요. 그러니깐, 오늘만큼은 강좌가 별루라고 딴지걸기 없기~~~ 히힛


대상 : 기존 DataList 강좌를 진짜로 읽고, 공부하신 분~~
선수지식 : ADO.NET 기본 지식.

DataGrid 컨트롤

이번 시간에는 바인드 컨트롤의 최고봉인 DataGrid에 대해 이야기를 해 볼까 합니다. 단순히 태오 ASP.NET 책에서 이야기한 내용을 그대로 카피해 놓는 수준이 아니라, 그리드에 DropDownList 추가하기, 그리드 동적 변경 등등에 대한 이야기도 같이 진행해 볼까 해요. 그리드 컨트롤은 뛰어난 기능들을 보유하고 있어서(게다가 영리하기까지 합니다) 현장에서의 활용도가 상당히 높은 편이니까요.(^^ 알아두면 매우 유용한 컨트롤입니다. 심지어 다른 써드파티의 그리드를 사용할 경우에도 도움이 됩니다)

하지만, 그에 따라 사용법도 조금은 복잡한 편이긴 합니다.(배우고 나면 그리 어렵지 않지만 ^^) 이번 섹션에서는 이러한 그리드 컨트롤의 사용법에 대해서 하나씩 알아보도록 하겠습니다. 레포트나 표 형태의 출력에 있어서 그리드 컨트롤은 상당히 유용한 컨트롤이니 말이죠.

영리한 DataGrid : AutoGenerateColumns

먼저, 그리드 컨트롤이 왜 영리한 컨트롤인지를 먼저 알아보도록 해요. 예제로써 말이죠. 여러분의 프로젝트에 새로운 웹 폼을 하나 추가해 보도록 하세염. 페이지의 이름은 DataGridEx01.aspx 라고 주도록 하고, 생성된 웹 폼 위에 DataGrid 컨트롤을 드래그 앤 드롭으로 올려놓도록 하세요. 히힛~ 그러면, 컨트롤의 ID는 DataGrid1이라는 값으로 자동 부여될 것입니다.

이제 코드 비하인드 페이지로 이동하여 다음과 같이 Page_Load 이벤트 처리기를 작성해 보도록 해요. 코드는 이전 DataList 에서 사용했던 코드와 거의 동일하죠? 까먹으셨다구요? 강좌가 너무 오랜만에 올라와서??? ㅠㅠ 그런거군요... ㅜ_ㅠ

private void Page_Load(object sender, System.EventArgs e)
{
    if(!IsPostBack)
    BindData();
}

private void BindData()
{
    string connectStr = "Server=(local); database=Pubs; user id=sa";

    SqlConnection Con = new SqlConnection(connectStr);
    string strSql = "Select Top 5 title_id, title, price, pubdate, notes from titles";
    SqlDataAdapter Adap = new SqlDataAdapter(strSql, Con);

    DataSet ds = new DataSet();
    Adap.Fill(ds, "titles");

    DataGrid1.DataSource = ds.Tables["titles"];
    DataGrid1.DataBind();
}

오쨌든, 모두 작성하셨다면 이제 페이지를 컴파일하고 실행해 보도록 해요. 당연히 아무 것도 출력될 리가 없다고 생각하고 계실 것 같습니다만... (-_-+ 다들 알고 있는 눈치지만, 그래도 놀라는 척 해줌 글 쓰는 사람 힘남다~) 그렇죠???? 아무것도 출력되지 않겠죠??? 그럴 것 같죠??? (네~~~) 왜냐하면, 우리는 템플릿도 만들지 않았고, 출력될 스타일도 지정하지 않았으니 말이예요.

하지만!!!! 재미있게도 결과가 출력되는 것을 볼 수 있습니다. 쿠궁!! 어떻게 이럴 수가 있는 것인가? 놀랍지 않으세요?(네? 놀랍지 않아요 -_-;;) 그렇습니다. 여러분의 반응이 우째되었던 이는 실로 영리한 컨트롤인 것입니다. 진짜루 말입니다.

이는 DataGrid의 AutoGenerateColumns라는 기능인데요. 즉, 데이터 원본을 기반으로 하여 자동으로 기본적인 테이블(<table>)을 만들어내는 기능입니다. 이 기능은 DataGrid 만이 보유하고 있는 기능으로, 템플릿의 지정없이도 기본적인 출력물을 쉽게 만들어 낼 수 있게 하지요. 물론, 각각의 템플릿을 기존의 바운드 컨트롤들처럼 작성하여 출력할 수도 있습니다.

그렇다면, AutoGenerateColumns 기능 외에 DataGrid 컨트롤이 제공하는 기능들에는 어떠한 것들이 있는지 한번 알아볼까요?? 응응??? DataList에는 없었던 새로운 기능들이 눈에 조금 띄실 겁니다. 이들에 대해서도 곧 알아보도록 할께요~

속성 설명
AllowPaging 페이징을 허용할 것인지의 여부 지정
AllowSorting 정렬을 허용할 것인지의 여부 지정
AutoGenerateColumns 데이터 원본을 기반으로 하여 자동으로 데이터들을 출력할 것인지를 여부 (각각의 컬럼은 BoundColumn으로 생성된다)
BackImageUrl DataGrid 컨트롤의 배경에 표시할 이미지의 URL
CellPadding 셀 사이의 간격(pixels)
CellSpacing 셀과 셀 내의 컨텐트 와의 사이 간격(pixels)
DataKeyField 바인드된 데이터 원본에서 기본 키로 사용할 필드
DataSource 바인딩할 데이터 원본
GridLines 테두리의 출력 형태.
사용 가능한 값 : None | Horizontal | Vertical | Both
HorizontalAlign DataGrid 컨트롤의 가로 정렬 위치의 지정.
사용 가능한 값 : Center | Justify | Left | NotSet | Right
PageSize DataGrid 컨트롤의 단일 페이지에 표시할 행의 수
ShowFooter Footer를 보이게 할 지의 여부
ShowHeader Header를 보이게 할 지의 여부
VirtualItemCount 사용자 지정 페이징을 하는 경우, DataGrid 컨트롤에 있는 가상 행의 개수

이제, [자동 서식]을 사용하여 그리드의 출력 스타일을 조금 이쁘게 바꾸어 보도록 해요. 웹 폼 디자이너에 마우스 우측 클릭을 한 뒤, [자동 서식]을 클릭하고 맘에 드는 서식을 적용하시면 되는 것이랍니다. 저는 엘레강스하고 우주적으로~~~ [전문가 2]를 선택해 보았습니당.

이전 DataList 예제에서 해 보았던 것이니 그리 어렵지 않으실 거예요. 사실, 개인적으로는 [자동 서식] 툴을 즐기는 편은 아닙니다. 개인적으로 썩 맘에 드는 서식은 없기 때문이지요. 저의 인크레더블하고, 뷰리플하고, 우주적인 감각을 살려주는 드자인이 부족하여~~~

하지만, 출력 디자인을 심각하게 따져야 하는 상황이 아니라면 이 [자동 서식]은 유용한 편이 아닐 수 없슴다. 가벼운 리포트를 위해서라면 더더욱 말이죠. 다음 그림은 이러한 서식이 적용된 결과 화면입니당.

데이터 원본을 기반으로 자동으로 출력물을 만들어 내는 AutoGenerateColumns 기능을 사용하면 이처럼 쉽게 데이터를 출력해낼 수가 있어요. 얼마나 간단해요! 얼마나?? 100원? (-_-+++)

하지만, 언제나 편리한 기능은 그 만큼의 제약사항을 동반하는 법이죠? 예를 들면, AutoGenerateColumns 기능을 사용하는 방법은 출력되는 각각의 컬럼 데이터를 우리 마음대로 제어할 수 없다는 단점이 있어요. 즉, AutoGenerateColumns을 사용할 경우에는 자동으로 데이터 원본의 모든 컬럼을 출력하기에, 특정 컬럼을 출력하지 못하게 한다거나 할 수가 없다는 이야기이며, 선택의 여지가 없이 모든 컬럼들이 출력되어진다는 것입니다. (흑흑 ㅠㅠ)

그렇다면, 어떻게 그러한 부분을 해결할 수 있을까요? 데이터 원본에 존재하는 컬럼 중 우리가 원하는 컬럼들만을 출력하고자 한다면 말입니다. 해서, 이제부터 알아볼 내용은 우리가 직접 수동으로 출력 레이아웃을 작성하는 방법이 되겠습니다~~~ 짜잔~~

BoundColumn의 사용

DataGrid 컨트롤에 표시할 컬럼(열)을 직접 지정하려면 AutoGenerateColumns 속성을 false로 설정하고 표시할 컬럼의 목록을 <Columns> 태그와 </Columns> 태그 사이에 나열해야 한답니다. 지정된 컬럼은 나열된 순서에 따라 출력되며, 이렇게 하면 DataGrid 컨트롤의 컬럼을 프로그래밍 방식으로 제어할 수 있게 되어요. 재미있는 것은 여기에 사용할 수 있는 컬럼에는 여러 가지의 종류가 있다는 것입니다. 가장 대표적인 컬럼으로는 BoundColumn 컬럼이 있는데, 이는 데이터 원본 필드에 바인딩되며, 지정된 스타일을 사용하여 출력 테이블의 셀에 렌더링되는 컬럼을 만듭니다. 말이 조금 어렵게 느껴진다면 직접 예제를 통해서 익혀보도록 해요~ 언제나 그게 가장 이해하기 쉬운 방법이니까요

프로젝트에 새로운 웹 폼을 하나 추가하고, 페이지의 이름을 DataGridEx02.aspx로 주도록 하세요. 반드시 이름을 저랑 똑같이 주셔야 하는 것은 아니지만.... 아시죠??? ^^ 기왕이면~~ 웹 폼 위에는 DataGrid 컨트롤을 하나 올리고, 그 컨트롤의 [자동 서식]에서 이번에는 그림과 같이 [단순 3]을 지정해 보도록 하겠습니다. (서식의 지정도 여러분의 취향이겠지만 일단은 같이 해 보자구요)

[확인] 버튼을 누르고, 웹 폼 디자이너로 돌아와서 HTML 모드로 전환하여, 이제 DataGrid의 코드를 다음과 같이 변경해 보도록 하세요. 이번 예제에서는 AutoGenerateColumns 기능을 사용하지 않을 것이며, 우리가 출력하고자 하는 모든 컬럼을 직접 코드로써 작성할 것입니다. 아래의 코드 중에서 파란 색으로 강조된 부분이 코드에서 변경해야 할 부분이니 유심히 봐 주세요.

<asp:DataGrid id="DataGrid1" runat="server" AutoGenerateColumns="False"
        BorderColor="#336666" BorderStyle="Double" BorderWidth="3px" BackColor="White"
        CellPadding="4" GridLines="Horizontal">

    <SelectedItemStyle Font-Bold="True" ForeColor="White" BackColor="#339966">
        </SelectedItemStyle>
    <ItemStyle ForeColor="#333333" BackColor="White"></ItemStyle>
    <HeaderStyle Font-Bold="True" ForeColor="White" BackColor="#336666">
        </HeaderStyle>
    <FooterStyle ForeColor="#333333" BackColor="White"></FooterStyle>
    <Columns>
        <asp:BoundColumn DataField="title_id" HeaderText="ID"></asp:BoundColumn>
        <asp:BoundColumn DataField="title" HeaderText="제목"></asp:BoundColumn>
        <asp:BoundColumn DataField="price" HeaderText="가격"
            DataFormatString="{0:N2}"></asp:BoundColumn>
        <asp:BoundColumn DataField="pubdate" HeaderText="출간일"
            DataFormatString="{0:yyyy-MM-dd hh:mm}"></asp:BoundColumn>
    </Columns>

    <PagerStyle HorizontalAlign="Center" ForeColor="White" BackColor="#336666"
        Mode="NumericPages"></PagerStyle>
</asp:DataGrid>

AutoGenerateColumns의 값을 "false"로 지정하게 되면, DataGrid는 데이터를 자동 바인드하지 않습니다. 이렇게 설정한 경우에는 여러분이 직접 코드로써 출력할 컬럼을 작성해 주어야 하죠. 기존의 DataList 컨트롤은 이를 위해서 템플릿을 사용했지만, DataGrid는 <asp:BoundColumn>이라는 특별한 컬럼을 사용해요. 그렇다고, 템플릿을 사용할 수 없는 것은 물론 아니죠. 템플릿을 사용하는 방법은 잠시 후 살펴보겠습니다.

DataGrid 내부에 출력할 컬럼들은 <Columns>라는 구역 안에 작성해 주어야 한다는 점에 주의해 주세요. 코드에서는 <asp:BoundColumn>을 사용하여 각각의 컬럼을 지정하고 있는데요. 이 타입의 컬럼은 지정된 데이터 원본 컬럼을 바인드하여 출력하는 역할을 하는 DataGrid 컨트롤의 기본 컬럼 타입입니다. 이 컬럼 형식 외에도 TemplateColumn, ButtonColumn, HyperLinkColumn, EditCommandColumn와 같은 컬럼 타입들을 사용할 수 있는데, 이들에 대해서도 이후 각각 알아볼 예정입니다. 지금은 가장 기본적인 컬럼 형식인 BoundColumn에만 주목해보려 해요~

다음은 DataGrid 컨트롤이 지원하는 모든 컬럼 형식들이 제공하는 속성 목록이 되겠습니다.

속성 설명
FooterText 컬럼의 하단(꼬리말)에 나타낼 텍스트
HeaderText 컬럼의 상단(머리말)에 나타낼 텍스트
HeaderImageUrl 컬럼의 상단(머리말)에 텍스트 대신 나타낼 이미지의 URL
SortExpression 사용자가 컬럼을 기준으로 정렬할 경우, 정렬에 사용할 필드의 이름
Visible 컬럼을 나타낼 것인지 숨길 것인지의 여부 (여기서 숨긴다는 의미는 결과 화면에 출력은 하되, 보이지 않게 한다는 의미가 아니다. 아예 출력을 하지 않는다는 것을 의미한다)

그리고, 다음 목록은 BoundColumn이 지원하는 속성들의 목록입니다.

속성 설명
DataField 컬럼에 바인드 할 데이터 원본(DataSource)의 특정 컬럼 명
DataFormatString 출력될 값의 포맷 문자열
ReadOnly 행이 편집 모드가 될 경우, 컬럼을 편집 가능하게 할 것인지, 편집 불가능하게 할 것인지의 여부

위의 표를 기반으로 다시금 예제의 코드에서 Columns 구역을 살펴보면, 첫 번째 BoundColumn은 바인드할 컬럼으로 title_id를 주고 있으며, 그 컬럼의 머리말로는 "ID" 값을 주고 있어요. 그리고, 두 번째 BoundColumn은 바인드할 컬럼으로 title을 지정하고 있으며, 컬럼의 머리말로는 "제목"을 주고 있지요. 세 번째와 네 번째 BoundColumn은 책의 가격과 출간일을 나타내도록 지정하고 있으며, 이 들의 경우는 DataFormatString 속성을 지정하여 출력하는 텍스트의 포맷도 설정하고 있습니다. 다음과 같이 말이죠~

<asp:BoundColumn DataField="title_id" HeaderText="ID"></asp:BoundColumn> <asp:BoundColumn DataField="title" HeaderText="제목"></asp:BoundColumn> <asp:BoundColumn DataField="price" HeaderText="가격" DataFormatString="{0:N2}"> </asp:BoundColumn> <asp:BoundColumn DataField="pubdate" HeaderText="출간일" DataFormatString="{0:yyyy-MM-dd hh:mm}"></asp:BoundColumn>

대략적인 출력 결과가 예상되세요? 그렇다면, 이제 페이지를 컴파일하고 실행해 보도록 해요. 물론, 여러분은 페이지를 실행하기 전에 코드 비하인드 페이지에 Page_Load 이벤트 처리기를 작성해 주어야 할 것입니다. 이전 예제인 DataGridEx01.aspx에서 사용했던 것과 동일한 코드를 말이죠. 제대로 작성되었다면 실행 시 여러분은 다음과 같은 결과를 볼 수 있을 것입니당당당.

호오, 깜찍하지 않나요? BoundColumn을 사용하면 데이터 바인딩 표현식을 사용하지 않고도 간단하게 데이터를 바인딩할 수 있어요. 그리고, 그 결과는 AutoGenerateColumns 기능을 사용했을 경우와 유사하죠. 비록, 출력할 컬럼들을 직접 코드로 작성해야 하지만, 이를 이용하면 데이터 원본에 존재하는 데이터 중 원하는 컬럼만을 출력할 수 있습니다. 사실, BoundColumn의 기능은 단지 이 정도의 수준이 아니예요. 각각의 행이 편집 모드로 들어갈 경우, BoundColumn로 작성된 컬럼들은 편집이 가능한 형태(예를 들면, TextBox)로 자동 전환 되기까지 하거든요~~~

현재까지는 일단 좋습니다. 좋아요~~ 그렇다면, 이제 그러한 내용을 테스트 해보도록 하자구요. 그런데, 그러한 테스트가 가능하려면 그리드 컨트롤내 각 행에 대해 버튼 컨트롤이 필요할 것입니다. 어떤 행을 선택 혹은 편집할 것인지를 서버에 알릴 수 있어야 할 테니 말이죠. 이전 DataList의 경우에는 템플릿에 그러한 버튼 컨트롤을 직접 추가하였던 것을 기억하세요? 기억이 나지 않는다면 돌아가서 확인해 보고 오시기 바랍니다. 허걱... 귀찮다구요??? -_-++ 그럼 안되는데...

어쨌든 말입니다. DataGrid에서도 DataList와 마찬가지로 템플릿을 이용하여 그러한 기능을 추가할 수 있어요. 하지만, 단지 버튼 컨트롤을 추가하기 위해서라면, DataGrid는 더 쉽고 편한 방법도 자체 제공하고 있죠. 그것도 각각의 기능에 따라서 말입니다. 행의 선택 혹은 삭제를 목적할 경우에 사용할 수 있는 ButtonColumn과 행을 편집, 업데이트, 취소하려는 경우 사용할 수 있는 EditCommandColumn이 바로 그것이옵니다. 그렇다면, 하나씩 한번 알아보도록 해요. 행의 선택 혹은 삭제를 위해 사용할 수 있는 ButtonColumn 컬럼 형식을 시작으로 해서 말입니다~

ButtonColumn 사용하기

ButtonColumn은 코드상에서 <asp:ButtonColumn>이라고 작성하며, 컬럼의 각 행에 대해 [추가] 또는 [삭제]를 목적으로 하는 버튼 서버 컨트롤을 추가할 수 있게 합니다. 이는 각각의 출력된 행에 대해 어떤 명령을 내리고 싶을 경우 사용하며, 지정된 컬럼에 대해 동일한 형태의 버튼 컨트롤을 출력하게 됩니다. 또한, 버튼 컨트롤로는 링크버튼도 사용이 가능하기에 출력 형태를 하이퍼링크 형태로 나타나게 할 수도 있어요. 역시 천 마디 말 보다는 하나의 적절한 예제가 짱이죠??? 좋습니다. 그렇다면, 현재의 예제에 ButtonColumn을 다음과 같이 추가해 보도록 해요.

<Columns>
    <asp:BoundColumn DataField="title_id" HeaderText="ID"></asp:BoundColumn>
    <asp:BoundColumn DataField="title" HeaderText="제목"></asp:BoundColumn>
    <asp:BoundColumn DataField="price" HeaderText="가격" DataFormatString="{0:N2}">
        </asp:BoundColumn>
    <asp:BoundColumn DataField="pubdate" HeaderText="출간일"
        DataFormatString="{0:yyyy-MM-dd hh:mm}"></asp:BoundColumn>
    <asp:ButtonColumn HeaderText="선택" ButtonType="PushButton" CommandName="Sel"
        Text=" S "></asp:ButtonColumn>

</Columns>

일단, 결과를 먼저 확인해 볼까요? 여러분이 예상하는 대로 결과가 나오고 있나요???

그렇습니다. 결과로서 버튼 컨트롤을 갖는 컬럼이 하나 추가되었네요. 물론, 아직까지는 각각의 버튼을 클릭해도 아무런 일도 일어나지 않을 것이지만 말입니다 (단지, 포스트백만이 일어날 겁니다) 여기서 중요한 것은 버튼을 갖는 컬럼을 그리드 컨트롤에 추가할 수 있다는 것입니다. 그것이 바로 ButtonColumn의 역할이니까요. 그렇다면, 이제 ButtonColumn이 갖는 속성들을 한번 살펴보도록 할까요?

속성 설명
ButtonType 렌더링할 버튼의 형식. 기본 값은 LinkButton 이다.
사용할 수 있는 값 : LinkButton|PushButton
* 프로그래밍에서는 ButtonColumnType 열거형을 사용하여 이 값을 변경할 수 있다.
CommandName 버튼을 클릭했을 때 전송되는 명령 문자열. 이 문자열은 해당 이벤트 처리기로 넘어오는 e 이벤트 인자를 통해서 얻어올 수 있다.
DataTextField 버튼의 Text에 출력(바인드)될 데이터 원본(DataSource)의 특정 컬럼 명
DataTextFormatString 버튼의 Text에 출력될 값의 포맷 문자열
Text 버튼의 Text에 일괄적으로 출력할 텍스트. DataTextField 속성이 설정되면 이 값은 무시된다.

ButtonColumn에 의해 생성되는 버튼의 역할은 이전 DataList 예제에서 템플릿에 버튼을 올려놓았을 경우와 동일하게 동작합니다. 각각의 버튼은 클릭 시 ItemCommand 이벤트를 호출하며, 여러분은 버튼이 가지고 있는 CommandName을 통해서 해당 버튼에 대한 처리를 할 수 있게 되는거죠.

주의 : ButtonColumn은 CommandArgument 속성은 제공하지 않습니다.

현재는 버튼을 클릭해도 아무런 일도 발생하지 않지만, 원한다면 DataGrid의 ItemCommand 이벤트 내에 필요한 코드를 작성해서 원하는 처리를 수행할 수도 있답니다. 예를 들면, 특정 행의 버튼이 클릭되는 경우, 그 행을 선택된 행으로 표시하거나 할 수 있다는 것이죠. 전에 DataList 예제에서 해 보았던 것처럼 말입니다.

좋아요. 그렇다면, 한번 해보도록 하자구요. 먼저, 웹 폼 디자이너에서 DataGrid 컨트롤을 선택하고, [속성 창]에서 번개 모양의 버튼을 클릭한 뒤 그림과 같이 ItemCommand 이벤트 처리기 구역을 더블 클릭해 보세요.

그러면, 코드 비하인드 페이지에 자동으로 DataGrid1_ItemCommand 이벤트 처리기가 추가되죠? 그 곳에 다음과 같이 코딩하면 됩니다. DataList 예제를 이미 수행한 여러분이라면 이러한 작업이 전혀 낯설지 않을 것입니다. (기존 예제를 안하신 분은 과연???? ^__^;;)

private void DataGrid1_ItemCommand(object source,
        System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
    if(e.CommandName == "Sel")
    {
        DataGrid1.SelectedIndex = e.Item.ItemIndex;
        BindData();
    }
}

이미 알고 계시겠지만, ItemCommand 이벤트는 그리드 컨트롤 내에서 버튼 컨트롤이 클릭될 경우 (정확히는 어떤 컨트롤이든지 이벤트를 발생시킬 경우)는 언제든지 발생하는 이벤트입니다. 버튼의 CommandName이 무엇이던지 간에 말이죠. 그러므로, 이후에 추가할 [편집], [업데이트]와 같은 다른 종류의 버튼이 클릭될 경우에도 ItemCommand 이벤트는 동작할 것이기에, 그러한 경우에는 위의 처리(행을 선택하는 코드)를 거치지 않도록 하기 위해서 if 문을 사용해 보았어요. 이미 DataList 예제에서 동일한 예제를 해 보았으니 이해하기에 어렵지는 않을 것 같네요.

이제, 페이지를 컴파일하고 실행해 볼까요? 그리고, 마음껏 버튼을 클릭해 보세요. 버튼이 클릭된 행의 배경색이 지정된 스타일로 변하는 것을 볼 수 있을 것입니다.

여러분이 앞서 배운 지식들은 이렇듯 그리드 컨트롤에서 재 사용이 가능합니다. 어떤가요. 멋지지 않은가요? 여러분의 기존 노력이 결코 헛되지 않았음을 느낄 수 있을 것입니다. 음핫핫~

재미있는 팁

ButtonColumn의 CommandName을 "Select"라고 지정한다면, ItemCommand 이벤트 처리기를 작성하지 않아도, 버튼을 클릭한 항목이 선택된 것으로 표시된답니다. 어떠한 이벤트 처리 코드를 작성하지 않아도 자동으로 그렇게 된다는 것이죠. 이해를 돕기 위해서, 현재 작성된 ItemCommand 처리기 내부의 코드를 모두 주석 처리하고, ButtonColumn을 다음과 같이 변경한 뒤 실행해 보시기 바랍니다.

<asp:ButtonColumn HeaderText="선택" ButtonType="PushButton" CommandName="Select" Text=" S "></asp:ButtonColumn>

노파심(?)에 이야기 드리자면, 그리드에 버튼 컨트롤을 올린다거나, 데이터를 바인드 한다거나 하는 작업들을 템플릿을 사용해서도 이룰 수 있어요. 아직, 구체적으로 DataGrid에서 템플릿을 사용하는 방법에 대해서는 이야기하지 않았지만 말입니다. 그렇다면, 모든 것이 템플릿을 사용하여 가능한데, 왜 이러한 컬럼 형식(ButtonColumn)이 필요한 것일까요? 나중에 보시면 알겠지만(DataList를 경험해 본 여러분이라면 또한 이미 어느 정도 예측하고 있겠지만) 템플릿을 사용하는 방법은 많은 하드 코딩을 요구하거든요.

해서, 자주 사용하는 기능들에 대해서는 DataGrid가 이렇듯 별도의 컬럼 형식으로 제공하고 있는 것입니다. 나중에(아마도 다음 강좌에서) 지금 작성한 것들을 모두 템플릿을 이용하는 방식으로 바꾸어 볼 텐데요. 그 때가 되면 여러분은 나름대로의 규칙을 세울 수 있을 것입니다. 어떤 경우에 어떤 컬럼 형식을 이용하는 것이 유익한지에 대해서 말이죠~

그렇다면, 기대해 보시지요. 다음 강좌를 말입니다.. 하하핫~~ (과연 기대해줄 것인가?? -_-+)


EditCommandColumn 사용하기

EditCommandColumn은 각 행의 데이터 항목들을 편집하기 위한 [편집], [업데이트], [취소] 명령 버튼을 내장하고 있는 DataGrid 컨트롤의 특수한 컬럼 형식입니다. 이러한 버튼들을 사용하여 여러분은 쉽게 DataGrid 컨트롤의 컬럼 값들을 편집할 수 있게 되죠. DataList의 경우 일일이 템플릿으로 작성해야 했던 부분을 EditCommandColumn이 모두 해결해 준다는 것이랍니다. 개발자인 여러분이 해야할 일은 단지 각각의 버튼이 눌렸을 경우, 어떤 처리를 해야할 지를 정의하는 것 뿐입니다.

기본적으로 EditCommandColumn은 출력 시 DataGrid 컨트롤의 각 데이터 행에 대해 [편집(Edit)] 버튼을 출력하며, 그 버튼이 클릭될 경우 EditCommand 이벤트가 발생되고, [편집] 버튼은 [업데이트(Update)] 및 [취소(Cancel)] 버튼으로 바뀌게 되어요. 업데이트(Update) 버튼이 클릭될 경우는 UpdateCommand 이벤트가 발생하며, 취소(Cancel) 버튼이 클릭될 경우는 CancelCommand 이벤트가 발생하구요.

물론, 각각의 버튼 컨트롤들은 자신의 이벤트를 호출하기 이전에, 절대로 피해갈 수 없는 ItemCommand 이벤트도 거치게 됩니다. (이러한 부분은 DataList와 완전하게 동일하죠)

EditCommandColumn은 여러 가지 속성들을 가지고 있는데, 여러분은 그 중 최소한 CancelText, EditText, UpdateText 속성에 대한 지정은 반드시 해야만 해요. 그래야 [편집], [업데이트], [취소] 버튼이 제대로 출력되어지기 때문이지요. 우선 예제를 접해보고 이야기를 계속 진행해 보도록 해요.

기존의 웹 폼에 EditCommandColumn을 추가 작성해 주세요. 다음과 같이요.

<Columns>
    <asp:BoundColumn DataField="title_id" HeaderText="ID"></asp:BoundColumn>
    <asp:BoundColumn DataField="title" HeaderText="제목"></asp:BoundColumn>
    <asp:BoundColumn DataField="price" HeaderText="가격" DataFormatString="{0:N2}">
        </asp:BoundColumn>
    <asp:BoundColumn DataField="pubdate" HeaderText="출간일"
        DataFormatString="{0:yyyy-MM-dd hh:mm}"></asp:BoundColumn>
    <asp:ButtonColumn HeaderText="선택" ButtonType="PushButton" CommandName="Sel"
        Text=" S "></asp:ButtonColumn>
    <asp:EditCommandColumn ButtonType="PushButton" EditText="편집" CancelText="취소"
        UpdateText="업데이트"></asp:EditCommandColumn>
</Columns>

결과를 먼저 확인해 보고 이야기를 진행할까요??? 페이지를 실행하면 다음과 같은 결과를 볼 수 있으실 겁니다.

그리고, 다음의 표는 EditCommandColumn이 제공하는 속성들을 정리한 표예요.

속성 설명
ButtonType 렌더링할 버튼의 형식. 기본 값은 LinkButton 이다.
사용할 수 있는 값 : LinkButton | PushButton
EditText [편집] 버튼에 나타낼 텍스트
UpdateText [업데이트] 버튼에 나타낼 텍스트
CancelText [취소] 버튼에 나타낼 텍스트

EditCommandColumn을 추가한 결과로 [편집] 버튼을 갖는 새로운 컬럼이 추가된 것을 볼 수 있으실 겁니다. 이 버튼을 누르면 어떤 일이 생길지 기대가 되지 않으세요?? 그렇다면, 꾸욱 한번 눌러보세요.

어랏? 아무런 일도 생기지 않는닷!!! 무엇이 문제인거냐? 때오!!!!!

그렇습니다. [편집] 버튼이 눌릴 경우 발생하는 EditCommand 이벤트에 아직 아무런 처리도 하지 않았기에 그러한 것입니다. ASP.NET이 여러분의 생각을 인공지능적으로 파악해서 알아서 원하는대로 동작해주지는 않아요~ 개발자가 어떻게 동작하라고 코드로써 명령을 하지 않으면 말이죠~~ ^^;;

그렇다면, 그 부분을 추가해 보도록 할까요?

웹 폼 디자이너에서 DataGrid 컨트롤을 선택하고, [속성 창]에서 번개 모양의 버튼을 클릭한 다음, 다음과 같이 EditCommand 이벤트 구역을 더블 클릭하세요.

그러면, 코드 비하인드 구역에 자동으로 DataGrid1_EditCommand 이벤트 처리기가 생성될 것입니다. (이젠 다 아시죠?) 그 구역에 다음과 같은 코드를 작성해 주세요.

private void DataGrid1_EditCommand(object source,
    System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
    DataGrid1.SelectedIndex = -1;
    DataGrid1.EditItemIndex = e.Item.ItemIndex;
    BindData();
}

코드는 단순합니다. 단지, 현재 버튼이 클릭된 행의 선택 모드를 해제한 다음, 편집 모드로 설정하고 다시금 데이터 바인딩을 하는 것이 전부이지요. 코드만으로 따지면 DataList의 것과 사실 동일합니다.

이제 결과를 다시금 확인해 Voa요. 페이지를 실행하고 다시금 [편집] 버튼을 눌러보면 놀랍게도(!!) 다음과 같이 행 자체가 편집 모드로 변경되어져 나오는 것을 볼 수 있습니다. 그리고, [편집] 버튼 대신 [업데이트]와 [취소] 버튼이 나타나 있는 것도 확인할 수 있구요. 호오~~

DataGrid 컨트롤은 특정 표준 명령도 가지고 있습니다. 이러한 명령에는 Select, Sort, Update, Cancel, Edit, Delete가 있는데요. 버튼의 CommandName으로 이러한 명령들을 지정하면, 관련 Command 이벤트가 자동으로 발생하게 된답니다.

편집 모드로 바뀌어 나타나는 이러한 모습이 기능적으로는 놀랍지만, 사실 솔직하게 이야기하면, 저의 미적 감각 수준을 만족시켜 주지는 못하는 것 같습니다. 오우~~ 엘레강쓰하지 못한~~~

출력된 TextBox의 두꺼운 테두리하며, 짧은 너비 등등이 특히나 말입니다. 하지만, 어쨌든 놀랍습니다. [편집] 버튼 대신 [업데이트]와 [취소] 버튼이 나타나는 것은 이전의 설명으로 예상했던 것이지만, 현재 행의 모든 컬럼이 TextBox로 대체되어 편집이 가능하게 나타난다는 사실은 정말로 의외가 아닐 수 없죠?? 그렇습니다. DataGrid가 대단히 영리하다는 것을 다시 한번 느낄 수 있는 대목이 아닌가 싶습니다.

사실, 이 영리함의 비밀은 TextBox로 나타난 각각의 컬럼들이 BoundColumn이라는 것에 있습니다. BoundColumn은 내부적으로 이러한 기능을 내포하고 있는 컬럼 형식인 것이죠. 하지만, 그 기능을 자체 내포하고 있다보니, 그 출력 형태를 개발자가 변경할 수가 없다는 단점도 있어요. 예를 들면, 현재 출력된 TextBox들의 너비를 조절할 수 있었으면 하는 생각들을 할 텐데, 그 너비를 늘릴 방법이 BoundColumn을 사용할 경우에는 전혀 없다는 것이죠.

BoundColumn은 이처럼 자동 데이터 바인딩, 자동 편집 모드 전환 등의 편리함을 제공하지만, 그러한 편리함을 주는 대신 각각의 출력 형태를 우리가 구체적으로 제어할 수 없다는 단점이 있습니다. 만일, 이러한 부분을 여러분이 제어하고 싶다면 방법은 하나죠. 그 방법은 누누이 언급했듯이 직접 템플릿을 작성하여 여러분이 원하는 형태로 꾸미는 것입니다. 하지만, 굳이 그렇게까지 할 필요가 없는 경우라면 즉, 지금 출력되는 형태만으로도 충분한 상황이라면 BoundColumn은 대단히 유용합니다. 적은 코드로 많은 기능을 사용할 수 있으니 말이죠.

이제, [업데이트] 버튼이 눌릴 경우에 실제로 데이터를 서버에 반영하는 부분을 구현해 보아야 할 것 같네요. 하지만, 그 전에 한, 두 가지 정도 이야기해야 할 것이 있어요.

일단, 현재 편집 모드를 자세히 보면, titles 테이블의 키 컬럼인 title_id 컬럼도 수정이 가능한 것을 볼 수 있을 것입니다. 이 컬럼은 수정이 되어서는 안 되는 컬럼입니다. 키 컬럼은 주민등록번호와 같은 컬럼, 즉, 절대로 변경되어서는 안 되는 컬럼이기 때문이지요. 그럼에도 불구하고 현재 title_id를 나타내는 컬럼도 편집이 가능하게 TextBox로 나타나고 있어어어~~요~~. 이래서는 안 되지 않겠습니까???

즉, 이 부분은 [편집] 모드라 할지라도, 그냥 일반 텍스트로 나타내는 것이 보다 낫지 않을까요?

그렇습니다. 그런 방법도 BoundColumn은 속성으로 이미 제공해 주고 있다는 것입니다. 이전 BoundColumn의 속성 표를 다시금 살펴보세요. 속성 중에 ReadOnly 라는 것이 존재하고 있는 것을 보실 수 있죠?? 바로 이 기능이 행이 편집 모드로 전환될 경우, 컬럼을 편집 가능하게 할 것인지, 편집 불가능하게 할 것인지의 여부를 지정하는 속성인 것입니다. 그렇다면, title_id를 나타내는 BoundColumn의 ReadOnly 속성을 True로 지정하면 이 문제가 해결되지 않을까요? 정말??? 한번 해보죠~~


<Columns>
    <asp:BoundColumn DataField="title_id" HeaderText="ID" ReadOnly="True">
        </asp:BoundColumn>

    <asp:BoundColumn DataField="title" HeaderText="제목"></asp:BoundColumn>
… 중략 …

이렇게 바꾸고 페이지를 다시금 실행해 보세요. 우리의 기대대로 결과는 출력될 것입니다.

호오,... 쓸만해 보이십니까??? 하하하... 그렇다면, 이제는 실제적인 업데이트 작업 쪽으로 들어가 보도록 할까여??
언제??? 아시면서~~~~~ 그것은~ 다음 시간에... 히힛... 투비 꼰티뉴~~~

Comments