Programming/.NET

특정 페이지에 ListBox와 같은 컨트롤을 배치하고 Design화면을 보면 다음과 같이 컨트롤을 디자인 할 수 있는 화면을 볼 수 있습니다.

 

컨트롤을 직접 작성하는 경우 이와 같은 기능을 구현하기 위해서는 우선 컨트롤을 직접 디자인할 수 있도록 하는 컨트롤디자이너를 생성해야 합니다.

 

public class WebCustomControl1ControlDesigner : CompositeControlDesigner

 

컨트롤 디자이너는 CompositeControlDesigner 추상클래스를 상속받도록 합니다. 우선 컨트롤 디자이너는 클래스형태만 만들어둡니다.

 

[Designer(typeof(WebCustomControl1ControlDesigner))]
[ToolboxData("<{0}:WebCustomControl1 runat=\"server\" width=\"100%\"></{0}:WebCustomControl1>")]
public class WebCustomControl1 : CompositeControl

 

이제 컨트롤 디자이너가 들어갈 컨테이너 컨트롤을 작성합니다. 이 컨트롤은 CompositeControl 클래스를 상속받습니다.

 

Designer 특성은 해당 컨테이너에 들어갈 디자이너 컨트롤을 지정하며 ToolboxData는 사용자가 해당 컨트롤을 페이지에 배치할때 표시될 내요을 지정합니다. {0}은 접두사가 붙는 부분입니다.

 

[PersistenceMode(PersistenceMode.InnerProperty), DefaultValue(null)]
public virtual ITemplate View
{
    get;
    set;
}

protected override void CreateChildControls()
{
    Controls.Clear();

    ITemplate template = View;

    Panel p = new Panel();
    Controls.Add(p);

    if (template != null)
        template.InstantiateIn(p);
}

 

컨테이너 컨트롤인 WebCustomControl1 클래스 에는 화면에 표시될 ITemplate 내부 속성을 추가하고 디자이너 컨트롤을 생성할 CreateChildControls 메소드를 재정의합니다. 여기까지 하면 컨테이너 컨트롤의 내부를 모두 작성한 것입니다.

 

private WebCustomControl1 myControl;

 

이제 디자이너 컨트롤인 WebCustomControl1ControlDesigner 클래스를 작성합니다. 디자이너 컨트롤에서는 컨테이너 컨트롤에 직접 접근할 필요가 있으므로 WebCustomControl1 형식의 컨트롤변수를 생성합니다.

 

public override void Initialize(IComponent component)
{
    base.Initialize(component);
    myControl = (WebCustomControl1)component;
}

 

초기화 메소드를 재정의하여 위에서 선언한 myControl에 컨테이너 컨트롤을 담아두도록 합니다.

 

public override string GetDesignTimeHtml(DesignerRegionCollection regions)
{
    return DesignHtml();
}

 

컨트롤이 화면에 배치되면 GetDesignTimeHtml 메소드가 자동으로 호출되는데 디자인타임에 표시할 내용을 직접 작성할 것이므로 해당 메소드를 재정의합니다.

 

protected virtual string DesignHtml()
{
    StringBuilder sb = new StringBuilder();

    sb.Append(BeginDesignHtml());
    sb.Append(ContentDesignHtml());
    sb.Append(EndDesignHtml());

    return sb.ToString();
}

protected virtual String BeginDesignHtml()
{
    StringBuilder sb = new StringBuilder();
    sb.Append("<table border='10'>");
    sb.Append("<tr>");
    sb.Append("<td>");

    return sb.ToString();
}

protected virtual String EndDesignHtml()
{
    return "</tr></td></table>";
}

protected virtual String ContentDesignHtml()
{
    StringBuilder sb = new StringBuilder();
    sb.Append("디자인 화면");

    return sb.ToString();
}

 

GetDesignTimeHtml 메소드에서는 DesignHtml 이라는 메소드를 반환하는데 이때 DesignHtml 메소드가 진짜 디자인타임에 표시할 HTML을 생성하는 메소드입니다. 이 메소드는 BeginDesignHtml, ContentDesignHtml, EndDesignHtml 메소드를 차례로 호출하여 HTML 문자열을 얻는데 각각의 Html메소드를 보시면 실제 가져올 HTML의 내용을 구현하고 있습니다.

 

public override string GetEditableDesignerRegionContent(EditableDesignerRegion region)
{
    IDesignerHost host = (IDesignerHost)Component.Site.GetService(typeof(IDesignerHost));

    if (host != null)
    {
        ITemplate template = myControl.View;

        if (template != null)
            return ControlPersister.PersistTemplate(template, host);
    }

    return String.Empty;
}

public override void SetEditableDesignerRegionContent(EditableDesignerRegion region, string content)
{
    if (content == null) {
        myControl.View = null;
        return;
    }

    IDesignerHost host = (IDesignerHost)Component.Site.GetService(typeof(IDesignerHost));

    if (host != null) {
        ITemplate template = ControlParser.ParseTemplate(host, content);

        if (template != null)
            myControl.View = template;
    }
}

 

재정의한 GetEditableDesignerRegionContent 메소드와 SetEditableDesignerRegionContent 메소드는 각각 상황에 따라 필요한 HTML을 가져오거나 설정하기 위한 메소드입니다.

 

이제 컨트롤을 빌드 후 필요한 페이지에서 컨트롤을 끌어다 놓으면 디자인타임에 표시할 HTMl을 확인할 수 있습니다.

 

 

컨트롤을 작성할 시에 사용자로 부터 입력될 값은 속성을 통해 받을 수 있는데 이 속성의 특성에 따라 전용 편집기를 호출하여 속성값의 입력을 좀더 비주얼적으로 처리할 수 있습니다.

 

public string Url
{
    get
    {
        String s = (String)ViewState["Url"];
        return ((s == null) ? String.Empty : s);
    }

    set
    {
        ViewState["Url"] = value;
    }
}

 

예를 들어 위와 같이 Url 입력이 필요한 속성을 정의하였다면

 

[Editor(typeof(UrlEditor), typeof(UITypeEditor))]

 

해당 속성의 특성을 위와 같이 정의하여 Url입력에 필요한 입력상자를 호출할 수 있도록 처리할 수 있습니다.

0 0