Share via


연습: ASP.NET 2.0용 사용자 지정 데이터 바인딩 ASP.NET 웹 컨트롤 만들기

업데이트: 2007년 11월

이 연습에서는 ASP.NET 버전 2.0에서 간단한 데이터 바인딩된 웹 서버 컨트롤을 만드는 방법을 보여 줍니다. ASP.NET 2.0에서는 데이터 소스 모델을 통해 페이징, 정렬 및 삭제와 같은 일반적인 데이터 작업을 허용하는 데이터 소스 컨트롤에 데이터 바인딩된 컨트롤을 바인딩하여 데이터 바인딩된 컨트롤 자체를 외부로 옮길 수 있습니다. 페이지 개발자는 이 데이터 모델로 데이터 바인딩된 컨트롤을 보다 유연하게 사용할 수 있고 재사용도를 높일 수 있습니다. 또한 ASP.NET 2.0 데이터 소스 모델에서는 데이터 수집 개체에 직접 바인딩하는 기능을 지원합니다. ASP.NET 2.0 데이터 모델용 사용자 지정 데이터 바인딩된 컨트롤을 개발하는 방법에 대한 자세한 내용은 ASP.NET 2.0용 사용자 지정 데이터 바인딩 웹 서버 컨트롤 개발을 참조하십시오.

이 연습에서는 데이터 소스 컨트롤 또는 IEnumerable 인터페이스를 구현하는 모든 개체에 바인딩될 수 있는 데이터 바인딩된 컨트롤을 만듭니다.

이 연습에서 수행할 작업은 다음과 같습니다.

  • 동적 컴파일을 통해 사용자 지정 데이터 바인딩된 컨트롤을 테스트할 웹 사이트를 만듭니다.

  • 기본 클래스인 DataBoundControl을 확장하는 데이터 바인딩된 컨트롤 클래스를 만듭니다. 이 클래스에서는 바인딩된 데이터를 나타내는 테이블 열을 표시합니다. 데이터 바인딩된 컨트롤 클래스에서는 다음 항목을 제공해야 합니다.

    • 기본 데이터 바인딩된 컨트롤 클래스의 PerformSelect 메서드를 재정의해야 합니다. 이 메서드 내에서 데이터 검색을 시작하는 작업이 수행됩니다.

    • IEnumerable 형식의 매개 변수 하나가 있는 메서드를 사용하여 반환된 데이터를 받아야 합니다. 데이터 처리가 필요한 경우 이 메서드 내에서 처리가 수행됩니다. 마지막 단계로 PerformDataBinding 메서드를 호출하여 데이터 바인딩을 시작합니다.

    • PerformDataBinding 메서드를 재정의해야 합니다. 이 메서드 내에서 검색된 데이터가 열거되고 데이터를 나타내는 자식 컨트롤이 추가됩니다.

  • Web.config 파일에 컨트롤을 등록합니다.

  • ASP.NET 웹 페이지에서 컨트롤을 테스트합니다.

  • 컨트롤을 이진 코드로 배포할 수 있도록 컨트롤을 컴파일합니다.

  • 컴파일된 사용자 지정 데이터 바인딩 서버 컨트롤을 테스트합니다.

컨트롤을 테스트할 웹 사이트 만들기

ASP.NET의 동적 컴파일을 사용하면 컨트롤을 어셈블리로 컴파일하지 않고도 페이지에서 컨트롤을 테스트할 수 있습니다. ASP.NET에서는 ASP.NET 웹 사이트의 루트 아래에 있는 App_Code 디렉터리에 추가된 코드를 동적으로 컴파일합니다. 따라서 컨트롤을 수동으로 어셈블리로 컴파일하지 않고도 페이지에서 App_Code 디렉터리에 있는 소스 파일의 클래스에 액세스할 수 있습니다.

참고:

ASP.NET 1.0 및 1.1에서는 App_Code 디렉터리가 제공되지 않습니다. 컨트롤을 처음 테스트할 때 App_Code 디렉터리를 사용할지 여부를 선택할 수 있습니다. "컨트롤을 어셈블리로 컴파일" 단원에서 설명한 대로 서버 컨트롤을 빌드하는 주요 단계는 ASP.NET의 이전 버전과 동일합니다.

사용자 지정 데이터 바인딩된 컨트롤을 테스트할 웹 사이트를 만들려면

  1. ServerControlsTest라는 웹 사이트를 만듭니다.

    IIS에서 이 사이트를 ServerControlsTest라는 가상 디렉터리로 만들 수 있습니다. IIS 가상 디렉터리를 만들고 구성하는 방법에 대한 자세한 내용은 방법: IIS 5.0 및 6.0에서 가상 디렉터리 만들기 및 구성을 참조하십시오.

  2. 웹 사이트의 루트(웹 응용 프로그램 루트) 디렉터리 바로 아래에 App_Code 디렉터리를 만듭니다.

SimpleDataBoundColumn 클래스 만들기

이 단원에서는 DataBoundControl 클래스를 확장하는 데이터 바인딩된 컨트롤 클래스를 만듭니다. 새 컨트롤은 1열 표에 바인딩된 데이터를 표시합니다.

SimpleDataBoundColumn 클래스를 만들려면

  1. App_Code 폴더에 SimpleDataBoundColumn.cs 또는 SimpleDataBoundColumn.vb라는 클래스를 만듭니다.

  2. 클래스 파일에 다음 코드를 추가합니다.

    Imports System
    Imports System.Collections
    Imports System.ComponentModel
    Imports System.Security.Permissions
    Imports System.Web
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    
    Namespace Samples.AspNet.Controls.VB
    
        <AspNetHostingPermission(SecurityAction.Demand, _
            Level:=AspNetHostingPermissionLevel.Minimal), _
            AspNetHostingPermission(SecurityAction.InheritanceDemand, _
            Level:=AspNetHostingPermissionLevel.Minimal)> _
        Public Class SimpleDataBoundColumn
            Inherits DataBoundControl
    
            Public Property DataTextField() As String
                Get
                    Dim o As Object = ViewState("DataTextField")
                    If o Is Nothing Then
                        Return String.Empty
                    Else
                        Return CStr(o)
                    End If
                End Get
                Set(ByVal value As String)
                    ViewState("DataTextField") = value
                    If (Initialized) Then
                        OnDataPropertyChanged()
                    End If
                End Set
            End Property
    
            Protected Overrides Sub PerformSelect()
                ' Call OnDataBinding here if bound to a data source using the
                ' DataSource property (instead of a DataSourceID), because the
                ' databinding statement is evaluated before the call to GetData.       
                If Not IsBoundUsingDataSourceID Then
                    OnDataBinding(EventArgs.Empty)
                End If
    
                ' The GetData method retrieves the DataSourceView object from  
                ' the IDataSource associated with the data-bound control.            
                GetData().Select(CreateDataSourceSelectArguments(), _
                    AddressOf OnDataSourceViewSelectCallback)
    
                ' The PerformDataBinding method has completed.
                RequiresDataBinding = False
                MarkAsDataBound()
    
                ' Raise the DataBound event.
                OnDataBound(EventArgs.Empty)
    
            End Sub
    
            Private Sub OnDataSourceViewSelectCallback(ByVal retrievedData As IEnumerable)
                ' Call OnDataBinding only if it has not already been 
                ' called in the PerformSelect method.
                If IsBoundUsingDataSourceID Then
                    OnDataBinding(EventArgs.Empty)
                End If
                ' The PerformDataBinding method binds the data in the  
                ' retrievedData collection to elements of the data-bound control.
                PerformDataBinding(retrievedData)
    
            End Sub
    
            Protected Overrides Sub PerformDataBinding(ByVal retrievedData As IEnumerable)
                MyBase.PerformDataBinding(retrievedData)
    
                ' Verify data exists.
                If Not (retrievedData Is Nothing) Then
                    Dim tbl As New Table()
                    Dim row As TableRow
                    Dim cell As TableCell
                    Dim dataStr As String = String.Empty
    
                    Dim dataItem As Object
                    For Each dataItem In retrievedData
                        ' If the DataTextField was specified get the data
                        ' from that field, otherwise get the data from the first field. 
                        If DataTextField.Length > 0 Then
                            dataStr = DataBinder.GetPropertyValue(dataItem, DataTextField, Nothing)
                        Else
                            Dim props As PropertyDescriptorCollection = TypeDescriptor.GetProperties(dataItem)
                            If props.Count >= 1 Then
                                If Nothing <> props(0).GetValue(dataItem) Then
                                    dataStr = props(0).GetValue(dataItem).ToString()
                                End If
                            End If
                        End If
    
                        row = New TableRow()
                        tbl.Rows.Add(row)
                        cell = New TableCell()
                        cell.Text = dataStr
                        row.Cells.Add(cell)
                    Next dataItem
    
                    Controls.Add(tbl)
                End If
    
            End Sub
        End Class
    End Namespace
    
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Security.Permissions;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    namespace Samples.AspNet.Controls.CS
    {
        [AspNetHostingPermission(SecurityAction.Demand,
           Level = AspNetHostingPermissionLevel.Minimal)]
        [AspNetHostingPermission(SecurityAction.InheritanceDemand,
            Level = AspNetHostingPermissionLevel.Minimal)]
        public class SimpleDataBoundColumn : DataBoundControl
        {
            public string DataTextField
            {
                get
                {
                    object o = ViewState["DataTextField"];
                    return ((o == null) ? string.Empty : (string)o);
                }
                set
                {
                    ViewState["DataTextField"] = value;
                    if (Initialized)
                    {
                        OnDataPropertyChanged();
                    }
                }
            }
    
            protected override void PerformSelect()
            {
                // Call OnDataBinding here if bound to a data source using the
                // DataSource property (instead of a DataSourceID), because the
                // databinding statement is evaluated before the call to GetData.       
                if (!IsBoundUsingDataSourceID)
                {
                    this.OnDataBinding(EventArgs.Empty);
                }
    
                // The GetData method retrieves the DataSourceView object from  
                // the IDataSource associated with the data-bound control.            
                GetData().Select(CreateDataSourceSelectArguments(),
                    this.OnDataSourceViewSelectCallback);
    
                // The PerformDataBinding method has completed.
                RequiresDataBinding = false;
                MarkAsDataBound();
    
                // Raise the DataBound event.
                OnDataBound(EventArgs.Empty);
            }
    
            private void OnDataSourceViewSelectCallback(IEnumerable retrievedData)
            {
                // Call OnDataBinding only if it has not already been 
                // called in the PerformSelect method.
                if (IsBoundUsingDataSourceID)
                {
                    OnDataBinding(EventArgs.Empty);
                }
                // The PerformDataBinding method binds the data in the  
                // retrievedData collection to elements of the data-bound control.
                PerformDataBinding(retrievedData);
            }
    
            protected override void PerformDataBinding(IEnumerable retrievedData)
            {
                base.PerformDataBinding(retrievedData);
    
                // Verify data exists.
                if (retrievedData != null)
                {
                    Table tbl = new Table();
                    TableRow row;
                    TableCell cell;
                    string dataStr = String.Empty;
    
                    foreach (object dataItem in retrievedData)
                    {
                        // If the DataTextField was specified get the data
                        // from that field, otherwise get the data from the first field. 
                        if (DataTextField.Length > 0)
                        {
                            dataStr = DataBinder.GetPropertyValue(dataItem,
                                DataTextField, null);
                        }
                        else
                        {
                            PropertyDescriptorCollection props =
                                    TypeDescriptor.GetProperties(dataItem);
                            if (props.Count >= 1)
                            {
                                if (null != props[0].GetValue(dataItem))
                                {
                                    dataStr = props[0].GetValue(dataItem).ToString();
                                }
                            }
                        }
    
                        row = new TableRow();
                        tbl.Rows.Add(row);
                        cell = new TableCell();
                        cell.Text = dataStr;
                        row.Cells.Add(cell);
                    }
    
                    this.Controls.Add(tbl); 
                }
            }
        }
    }
    

코드 설명

SimpleDataBoundColumn 클래스는 기본 데이터 바인딩 클래스인 DataBoundControl에서 파생됩니다. 이 기본 클래스에서 파생되어 DataSourceID, DataSourceDataMember 데이터 바인딩 속성이 노출됩니다. 페이지 개발자는 이러한 노출된 속성을 통해 해당 사용자 지정 컨트롤에 바인딩할 데이터 소스 및 특정 데이터 멤버를 지정할 수 있습니다.

사용자 지정 데이터 바인딩 속성을 추가하는 방법을 보여 주기 위해 SimpleDataBoundColumn 클래스에 DataTextField 속성이 추가되었습니다. 페이지 개발자가 DataTextField 속성을 추가하면 새 값이 뷰 상태에 저장됩니다. 또한 컨트롤이 이미 초기화된 경우 OnDataPropertyChanged 메서드가 호출됩니다. 이를 통해 데이터 바인딩된 컨트롤이 데이터에 다시 바인딩되므로 컨트롤에서 새로운 데이터 바인딩 속성 설정을 사용할 수 있습니다.

재정의된 DataBind 메서드는 필수적 요소이며 관련 데이터 소스의 개체를 열거하는 논리를 포함하고 자식 컨트롤을 만듭니다. ASP.NET 2.0 데이터 바인딩된 컨트롤에서는 SimpleDataBoundColumn 클래스에서와 같이 재정의된 DataBind 메서드 내에서 다음 작업을 수행해야 합니다.

  • IsBoundUsingDataSourceID 속성 값이 false인지 검사하여 DataSource 속성에 데이터 소스가 지정되어 있는지 여부를 확인합니다.

  • 바인딩될 데이터가 DataSource 속성에 지정된 경우 OnDataBinding 메서드를 호출하여 DataSource 속성에 지정된 데이터 멤버를 바인딩합니다.

  • GetData 메서드를 호출하여 데이터 바인딩된 컨트롤에 연결된 DataSourceView 개체를 검색합니다.

  • 검색된 DataSourceView 개체의 Select 메서드를 호출하여 데이터 검색을 시작하고 검색된 데이터를 처리할 OnDataSourceViewSelectCallback 콜백 메서드를 지정합니다.

  • PerformSelect 메서드의 데이터 검색 작업이 완료되었음을 나타내기 위해 RequiresDataBinding 속성을 false로 설정한 다음 MarkAsDataBound 메서드를 호출합니다.

  • OnDataBound 이벤트가 발생합니다.

OnDataSourceViewSelectCallback 콜백 메서드에서는 검색된 데이터를 받습니다. 이 콜백 메서드에서는 IEnumerable 형식의 매개 변수 하나를 받아야 합니다. 사용자 지정 컨트롤에서 필요한 모든 데이터 처리가 여기에서 수행됩니다. 이 사용자 지정 컨트롤은 데이터를 있는 그대로 사용합니다. 따라서 이 예제에서는 추가 데이터 처리가 발생하지 않습니다. 마지막 단계로 PerformDataBinding 메서드를 호출하여 데이터 바인딩 프로세스를 시작합니다.

PerformDataBinding 메서드를 재정의하는 동안 데이터를 나타내는 모든 자식 컨트롤이 만들어집니다. 데이터 컬렉션이 열거되고 각 데이터 항목마다 새 TableCell 개체가 만들어집니다. DataTextField 속성이 설정된 경우 이 속성을 통해 셀의 Text 속성에 바인딩할 데이터 필드가 결정됩니다. 그렇지 않은 경우에는 첫 번째 필드가 사용됩니다.

부모 Table 컨트롤이 사용자 지정 SimpleDataBoundColumn 컨트롤의 Controls 컬렉션에 추가됩니다. 컨트롤의 Controls 컬렉션에 추가되는 모든 컨트롤은 상속된 Render 메서드가 실행되는 동안 자동으로 렌더링됩니다.

데이터 바인딩 웹 서버 컨트롤에서 필수적으로 구현해야 하는 항목에 대한 자세한 내용은 ASP.NET 2.0용 사용자 지정 데이터 바인딩 웹 서버 컨트롤 개발을 참조하십시오.

태그 접두사 만들기

태그 접두사는 컨트롤을 페이지에서 선언적으로 만드는 경우 컨트롤의 형식 이름 앞에 나오는 접두사입니다(예: <asp:Table />의 "asp"). ASP.NET의 경우 컨트롤을 페이지에서 선언적으로 사용하려면 컨트롤의 네임스페이스에 매핑되는 태그 접두사가 필요합니다. 페이지 개발자는 다음 예제와 같이 사용자 지정 컨트롤을 사용하는 각 페이지에 @ Register 지시문을 추가하여 태그 접두사/네임스페이스 매핑을 제공할 수 있습니다.

<%@ Register TagPrefix="aspSample" 
    Namespace="Samples.AspNet.Controls.CS"%>
<%@ Register TagPrefix="aspSample" 
    Namespace="Samples.AspNet.Controls.VB"%>
참고:

@ Register 지시문에 컨트롤 어셈블리의 이름을 지정하는 assembly 특성은 없습니다. assembly 특성이 없는 경우 ASP.NET에서는 어셈블리가 App_Code 디렉터리의 소스 파일에서 동적으로 컴파일된다고 가정합니다.

페이지 개발자는 각 .aspx 페이지에서 @ Register 지시문을 사용하는 대신 Web.config 파일에 태그 접두사 및 네임스페이스 매핑을 지정할 수 있습니다. 이 방법은 사용자 지정 컨트롤이 웹 응용 프로그램의 여러 페이지에 사용될 경우 유용합니다. 다음 절차에서는 Web.config 파일에 태그 접두사 매핑을 지정하는 방법을 설명합니다.

Web.config 파일에서 태그 접두사 매핑을 추가하려면

  1. 웹 사이트에 Web.config라는 파일이 없는 경우 웹 사이트의 루트 폴더에 이 파일을 만듭니다.

  2. 새 Web.config 파일을 만든 경우 다음 XML 태그를 파일에 복사하고 해당 파일을 저장합니다. 사이트에 이미 Web.config 파일이 있는 경우 이 파일에 강조 표시된 다음 요소를 추가합니다.

    참고:

    태그 접두사 엔트리는 pages 섹션 아래에 있는 controls 섹션의 자식이어야 하고 pages 섹션은 system.web의 자식이어야 합니다.

    <?xml version="1.0"?>
    <configuration>
      <system.web>
        <pages>
          <controls>
            <add tagPrefix="aspSample" namespace="Samples.AspNet.Controls.CS" />
          </controls>
        </pages>
      </system.web>
    </configuration>
    
    <?xml version="1.0"?>
    <configuration>
      <system.web>
        <pages>
          <controls>
            <add tagPrefix="aspSample" namespace="Samples.AspNet.Controls.VB" />
          </controls>
        </pages>
      </system.web>
    </configuration>
    

    강조 표시된 섹션은 태그 접두사 "aspSample"을 Samples.AspNet.Controls.CS 또는 Samples.AspNet.Controls.VB 네임스페이스에 매핑하는 태그 접두사 엔트리를 보여 줍니다.

구성 파일에 태그 접두사 매핑을 지정하면 웹 사이트의 페이지에서 SimpleDataBoundColumn 컨트롤을 선언적으로(<aspSample:SimpleDataBoundColumn />) 사용할 수 있습니다.

참고:

ASP.NET 1.0 및 1.1에서의 태그 접두사 매핑은 사용자 지정 컨트롤을 사용한 각 페이지의 @ Register 지시문에 지정됩니다.

사용자 지정 데이터 바인딩된 컨트롤을 사용하는 페이지 만들기

이 연습 단원에서는 사용자 지정 데이터 바인딩된 컨트롤을 테스트하기 위한 페이지 태그를 만듭니다.

사용자 지정 데이터 바인딩된 컨트롤을 사용하는 페이지를 만들려면

  1. 웹 사이트에 TestSimpleDataBoundColumn.aspx라는 파일을 만듭니다.

  2. 다음 태그를 TestSimpleDataBoundColumn.aspx 파일에 복사하고 파일을 저장합니다.

    <%@ Page Language="VB" Trace="true"%>
    <%@ Register TagPrefix="aspSample" Namespace="Samples.AspNet.Controls.VB" %>
    <%@ Import Namespace="System.Data" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <script >
             Function CreateDataSource() As ICollection 
    
             ' Create sample data for the DataList control.
             Dim dt As DataTable = New DataTable()
             dim dr As DataRow
    
             ' Define the columns of the table.
             dt.Columns.Add(New DataColumn("IntegerValue", GetType(Int32)))
             dt.Columns.Add(New DataColumn("StringValue", GetType(String)))
             dt.Columns.Add(New DataColumn("CurrencyValue", GetType(Double)))
             dt.Columns.Add(New DataColumn("ImageValue", GetType(String)))
    
             ' Populate the table with sample values.
             Dim i As Integer
    
             For i = 0 To 8 
    
                dr = dt.NewRow()
    
                dr(0) = i
                dr(1) = "Description for item " & i.ToString()
                dr(2) = 1.23 * (i + 1)
                dr(3) = "Image" & i.ToString() & ".jpg"
    
                dt.Rows.Add(dr)
    
             Next i
    
             Dim dv As DataView = New DataView(dt)
             Return dv
    
          End Function
    
          Sub Page_Load(sender As Object, e As EventArgs) 
    
             ' Load sample data only once, when the page is first loaded.
             If Not IsPostBack Then 
    
                simpleDataBoundColumn1.DataSource = CreateDataSource()
                simpleDataBoundColumn1.DataBind()
    
             End If
    
          End Sub
    
    </script>
    
    <head >
        <title>SimpleDataBoundColumn test page</title>
    </head>
    <body>
        <form id="form1" >
        <div>
            <aspSample:SimpleDataBoundColumn  id="simpleDataBoundColumn1" DataTextField="CurrencyValue" BorderStyle="Solid"></aspSample:SimpleDataBoundColumn>
        </div>
        </form>
    </body>
    </html>
    
    <%@ Page Language="C#" Trace="true"%>
    <%@ Register TagPrefix="aspSample" Namespace="Samples.AspNet.Controls.CS" %>
    <%@ Import Namespace="System.Data" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <script >
    
          ICollection CreateDataSource() 
          {
             DataTable dt = new DataTable();
             DataRow dr;
    
             dt.Columns.Add(new DataColumn("IntegerValue", typeof(Int32)));
             dt.Columns.Add(new DataColumn("StringValue", typeof(string)));
             dt.Columns.Add(new DataColumn("CurrencyValue", typeof(double)));
    
             for (int i = 0; i < 9; i++) 
             {
                dr = dt.NewRow();
    
                dr[0] = i;
                dr[1] = "Item " + i.ToString();
                dr[2] = 1.23 * (i + 1);
    
                dt.Rows.Add(dr);
             }
    
             DataView dv = new DataView(dt);
             return dv;
          }
    
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                simpleDataBoundColumn1.DataSource = CreateDataSource();
                simpleDataBoundColumn1.DataBind();
            }
        }
    </script>
    
    <head >
        <title>SimpleDataBoundColumn test page</title>
    </head>
    <body>
        <form id="form1" >
        <div>
            <aspSample:SimpleDataBoundColumn  id="simpleDataBoundColumn1" DataTextField="CurrencyValue" BorderStyle="Solid"></aspSample:SimpleDataBoundColumn>
        </div>
        </form>
    </body>
    </html>
    
  3. SimpleDataBoundColumnTest.aspx 페이지를 실행합니다.

  4. 사용자 지정 컨트롤의 소스 코드를 변경합니다. 예를 들어 RenderContents 메서드의 끝에 다음 코드 줄을 입력하여 추가 문자열을 출력합니다.

    writer.Write("<br />Testing how the App_Code directory works.");
    
    writer.Write("<br />Testing how the App_Code directory works.")
    
  5. 브라우저에서 SimpleDataBoundColumnTest.aspx 페이지를 새로 고칩니다.

    컨트롤을 컴파일하지 않았지만 컨트롤의 변경 내용이 페이지에 적용됨을 확인할 수 있습니다.

컨트롤을 어셈블리로 컴파일

App_Code 디렉터리를 사용하면 컨트롤을 컴파일하지 않고도 컨트롤을 테스트할 수 있습니다. 그러나 다른 개발자에게 사용자 컨트롤을 개체 코드로 배포하려면 해당 컨트롤을 컴파일해야 합니다. 또한 어셈블리로 컴파일되지 않은 컨트롤은 비주얼 디자이너의 도구 상자에 추가할 수 없습니다.

컨트롤을 어셈블리로 컴파일하려면

  1. 다음 단계를 수행하여 사용자 컴퓨터의 Windows 환경 변수 PATH에 .NET Framework 설치 경로가 포함되도록 설정합니다.

    1. Windows에서 내 컴퓨터를 마우스 오른쪽 단추로 클릭하고 속성을 선택한 다음 고급 탭, 환경 변수 단추를 차례로 클릭합니다.

    2. 시스템 변수 목록에서 Path 변수를 두 번 클릭합니다.

    3. 변수 값 텍스트 상자에서 기존 값의 끝에 세미콜론(;)을 추가한 후 .NET Framework 설치 경로를 입력합니다. 일반적으로 .NET Framework는 Windows 설치 디렉터리에서 \Microsoft.NET\Framework\versionNumber에 설치됩니다.

    4. 확인을 클릭하여 각 대화 상자를 닫습니다.

  2. 이 연습의 이전 절차에서 만든 소스 파일이 들어 있는 App_Code 디렉터리에서 다음 명령을 실행합니다. 이렇게 하면 동일한 App_Code 디렉터리에 Samples.AspNet.Controls.CS.dll 또는 Samples.AspNet.Controls.VB.dll이라는 어셈블리가 생성됩니다.

    csc /t:library /out:Samples.AspNet.Controls.CS.dll /r:System.dll /r:System.Web.dll *.cs
    
    vbc /t:library /out:Samples.AspNet.Controls.VB.dll /r:System.dll /r:System.Web.dll *.vb
    

    /t:library 컴파일러 옵션을 사용하면 컴파일러에서 실행 어셈블리 대신 라이브러리를 만듭니다. /out 옵션은 어셈블리에 사용할 이름을 제공하고 /r 옵션은 어셈블리에 링크된 어셈블리를 나열합니다.

    참고:

    예제를 독립적으로 유지하기 위해 이 연습에서는 컨트롤이 하나만 있는 어셈블리를 만듭니다. 일반적으로 .NET Framework 디자인 지침에 따르면 적은 수의 클래스만 포함된 어셈블리를 만들지 않는 것이 좋습니다. 또한 쉽게 배포할 수 있도록 가능한 적은 수의 어셈블리를 만들어야 합니다.

TagPrefixAttribute를 사용하여 태그 접두사/네임스페이스 매핑 제공

이전 단계에서는 페이지 개발자가 페이지나 Web.config 파일에 태그 접두사를 지정하는 방법을 확인했습니다. 컨트롤을 컴파일하면 어셈블리 수준의 System.Web.UI.TagPrefixAttribute 특성을 포함하여 비주얼 디자이너에서 컨트롤에 사용할 기본 태그 접두사를 지정할 수도 있습니다. TagPrefixAttribute 특성은 비주얼 디자이너가 페이지의 @ Register 지시문 또는 Web.config 파일에서 태그 접두사 매핑을 찾지 못한 경우 사용할 태그 접두사를 제공하므로 유용합니다. 도구 상자의 컨트롤을 처음으로 두 번 클릭하거나 페이지로 끌어 오면 태그 접두사가 페이지에 등록됩니다.

TagPrefixAttribute 특성을 사용하려는 경우 컨트롤과 함께 컴파일되는 별도의 파일에 이 특성을 지정할 수 있습니다. 규칙에 따라 이 파일의 이름은 AssemblyInfo.cs 또는 AssembyInfo.vb와 같이 AssemblyInfo.languageExtension으로 지정됩니다. 다음 절차에서는 TagPrefixAttribute 메타데이터를 지정하는 방법을 설명합니다.

참고:

컨트롤의 어셈블리에 TagPrefixAttribute를 지정하지 않고 페이지 개발자가 페이지 또는 Web.config 파일에 태그 접두사/네임스페이스 매핑을 지정하지 않는 경우 비주얼 디자이너에서 기본 태그 접두사를 만들 수 있습니다. 예를 들어 도구 상자에서 컨트롤을 끌어 오면 Visual Studio 2005에서는 컨트롤에 대해 cc1 같은 자체의 고유한 태그를 만듭니다.

TagPrefixAttribute를 사용하여 태그 접두사 매핑을 추가하려면

  1. 소스 코드 디렉터리에 AssemblyInfo.cs 또는 AssemblyInfo.vb라는 파일을 만들고 다음 코드를 파일에 추가합니다.

    using System;
    using System.Web.UI;
    [assembly: TagPrefix("Samples.AspNet.Controls.CS", "aspSample")]
    
    Imports System
    Imports System.Web.UI
    <Assembly: TagPrefix("Samples.AspNet.Controls.VB", "aspSample")> 
    

    태그 접두사 특성은 Samples.AspNet.Controls.CS 또는 Samples.AspNet.Controls.VB 네임스페이스와 aspSample 접두사 간에 매핑을 만듭니다.

  2. 포함 리소스가 있는지 여부에 관계없이 이전에 사용된 컴파일 명령을 사용하여 모든 소스 파일을 다시 컴파일합니다.

ASP.NET 페이지에서 컴파일된 사용자 지정 데이터 바인딩 서버 컨트롤 사용

컴파일된 버전의 사용자 지정 컨트롤을 테스트하려면 웹 사이트의 페이지에서 컨트롤의 어셈블리에 액세스할 수 있도록 설정해야 합니다.

웹 사이트에서 컨트롤의 어셈블리에 액세스할 수 있도록 설정하려면

  1. 웹 사이트의 루트 아래에 Bin 디렉터리를 만듭니다.

  2. 컨트롤 어셈블리(Samples.AspNet.Controls.CS.dll 또는 Samples.AspNet.Controls.VB.dll)를 App_Code 디렉터리에서 Bin 디렉터리로 끌어 놓습니다.

  3. App_Code 디렉터리에서 컨트롤의 소스 파일을 삭제합니다.

    소스 파일을 삭제하지 않으면 컴파일된 어셈블리와 ASP.NET에서 동적으로 생성된 어셈블리 모두에 컨트롤 형식이 유지됩니다. 이렇게 되면 컨트롤을 로드할 때 모호한 참조가 만들어지고 컨트롤이 사용되는 페이지에서 컴파일러 오류가 발생합니다.

이 연습에서 만든 어셈블리는 웹 사이트의 페이지에서 컨트롤을 사용할 수 있도록 ASP.NET 웹 사이트의 Bin 디렉터리에 배치되므로 이를 전용 어셈블리라고 합니다. 복사본이 설치되어 있지 않은 다른 응용 프로그램에서는 이 어셈블리에 액세스할 수 없습니다. 공유 웹 호스팅 응용 프로그램에 대해 컨트롤을 만드는 경우 일반적으로 컨트롤을 전용 어셈블리에 패키지합니다. 그러나 전용 호스팅 환경에서 사용할 컨트롤을 만들거나 ISP가 모든 고객이 사용할 수 있도록 설정하는 컨트롤 모음을 만들 경우에는 전역 어셈블리 캐시에 설치된 강력한 이름의 공유 어셈블리에 컨트롤을 패키지해야 합니다. 자세한 내용은 어셈블리 및 전역 어셈블리 캐시 사용을 참조하십시오.

이제 Web.config 파일에서 만든 태그 접두사 매핑을 수정하여 컨트롤의 어셈블리 이름을 지정해야 합니다.

Web.config 파일에서 태그 접두사 매핑을 수정하려면

  • Web.config 파일을 편집하여 addtagPrefix 요소에 assembly 특성을 추가합니다.

    <controls>
      <add tagPrefix="aspSample" namespace="Samples.AspNet.Controls.CS" assembly="Samples.AspNet.Controls.CS" />
    </controls>
    
    <controls>
      <add tagPrefix="aspSample" namespace="Samples.AspNet.Controls.VB" assembly="Samples.AspNet.Controls.VB" />
    </controls>
    

assembly 특성은 컨트롤을 포함하는 어셈블리의 이름을 지정하고 addtagPrefix 요소는 태그 접두사를 네임스페이스 및 어셈블리 조합에 매핑합니다. ASP.NET에 의해 App_Code 디렉터리의 소스 파일에서 동적으로 어셈블리가 생성되면 어셈블리 특성이 필요하지 않습니다. 어셈블리 특성이 사용되지 않는 경우 ASP.NET은 App_Code 디렉터리에서 동적으로 생성된 어셈블리로부터 컨트롤 형식을 로드합니다.

사용자 지정 컨트롤을 사용하는 페이지를 보려면

  • 주소 표시줄에 다음 URL을 입력하여 브라우저에 SimpleDataBoundColumnTest.aspx 페이지를 표시합니다.

    https://localhost/ServerControlsTest/SimpleDataBoundColumnTest.aspx
    

Visual Studio 2005 같은 비주얼 디자이너에서 컨트롤을 사용하는 경우 도구 상자에 컨트롤 추가, 도구 상자의 컨트롤을 디자인 화면으로 끌어 오기, 속성 브라우저에서 속성 및 이벤트 액세스 등의 작업을 수행할 수 있습니다. 또한 Visual Studio 2005의 경우 컨트롤은 페이지 디자이너의 소스 뷰 및 코드 편집기에서 IntelliSense 기능을 완벽하게 지원합니다. 페이지 개발자가 컨트롤 태그를 클릭하는 경우 속성 브라우저 지원 및 script 블록의 문 완성 기능을 예로 들 수 있습니다.

참고:

대부분의 비주얼 디자이너에서는 사용자 지정 컨트롤을 디자이너의 도구 상자에 추가할 수 있습니다. 자세한 내용은 디자이너 설명서를 참조하십시오.

다음 단계

이 연습의 간단한 사용자 지정 데이터 바인딩 서버 컨트롤에서는 페이지 개발자가 컨트롤을 외부 데이터 소스에 바인딩하는 효율적이고 유연한 표준 방식을 제공하는 사용자 지정 컨트롤을 만드는 데 사용되는 기본 단계를 보여 줍니다. 이 연습을 시작으로 Visual Studio에서 복잡한 사용자 지정 서버 컨트롤을 만들 수 있도록 제공되는 프레임워크를 살펴볼 수 있습니다. 다음과 같은 항목을 살펴 보십시오.

참고 항목

작업

연습: 사용자 지정 서버 컨트롤 개발 및 사용

개념

ASP.NET 2.0용 사용자 지정 데이터 바인딩 웹 서버 컨트롤 개발

ASP.NET 데이터 바인딩 웹 서버 컨트롤 개요

사용자 지정 서버 컨트롤의 메타데이터 특성

ASP.NET 컨트롤 디자이너 개요

참조

HierarchicalDataBoundControlDesigner

기타 리소스

사용자 지정 ASP.NET 서버 컨트롤 개발