검색 결과를 보여줄 컨트롤을 만듭시다. Windows Form 컨트롤 라이브러리 템플릿의 프로젝트를 추가하세요. 여기에서는 RankedUrlControlLib라고 정할게요.
이 프로젝트에서는 검색 결과 하나를 보여주는 RankedUrlControl과 검색 결과 목록을 보여주는 RUListControl을 만들어 봅시다.
마법사에서 기본으로 제공하는 컨트롤의 이름을 RankedUrlControl로 변경합시다. 그리고 자식 컨트롤을 배치합니다.
자식 컨트롤은 검색 결과 페이지의 타이틀과 주소를 보여주는 Label 컨트롤과 검색 사이트로 이동하는 Button 컨트롤, 검색 결과 페이지의 내용을 보여주는 TextBox 컨트롤, 평가 점수를 보여주는 Label 컨트롤을 배치합시다.
번호 | 컨트롤 이름 | 컨트롤 유형 | 설명 |
1 | lb_title | Label | 타이틀 |
2 | lb_addr | Label | 사이트 주소 |
3 | btn_go | Button | 바로가기 버튼 |
4 | tbox_content | TextBox | 페이지 내용 |
5 | lb_score | Label | 평가 점수 |
[표 11.1] RankedUrlControl의 자식 컨트롤
먼저 바로가기 버튼을 클릭했을 때 이벤트 처리를 위한 대리자와 인자 클래스를 정의합시다.
public delegate void RUrlClickEventHandler(object sender,RUrlClickEventArgs e); public class RUrlClickEventArgs:EventArgs { }
RUrlClickEventArgs 클래스에는 현재 결과를 보여주고 있는 순위화 한 페이지 개체를 가져오기 속성을 제공합니다.
public RankedUrl RUrl { get; private set; }
페이지 주소 가져오기 속성도 제공합시다.
public string Url { get { return RUrl.Url; } }
생성자 메서드는 컨트롤 라이브러 내부에서만 생성할 수 있게 접근성을 internal로 지정하고 입력 인자로 결과를 보여주고 있는 순위화 한 페이지 개체를 받습니다. 그리고 속성을 설정합니다.
internal RUrlClickEventArgs(RankedUrl rurl) { RUrl = rurl; }
ToString 메서드를 재정의하여 페이지 주소를 반환하게 합시다.
public override string ToString() { return Url; }
▷ RUrlClickEventArgs.cs
using System; using WSE_Core; namespace RankedUrlControlLib { /// <summary> /// RankedUrlControl 바로 가기 버튼 클릭 이벤트 핸들러 /// </summary> /// <param name="sender">이벤트 전송자</param> /// <param name="e">이벤트 처리 인자</param> public delegate void RUrlClickEventHandler(object sender,RUrlClickEventArgs e); /// <summary> /// RUrlClickEventHandler 이벤트 처리 인자 클래스 /// </summary> public class RUrlClickEventArgs:EventArgs { /// <summary> /// 순위화 한 페이지 - 가져오기 /// </summary> public RankedUrl RUrl { get; private set; } /// <summary> /// 웹 페이지 주소 - 가져오기 /// </summary> public string Url { get { return RUrl.Url; } } internal RUrlClickEventArgs(RankedUrl rurl) { RUrl = rurl; } /// <summary> /// ToString 메서드 재정의 /// </summary> /// <returns>웹 페이지 주소</returns> public override string ToString() { return Url; } } }
이제 순위화 한 페이지 정보를 보여주는 RankedUrlControl을 구현합시다.
public partial class RankedUrlControl : UserControl { }
멤버로 순위화 한 페이지 개체를 참조하는 필드를 선언합시다.
RankedUrl rurl;
그리고 바로가기 버튼의 클릭 이벤트를 멤버로 선언합니다.
public event RUrlClickEventHandler RUClick = null;
생성자 메서드는 마법사에 의해 만들어진 상태를 변경하지 않습니다.
public RankedUrlControl() { InitializeComponent(); }
순위화 한 페이지 개체를 설정하는 메서드를 제공합시다. 메서드의 입력 인자로 순위화 한 페이지 개체를 전달받습니다. 메서드 내부에서는 멤버 필드를 설정하고 각 컨트롤의 속성을 설정하는 작업을 수행합니다.
public void SetRankedUrl(RankedUrl rurl) { this.rurl = rurl; lb_title.Text = rurl.PUrl.Title; lb_addr.Text = rurl.Url; tbox_content.Text = rurl.PUrl.Content; lb_score.Text = rurl.Score.ToString(); }
바로가기 버튼 클릭 이벤트 핸들러를 추가합니다.
private void btn_go_Click(object sender, EventArgs e)
이벤트 핸들러에서는 클릭 이벤트 멤버가 null이 아니면 설정한 클릭 이벤트가 있는 것이므로 순위화 한 페이지 개체를 입력 인자로 전달하여 이벤트를 Invoke 시킵니다.
if (RUClick != null) { RUClick (this, new RUrlClickEventArgs(rurl)); }
▷ RankedUrlControl.cs
using System; using System.Windows.Forms; using WSE_Core; namespace RankedUrlControlLib { /// <summary> /// 순위화 한 페이지 정보 컨트롤 /// </summary> public partial class RankedUrlControl : UserControl { RankedUrl rurl; /// <summary> /// 바로가기 버튼 클릭 이벤트 /// </summary> public event RUrlClickEventHandler RUClick = null; /// <summary> /// 생성자 메서드 /// </summary> public RankedUrlControl() { InitializeComponent(); } /// <summary> /// 순위화 한 페이지 설정 메서드 /// </summary> /// <param name="rurl"></param> public void SetRankedUrl(RankedUrl rurl) { this.rurl = rurl; lb_title.Text = rurl.PUrl.Title; lb_addr.Text = rurl.Url; tbox_content.Text = rurl.PUrl.Content; lb_score.Text = rurl.Score.ToString(); } private void btn_go_Click(object sender, EventArgs e) { if (RUClick != null) { RUClick (this, new RUrlClickEventArgs(rurl)); } } } }
이번에는 검색 결과를 포함하는 컬렉션 컨트롤을 정의합시다. 새 항목 추가에서 사용자 정의 컨트롤을 추가하세요. 여기서는 RUListControl이라 정할게요.
RUListControl에는 자식 컨트롤로 RankedUrlControl을 보여주기 위함이며 검색 결과를 이용하여 동적으로 추가하는 작업을 수행합니다. 기본적인 자식 컨트롤을 배치하는 부분은 없습니다.
public partial class RUListControl : UserControl { }
결과 항목을 자식으로 두어야 하므로 RankedUrlControl을 보관하는 컬렉션을 멤버가 있어야 합니다.
List<RankedUrlControl> children = new List<RankedUrlControl>();
자식 컨트롤의 바로가기 버튼을 클릭하였을 때의 클릭 이벤트를 멤버로 선언합시다. 이는 RUListControl을 소유한 곳에서 처리하기 위한 이벤트 핸들러를 설정할 멤버입니다.
public event RUrlClickEventHandler RUClick = null;
생성자 메서드는 마법사에서 제공하는 것에서 변경할 것이 없습니다.
public RUListControl() { InitializeComponent(); }
결과 목록을 지우는 메서드도 제공합시다. 여기에서는 자식 컨트롤을 Dispose한 이후에 컨트롤 목록을 지웁니다.
public void Clear() { foreach (RankedUrlControl rucon in children) { rucon.Dispose(); } children.Clear(); }
결과 항목을 추가하는 메서드를 제공합시다. 입력 인자로는 검색 결과인 순위화 한 페이지 개체를 받습니다.
public void AddRankedUrl(RankedUrl rurl)
결과 항목을 보여줄 RankedUrlControl 개체를 생성하여 순위화 한 페이지 개체를 입력 인자로 설정합니다.
RankedUrlControl rucon = new RankedUrlControl(); rucon.SetRankedUrl(rurl);
화면에 생성한 컨트롤을 배치하는데 이는 현재 추가한 자식의 개수에 따라 위치를 계산하여 배치합니다. 수치는 여러분이 작성하는 것에 맞게 설정하세요.
int ruc_cnt = children.Count; rucon.Location = new Point(0, ruc_cnt * 200 + 24); rucon.Height = 200; rucon.Width = this.Width - 24; rucon.Parent = this; children.Add(rucon);
그리고 자식 컨트롤을 클릭했을 때의 이벤트 핸들러를 등록합니다.
rucon. RUClick += new RUrlClickEventHandler(rucon_Click);
이벤트 핸들러에서는 자신을 포함하고 있는 곳에서 클릭 이벤트 핸들러를 등록한 것이 있으면 전달받은 이벤트를 bypass 해줍니다.
void rucon_Click(object sender, RUrlClickEventArgs e) { if (RUClick != null) { RUClick (sender, e); } }
▷ RUListControl.cs
using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; using WSE_Core; namespace RankedUrlControlLib { /// <summary> /// 결과 항목 컨트롤 /// </summary> public partial class RUListControl : UserControl { List<RankedUrlControl> children = new List<RankedUrlControl>(); /// <summary> /// 바로가기 버튼 클릭 이벤트 /// </summary> public event RUrlClickEventHandler RUClick = null; /// <summary> /// 생성자 메서드 /// </summary> public RUListControl() { InitializeComponent(); } /// <summary> /// 자식 항목 지우기 메서드 /// </summary> public void Clear() { foreach (RankedUrlControl rucon in children) { rucon.Dispose(); } children.Clear(); } /// <summary> /// 결과 항목 추가 메서드 /// </summary> /// <param name="rurl">순위화 한 페이지 개체</param> public void AddRankedUrl(RankedUrl rurl) { RankedUrlControl rucon = new RankedUrlControl(); rucon.SetRankedUrl(rurl); int ruc_cnt = children.Count; rucon.Location = new Point(0, ruc_cnt * 200 + 24); rucon.Height = 200; rucon.Width = this.Width - 24; rucon.Parent = this; rucon. RUClick += new RUrlClickEventHandler(rucon_Click); children.Add(rucon); } void rucon_Click(object sender, RUrlClickEventArgs e) { if (RUClick != null) { RUClick (sender, e); } } } }