ASP.NET 별점 사용자 지정 컨트롤 별점 별점 컨트롤

11096 단어
1. 인용문
이전 몇 번의 작업에서 개발된 성급 컨트롤러는 정적 전시에만 적용된다. 예를 들어 특정한 소프트웨어의 인기도를 표시하는 것이다. 그러나 실제로 많은 사이트들이 사용자가 특정한 정보에 대해 점수를 매기고 최종적으로 이 정보의 인기도를 계산하여 데이터를 더욱 객관적이고 신뢰할 수 있도록 하기 때문에 기존의 성급 컨트롤러에 개선을 해야 한다.실제 효과도는 다음과 같이 동적으로 점수를 매길 수 있습니다.
그림의 첫 번째 줄은 평점 후 컨트롤의 상태로 개발자가 평점 이벤트를 처리하고 페이지에서 선택한 점수를 출력했다.그림의 두 번째 행에는 별표 패턴으로 마우스가 이동한 채점 상태가 표시됩니다. 이때 빨간색 별표를 사용하여 사용자에게 알립니다.
  2. 분석하다.
이 컨트롤에 대해 우리는 기존 컨트롤을 바탕으로 두 가지 특성을 추가해야 한다.
  1. 마우스 띄우기 표시를 넣으면 마우스가 멈출 때 사용자가 선택한 점수를 표시합니다.
  2. 마우스 클릭 시 서버에 전송되고 해당 사건을 노출시켜 개발자가 처리할 수 있다.
첫 번째 요구 사항은 자바스크립트의 마우스 이벤트를 처리할 수 있습니다. onmouseover 이벤트를 터치할 때 현재 마우스가 몇 번째 별 모양에 걸려 있는지 판단하고 빨간색 별 모양을 표시합니다.패턴을 표시하는 방법도 있습니다. 원래 별 패턴이 표시된 레이어(div)에 레이어를 중첩하고 레이어의 배경을 빨간색 별 패턴으로 설정하면 페이지가 로드될 때 레이어가 표시되지 않아야 합니다(너비 0으로 설정하면 됩니다). 그리고 마우스가 지나갈 때 레이어의 너비를 설정합니다. 이 레이어가 배경 레이어를 덮어쓸 수 있도록 주의하면 됩니다.
마찬가지로 마우스를 옮길 때 이 층을 숨겨야 한다. 그러면 onmouseout 이벤트를 처리하고 층의 폭을 다시 0으로 설정하면 숨겨진 층의 목적을 달성할 수 있다.
두 번째 요구 사항은 개발자가 이 이벤트를 구독할 수 있도록 사용자 정의 컨트롤에 공개 이벤트를 노출하는 것이다. 다음은 클라이언트가 리셋 스크립트를 만들어서 (JavaScript의 onclick 이벤트 트리거) 를 눌렀을 때 이 리셋 스크립트를 실행하여 서버에 제출하면 된다.
리셋 스크립트를 만들기 위해 사용자 정의 컨트롤러가 IPostBack EventHandler 인터페이스를 실현하도록 합니다. 이 인터페이스는 ASP를 정의합니다.NET 서버 컨트롤이 반환 이벤트를 처리하기 위해 반드시 수행해야 하는 방법입니다.
서버에 제출한 후에 사용자 정의 컨트롤러가 공개된 이벤트를 호출하고 별 모양 도안을 노란색 배경 표지 사용자 평점으로 바꿔야 한다. 그러면 우리는 배경 층에 한 층을 추가하고 첫 번째 수요와 같은 알고리즘으로 배경 층을 덮어쓰면 된다.
확인이 필요한 것은 사용자가 점수를 매긴 후에 다시 점수를 매기는 것을 허용하지 않는다는 것이다. (사용자가 현재 마우스를 멈추고 점수를 선택한 층을 숨기면 된다.)
마지막으로 고려해야 할 문제는 사용자 정의 컨트롤에 서버 사이드 컨트롤을 용기로 그림을 표시하는 것이다. 페이지에 여러 개의 사용자 정의 컨트롤을 설치하는 데 문제가 발생하지 않도록 각 서버 사이드 컨트롤이 생성한 클라이언트 번호가 유일하다는 것을 보증해야 한다. 해결 방법은 바로 INamingContainer 인터페이스를 실현하는 것이다.
  3. 이루어지다
3.1 ControlSolution 솔루션의 ControlLibrary 라이브러리에서 WebControl에서 계승된 PostStart 클래스를 만들고 IPostBack Event Handler와 INamingContainer 인터페이스를 실현한다.using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace ControlLibrary
{
  public class PostStar :
  WebControl,IPostBackEventHandler,INamingContainer
  {
  }
}

3.2 사용자 정의 컨트롤에 대한 점수 및 주석 속성을 추가합니다.[DefaultValue(0)]
public int Score
{
  get
  {
    object obj = ViewState["Score"];
    return obj == null ? 0 : Convert.ToInt32(obj);
  }
  internal set
  {
    ViewState["Score"] = value;
  }
}
public string Comment
{
  get
  {
    object obj = ViewState["Comment"];
    return obj == null ? string.Empty : Convert.ToString(obj);
  }
  set
  {
    ViewState["Comment"] = value;
  }
}
3.3CreatechildControls 방법을 다시 써서 하위 컨트롤 차원을 만들고 이 방법에서CreatectrolHierarchy 방법을 호출했습니다. protected override void CreateChildControls()
{
  base.CreateChildControls();
  CreateControlHierarchy();
}
3.4 Create ControlHierarchy 메서드를 작성합니다. 이 메서드에서 먼저 하위 컨트롤 컬렉션에 1열 2열의 테이블을 만들고 다음에CreateComment 메서드를 사용하여 첫 페이지에서 주석을 출력한 다음에CreateStart 메서드를 사용하여 별 모양 패턴을 만듭니다.protected virtual void CreateControlHierarchy()
{
  Table table = new Table();
  TableRow row = new TableRow();
  table.Rows.Add(row);
  TableCell comment = new TableCell();
  CreateComment(comment);
  row.Cells.Add(comment);
  TableCell stars = new TableCell();
  CreateStars(stars);
  row.Cells.Add(stars);
  this.Controls.Add(table);
}
3.5는CreateComment 방법을 실현하고 설명 텍스트를 칸에 간단하게 값을 부여하는Text 속성: private void CreateComment(TableCell cell)
{
  cell.Text = Comment;
}
3.6 별 모양을 만드는 CreateStars 방법을 작성한다. 이 방법에서는RegisterCSS 방법으로 페이지에 등록하는 CSS 스타일시트 파일(이 파일은 자원 파일로 발표)을 호출했다. 다음에는CreateBackPanel,CreatecurrentPanel,그리고CreateChangePanel 방법으로 배경층을 만드는 데 사용한다.선택한 이후의 레이어와 현재 마우스가 멈춰 있음을 나타내는 레이어를 식별하고 CreateList 메소드를 사용하여 목록을 작성하고 계층 구조에 따라 레이어와 목록을 구성합니다(Panel 컨트롤을 사용하여 레이어를 나타냅니다).private void CreateStars(TableCell cell)
{
  RegisterCSS();
  string starPath = Page.ClientScript.GetWebResourceUrl(this.GetType(), "ControlLibrary.Image.stars.gif");
  Panel panBg = CreateBackPanel(starPath);      
  cell.Controls.Add(panBg);
  Panel panCur = CreateCurrentPanel(starPath);      
  Panel panChange =CreateChangePanel(starPath);
  HtmlGenericControl ul = CreateList();
  panBg.Controls.Add(ul);
  panBg.Controls.Add(panCur);
  panCur.Controls.Add(panChange);          
}

3.7 RegisterCSS 방법을 사용하여 스타일시트 리소스 파일을 가져오고 HtmlLink 클래스를 사용하여 스타일시트를 등록합니다.private void RegisterCSS()
{
  string css = Page.ClientScript.GetWebResourceUrl(this.GetType(),
   "ControlLibrary.CSS.star.css");
  HtmlLink link = new HtmlLink();
  link.Href = css;
  link.Attributes.Add("rel", "stylesheet");
  link.Attributes.Add("type", "text/css");
  Page.Header.Controls.Add(link);
}

3.8 CreateBackPanel, CreateCurrentPanel, CreateChangePanel 및 CreateList 메소드를 작성하여 다음을 수행합니다.private Panel CreateBackPanel(string starPath)
{
  Panel panBg = new Panel();
  panBg.ID = "divBg";
  panBg.Style.Add(HtmlTextWriterStyle.BackgroundImage, starPath);
  
  panBg.CssClass = "stars";
  return panBg;
}
private Panel CreateCurrentPanel(string starPath)
{
  Panel panCur = new Panel();
  panCur.ID = "divCur";
  panCur.Style.Add(HtmlTextWriterStyle.BackgroundImage, starPath);
  panCur.CssClass = "current";
  return panCur;
}
private Panel CreateChangePanel(string starPath)
{
  Panel panChange = new Panel();
  panChange.ID = "divChange";
  panChange.Style.Add(HtmlTextWriterStyle.BackgroundImage, starPath);
  
  panChange.CssClass = "change";
  return panChange;
}
private HtmlGenericControl CreateList()
{
  HtmlGenericControl ul = new HtmlGenericControl("ul");
  ul.ID = "ulist";
  
  ul.Attributes.Add("class", "ulist");
  for (int i = 0; i < 5; i++)
  {
    HtmlGenericControl li = new HtmlGenericControl("li");
    li.Attributes.Add("value", (i + 1).ToString());
            
    ul.Controls.Add(li);
  }
  return ul;
}
3.10 Render 다시 쓰기 방법은 컨트롤을 나타냅니다. 이 방법은 PrepareControlForReader 방법을 호출했습니다. protected override void Render(HtmlTextWriter writer)
{
  PrepareControlForRender();
  base.Render(writer);
}
3.11 PrepareControlForRender를 구현하여 목록의 목록 항목을 컨트롤 수준에서 제거하고 JavaScript 이벤트를 등록합니다.private void PrepareControlForRender()
{
  if (this.Controls.Count < 1)
    return;
  Table table = (Table)this.Controls[0];
  table.CellSpacing = 0;
  table.CellPadding = 0;
  TableCell cell = table.Rows[0].Cells[1];
  Panel panCur = (Panel)cell.Controls[0].Controls[1];
  Panel panChange = (Panel)panCur.Controls[0];
  HtmlGenericControl ul = (HtmlGenericControl)cell.Controls[0].Controls[0];
  for (int i = 0; i < ul.Controls.Count; i++)
  {
    HtmlGenericControl li = (HtmlGenericControl)ul.Controls[i];
    li.Attributes.Add("onmouseover", "document.getElementById('" + panChange.ClientID + "').style.width='" + 16 * (i + 1) + "px';");
    li.Attributes.Add("onmouseout", "document.getElementById('" + panChange.ClientID + "').style.width='0px';");
    li.Attributes.Add("onclick", Page.ClientScript.GetPostBackClientHyperlink(this, (i + 1).ToString()));
  }
}

목록 항목의 클릭 이벤트 (onclick) 에서 서버 리셋을 촉발한 것을 볼 수 있습니다. 여기는 Page를 통해 보입니다.ClientScript.GetPostBackClientHyperlink 방법으로 완성된 이 방법은 두 개의 파라미터를 전달한다. 첫 번째 파라미터는 리셋을 일으키는 서버 컨트롤을 인용하고 두 번째 파라미터는 리셋할 때 전달하는 파라미터를 표시하며 여기에 성형 도안의 인덱스를 전달한다.
목록을 만드는 동시에 JavaScript 스크립트를 등록하지 않는 이유는 CreateChildControls 메소드가 실행될 때 각 서버 측 컨트롤의 ClientID가 생성되지 않았기 때문입니다. 이 때 등록된 스크립트가 클라이언트 작업 중 오류가 발생할 수 있습니다.
3.12 이벤트를 트리거하기 위해 먼저 이벤트 매개 변수 클래스 StarEventArgs를 작성합니다. 이 클래스는 Score 속성 저장 점수를 정의합니다.public class StarEventArgs : EventArgs
{
  public int Score
  {
    get;
    set;
  }
}
3.13 PostStar에서 이벤트 속성을 선언합니다. 여기서는 이전 작업과 다릅니다.이벤트를 개인 필드로 표시하고 속성을 통해 노출 (이전의 사용법보다 이런 사용법을 추천합니다): private event EventHandler _postScore;
public event EventHandler PostScore
{
  add
  {
    _postScore += value;
  }
  remove
  {
    _postScore -= value;
  }
}
3.14 OnPostScore 방법으로 이벤트를 호출하고 컨트롤 차원에서 상응하는 층을 얻어 고정된 점수를 표시합니다: private void OnPostScore(object sender, StarEventArgs e)
{
  if (_postScore != null)
    _postScore(sender, e);
  TableCell cell = ((Table)this.Controls[0]).Rows[0].Cells[1];
  Panel panCur = (Panel)cell.Controls[0].Controls[1];
  panCur.Style.Add("width", e.Score * 16 + "px");
  Panel panChange = (Panel)panCur.Controls[0];
  panChange.Style.Add("display", "none");
  HtmlGenericControl ul =
  (HtmlGenericControl)cell.Controls[0].Controls[0];
  ul.Style.Add("display", "none");
}
3.15 IPostBack Event Handler 인터페이스를 실현하는 RaisePostBack Event 방법클라이언트가 서버 리셋을 일으킨 후에 이 방법을 실행하고 해당하는 매개 변수를 전달합니다. 우리는 이 방법에서 모든 하위 컨트롤을 만든 후에 해당하는 이벤트를 일으켜 속성을 설정하기만 하면 됩니다. public void RaisePostBackEvent(string args)
{
  if (!string.IsNullOrEmpty(args))
  {
    EnsureChildControls();
    int score = Convert.ToInt32(args);
    StarEventArgs e = new StarEventArgs();
    e.Score = score;
    OnPostScore(this, e);
  }
}
3.16 웹 사이트에서 테스트 페이지를 만들고 사용자 정의 컨트롤을 등록 및 선언합니다.   Namespace=?ControlLibrary? %>
  OnPostScore="star_PostScore" />
부록: 스타일시트 파일: .stars {width: 80px; height: 16px; text-align: left; overflow: hidden; position: relative; background: url(stars.gif) 0px -32px repeat-x;}
.stars .ulist { list-style: none; position: absolute; bottom:0px; margin:0px; padding: 0; }
.stars .ulist li { display: inline; float: left; width: 16px; height: 16px; cursor: pointer; overflow: hidden; }
.stars .current {width: 0px; height: 16px; background: url(stars.gif) 0px 0px repeat-x;}
.stars .change {width: 0px; height: 16px; background: url(stars.gif) 0px -16px repeat-x;}
4.총결산
이번 작업에서 우리는 사용자가 점수를 매길 수 있는 사용자 정의 컨트롤을 만들었습니다. PostStart 클래스는 IPosteventHandler 인터페이스를 계승하여 서버 제출을 유발했습니다. 이 인터페이스를 도입하면 필요에 따라 서버 제출을 유발할 수 있습니다. 해당하는 자바스크립트 이벤트를 등록하기만 하면 됩니다.또한 페이지에 여러 채점 컨트롤을 사용할 때 오류가 발생하지 않도록 INamingContainer 인터페이스를 구현했습니다.

좋은 웹페이지 즐겨찾기