ASP.NET 3.5의 새로운 컨트롤 ListView를 사용해보자.

2008. 3. 10. 14:51 IT 및 개발/ASP.NET & AJAX

Visual Studio 2008의 발표와 함께 ASP.NET 3.5도 정식 발표가 되었습니다.
ASP.NET 3.5로 버전이 변경되면서 2.0과의 차이점은 많이 있지는 않습니다만
그래도 아주 유용한 컨트롤이 추가가 되었습니다.
ListView라는 컨트롤 인데요. 제가 보기엔 GridView와 DataList의 장점을 빼내어
만들어진 컨트롤 같습니다. 그동안 참으로 아쉬웠던 부분이였는데...
이번에 이렇게 추가가 되어서 참으로 기쁩니다.
그럼 ListView의 설명과 사용법에 대해서 알아보도록 하겠습니다.

ListView 설명

아래 설명은 MSDN의 ListView 클래스의 설명을 사용하였습니다.
그동안 GridView를 사용하셨던 분들이라면 더욱 쉽게 접근을 하실수 있을 것입니다.
(GridView  예제 참고 : 게시판 목록을 보여주는 GridView 예제)

템플릿 형식 설명
LayoutTemplate LayoutTemplate 속성을 사용하여 ListView 컨트롤의 루트 컨테이너에 대한 사용자 지정 UI(사용자 인터페이스)를 정의할 수 있습니다. LayoutTemplate 템플릿은 ListView 컨트롤의 필수 요소입니다.

LayoutTemplate 내용에는 ItemTemplate 템플릿에 정의된 항목이나 GroupTemplate 템플릿에 정의된 그룹에 대한 테이블 행(tr) 요소 같은 자리 표시자 컨트롤이 들어 있어야 합니다. 이 자리 표시자 컨트롤의 runat 특성은 "server"로 설정되어 있어야 하고 ID 특성은 ListView 컨트롤이 그룹을 사용하고 있는지 여부에 따라 ItemPlaceholderID 또는 GroupPlaceholderID 속성의 값으로 설정되어 있어야 합니다.
ItemTemplate ItemTemplate 속성을 사용하여 데이터 항목을 표시하기 위한 사용자 지정 UI(사용자 인터페이스)를 정의할 수 있습니다. ItemTemplate 템플릿은 ListView 컨트롤의 필수 요소입니다. 이 템플릿에는 일반적으로 레코드의 필드 값을 표시하기 위한 컨트롤이 들어 있습니다. 사용자가 데이터를 수정할 수 있도록 하기 위해 일반적으로 레코드를 선택하거나, 편집 모드로 전환하거나, 레코드를 삭제할 수 있는 단추도 ItemTemplate 템플릿에 추가합니다.

컨트롤에 바인딩된 데이터 소스의 필드 값을 표시하려면 데이터 바인딩 식을 사용합니다. 자세한 내용은 데이터 바인딩 식 구문을 참조하십시오.

기본 제공 선택, 삭제 및 편집 작업을 수행하는 단추를 만들려면 단추 컨트롤을 템플릿에 추가합니다. 컨트롤의 CommandName 속성을 다음 표에 있는 값 중 하나로 설정합니다.
단추 종류 CommandName 값
삭제 "Delete"
편집 "Edit"
선택 "Select"
ItemSeparatorTemplate ItemSeparatorTemplate 속성을 사용하여 ListView 컨트롤의 단일 항목 사이에 있는 구분 기호의 내용을 정의할 수 있습니다. ItemSeparatorTemplate은 마지막 항목을 제외하고 모든 항목 뒤에 표시됩니다.
GroupTemplate GroupTemplate 속성을 사용하여 ListView에 바둑판식 레이아웃을 만들 수 있습니다. 바둑판식 테이블 레이아웃에서는 항목이 한 행에서 가로 방향으로 반복됩니다. 항목의 반복 횟수는 GroupItemCount 속성에 의해 지정됩니다.

GroupTemplate 속성에는 테이블 셀(td), div 또는 span 요소 같은 데이터 항목에 대한 자리 표시자가 들어 있어야 합니다. 이 자리 표시자의 runat 특성은 "server"로 설정되어 있어야 하고 ID 특성은 ItemPlaceholderID 속성의 값으로 설정되어 있어야 합니다. 런타임에 ListView 컨트롤은 자리 표시자를 ItemTemplate 및 AlternatingItemTemplate 템플릿의 각 항목에 대해 정의된 내용으로 바꿉니다.
GroupSeparatorTemplate 구분 기호를 사용하여 각 그룹 사이에 사용자 지정 내용이 들어 있는 요소를 넣을 수 있습니다. 그런 다음 ListView 컨트롤에서 GroupTemplate 내용과 GroupSeparatorTemplate 내용을 교대로 렌더링합니다. GroupTemplate 내용은 항상 마지막에 렌더링됩니다.

ListView 컨트롤은 LayoutTemplate 템플릿 내에서 GroupSeparatorTemplate 내용을 렌더링하므로 GroupSeparatorTemplate 템플릿의 전체 행에 대한 내용을 정의해야 합니다. 예를 들어 ListView 컨트롤에서 테이블 행(tr) 요소를 사용하여 그룹을 만들 수 있습니다. GroupItemCount 속성이 3으로 설정된 경우 GroupSeparatorTemplate 템플릿의 colspan 특성을 3으로 설정해야 합니다.
EmptyItemTemplate 현재 페이지의 마지막 그룹에 표시할 데이터 항목이 더 이상 없으면 ListView 컨트롤에 빈 항목이 표시됩니다. GroupItemCount가 1보다 큰 값으로 설정된 경우에만 이러한 상황이 발생할 수 있습니다. 예를 들어, ListView 컨트롤에서 GroupItemCount 속성이 5로 설정되어 있고 데이터 소스에서 반환된 전체 항목 수가 8개인 경우 마지막 데이터 행에는 ItemTemplate 템플릿에 정의된 3개의 항목과 EmptyItemTemplate 템플릿에 정의된 2개의 항목이 포함됩니다.

EmptyItemTemplate 속성을 사용하여 빈 항목에 대한 사용자 지정 UI(사용자 인터페이스)를 정의할 수 있습니다.
EmptyDataTemplate 컨트롤에 바인딩된 데이터 소스에 레코드가 들어 있지 않고 InsertItemPosition 속성이 InsertItemPosition..::.None으로 설정된 경우 빈 템플릿이 ListView 컨트롤에 표시됩니다. 이 템플릿은 LayoutTemplate 템플릿 대신 렌더링됩니다. InsertItemPosition 속성을 InsertItemPosition..::.None 이외의 값으로 설정하면 EmptyDataTemplate 템플릿이 렌더링되지 않습니다.

EmptyDataTemplate 속성을 사용하여 빈 템플릿에 대한 사용자 지정 UI(사용자 인터페이스)를 정의할 수 있습니다.
SelectedItemTemplate 선택한 항목을 다른 항목과 구별하기 위해 선택한 데이터 항목에 대해 렌더링할 내용을 정의합니다.
AlternatingItemTemplate 연속된 항목을 쉽게 구별하기 위해 대체 항목에 대해 렌더링할 내용을 정의합니다.
EditItemTemplate 항목을 편집할 때 렌더링할 내용을 정의합니다. EditItemTemplate 템플릿이 ItemTemplate 템플릿 대신 편집 중인 데이터 항목에 대해 렌더링됩니다.
InsertItemTemplate 항목을 삽입하기 위해 렌더링할 내용을 정의합니다. InsertItemTemplate 템플릿이 ItemTemplate 템플릿 대신 ListView 컨트롤에 표시된 항목의 처음이나 끝에서 렌더링됩니다. ListView 컨트롤의 InsertItemPosition 속성을 사용하여 InsertItemTemplate 템플릿의 렌더링 위치를 지정할 수 있습니다.

위 템플릿 설명의 이해가 잘 가지 않으시면 아래 소스를 이용한 사용 예제를 보시면 이해가 되실겁니다. 더욱 자세한 사항은 MSDN의 ListView 컨트롤 설명을 참고하시기 바랍니다.


ListView의 사용 예제

사용예제는 간단한 이미지 게시판 목록을 만들어 보도록 하겠습니다.
예제는 총 2가지로 동시에 진행되도록 하겠습니다.

첫번째 한줄에 하나의 데이터만 나오는 예제
두번째 한줄에 둘 이상의 데이터가 나오는 예제

설명은 소스를 가지고 간단히만 하도록 하겠습니다. 소스만 봐도 충분히 이해가 될것입니다.

그리고 예제에서는 DB까지 설명은 하지 않도록 하겠습니다. 단, 쿼리문은 아래와 같습니다.

Select [GoodsSeq],[Title],[Content],[ImageUrl] From TB_Goods

1. 게시판 목록에서 사용할 스타일을 지정하도록 하겠습니다.

<style type="text/css">
    body { font-family:Verdana, 굴림; font-size:9pt; }
   
    .list_title  { background-color:#5d7b9d; color:#ffffff; font-weight:bold; text-align:center;
                    height:25px; border-bottom:solid 2px #000000; border-top:solid 2px #000000;
                    padding-top:4px; }
    .list_item   { background-color:#ffffff; color:#284775; }
    .list_item2  { background-color:#eeeeee; color:#333333; }
    .list_sep    { background-color:#000000; height:1px; }
    .list_nodata { background-color:#ffffff; height:50px; text-align:center; }
</style>

2-1. 한줄에 하나의 데이터만 나오도록 하는 예제
   - 기존의 GridView 처럼 생각하시면 될거 같습니다.

<asp:ListView ID="ListView1" runat="server" ItemPlaceholderID="phItemList"
    OnItemDataBound="ListView_ItemDataBound">
    <LayoutTemplate>
        <table border="0" cellpadding="0" cellspacing="0">
            <tr>
                <td class="list_title" style="width:60px;">이미지</td>
                <td class="list_title" style="width:460px;">타이틀 / 설명</td>
            </tr>
            <asp:PlaceHolder ID="phItemList" runat="server" />
            <tr><td colspan="4" class="list_sep"></td></tr>
        </table>
    </LayoutTemplate>
    <ItemTemplate>

        <tr>
            <td class="list_item">
                <asp:Image ID="imgGoods" runat="server" Width="50px" Height="50px" Style="margin:5px;" />
            </td>
            <td class="list_item">
                <asp:HyperLink ID="hlTitle" runat="server" />
                <asp:Label ID="lblContent" runat="server" />
            </td>
        </tr>
    </ItemTemplate>
    <AlternatingItemTemplate>

            <td class="list_item2">
                <asp:Image ID="imgGoods" runat="server" Width="50px" Height="50px" Style="margin:5px;" />
            </td>
            <td class="list_item2">
                <asp:HyperLink ID="hlTitle" runat="server" />
                <asp:Label ID="lblContent" runat="server" />
            </td>
    </AlternatingItemTemplate>
    <ItemSeparatorTemplate>
        <tr><td colspan="2" class="list_sep"></td></tr>
    </ItemSeparatorTemplate>
    <EmptyDataTemplate>

        <table border="0" cellpadding="0" cellspacing="0">
            <tr>
                <td class="list_title" style="width:60px;">이미지</td>
                <td class="list_title" style="width:460px;">타이틀 / 설명</td>
            </tr>
            <tr>
                <td colspan="2" class="list_nodata">데이터가 없습니다.</td>
            </tr>
            <tr><td colspan="2" class="list_sep"></td></tr>
        </table>
    </EmptyDataTemplate>
</asp:ListView>
- 여러 템플릿 중에서 LayoutTemplate, ItemTemplate은 필수 사항입니다.
- 속성중에서 빨간색으로 된 부분 ItemPlaceholderID는 필수사항입니다.

2-1. 한줄에 두개 이상의 데이터가 나오도록 하는 예제
   - 기존의 DataList 처럼 생각하시면 될거 같습니다.

<asp:ListView ID="ListView2" runat="server" GroupPlaceholderID="phGroupList" ItemPlaceholderID="phItemList" GroupItemCount="2"
    OnItemDataBound="ListView_ItemDataBound">
    <LayoutTemplate>
        <table border="0" cellpadding="0" cellspacing="0" style="table-layout:fixed;">
            <tr>
                <td class="list_title" style="width:60px;">이미지</td>
                <td class="list_title" style="width:200px;">타이틀 / 설명</td>
                <td class="list_title" style="width:60px;">이미지</td>
                <td class="list_title" style="width:200px;">타이틀 / 설명</td>
            </tr>
            <asp:PlaceHolder ID="phGroupList" runat="server" />
            <tr><td colspan="4" class="list_sep"></td></tr>
        </table>
    </LayoutTemplate>
    <GroupTemplate>
        <tr>
            <asp:PlaceHolder ID="phItemList" runat="server" />
        </tr>
    </GroupTemplate>
    <ItemTemplate>

        <td class="list_item">
            <asp:Image ID="imgGoods" runat="server" Width="50px" Height="50px" Style="margin:5px;" />
        </td>
        <td class="list_item">
            <asp:HyperLink ID="hlTitle" runat="server" />
            <asp:Label ID="lblContent" runat="server" />
        </td>
    </ItemTemplate>
    <GroupSeparatorTemplate>

        <tr><td colspan="4" class="list_sep"></td></tr>
    </GroupSeparatorTemplate>
    <EmptyItemTemplate>

        <td colspan="2">&nbsp;</td>
    </EmptyItemTemplate>
    <EmptyDataTemplate>
        <table border="0" cellpadding="0" cellspacing="0">
            <tr>
                <td class="list_title" style="width:60px;">이미지</td>
                <td class="list_title" style="width:200px;">타이틀 / 설명</td>
                <td class="list_title" style="width:60px;">이미지</td>
                <td class="list_title" style="width:200px;">타이틀 / 설명</td>
            </tr>
            <tr>
                <td colspan="4" class="list_nodata">데이터가 없습니다.</td>
            </tr>
            <tr><td colspan="4" class="list_sep"></td></tr>
        </table>
    </EmptyDataTemplate>
</asp:ListView>
- 여러 템플릿 중에서 LayoutTemplate, GroupTemplate, ItemTemplate은 필수 사항입니다.
- 속성중에서 빨간색으로 된 부분 GroupPlaceholderID, GroupItemCount, ItemPlaceholderID는 필수사항입니다.

참고
위 2번에서 각 데이터가 들어갈 컨트롤에 직접 데이터 바인딩이 가능합니다.

<asp:Label ID="lblContent" runat="server" Text='<%#Eval("Content")%>' />

이와같이 지정을 하면 직접 데이터 바인딩이 됩니다. 참고로 Text 속성의 데이터를 지정할때 " 를 사용하지 말고 ' 를 사용해야 합니다.

그리고 이 예제에서는 직접 데이터 바인딩을 하지않고 OnItemDataBound 을 사용하여 데이터를 지정하도록 하겠습니다.

3. OnItemDataBound 사용
    - 2번의 디자인 소스에 보면 ListView 속성에 OnItemDataBound="ListView_ItemDataBound" 라는 이벤트가 지정되어 있습니다. cs 파일의 비하인드 코드에서 코드를 작성해 보도록 하겠습니다.

protected void ListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
    ListViewDataItem item = (ListViewDataItem)e.Item;
    // 아이템의 타입이 DataItem일 경우
    if (item.ItemType == ListViewItemType.DataItem)
    {
        // 상품의 이미지를 설정한다.
        Image imgGoods = item.FindControl("imgGoods") as Image;
        imgGoods.ImageUrl = string.Format("~/files/images/{0}", DataBinder.Eval(item.DataItem, "ImageUrl"));

        // 상품명과 상품 상세보기 링크를 설정한다.
        HyperLink hlTitle= item.FindControl("hlTitle") as HyperLink;
        hlTitle.Text = DataBinder.Eval(item.DataItem, "Title").ToString();
        hlTitle.NavigateUrl = string.Format("~/View.aspx?Seq={0}", DataBinder.Eval(item.DataItem, "GoodsSeq"));

        // 상품의 설명을 설정한다.
        Label lblContent = item.FindControl("lblContent") as Label;
        lblContent.Text = DataBinder.Eval(item.DataItem, "Content").ToString();
    }
}

이제 브라우저로 보기를 실행해보시기 바랍니다.
아래와 같은 화면이 나왔을 것입니다. (원하시는 화면이 나왔나요??)



이것으로 ASP.NET 3.5의 새로운 컨트롤 ListView에 대한 설명을 마치도록 하겠습니다.
이 내용이 많은 도움이 되길 바랍니다!!

작성자 : 상현넘™ [http://www.shblitz.net]