Et site med kursusmaterialer, der bruges i forbindelse med undervisning i forskellige it relaterede emnerEn skøn grafik du kan nyde mens der undervises.
   

Send spørgsmål eller kommentar til Thor - klik her: Send en kommentar til Thor - omkring undervisning eller kursus  Søg i kursusmaterialerne. Kan bruges i forbindelse med undervisningen eller efter kurset  Til forsiden af kursusmaterialer.dk 

 

ASP.NET III / Custom controls / Rendered kontroller


ASP.NET fjernundervisningskursus

- Vil du gerne på kursus NU?

- Vil du gerne lære i dit eget tempo?

- Har du ikke tid til at tage på kursus ude i byen?

Så køb et kursus i ASP.NET som fjernundervisning på www.it-fjernundervisning.dk


Renderede kontroller

Disse kontroller minder meget om custom kontroller - den eneste forskel er, at man bygger deres visuelle udseende alene ved hjælp af HTML elementer. Det betyder, at man ikke har de indbyggede egenskaber, metoder og hændelser til at hente og vise data - man må kode det hele i hånden.

Metoden til at etablere disse kontroller minder meget om processen bag custom kontroller:

  1. Opret et custom control projekt
  2. Etablér et test projekt
  3. Opret reference fra test projektet til custom control projektet
  4. Etabler kontrollens visuelle udtryk ved at overskrive Render metoden
  5. Skriv den kode der skal til for at reagere på brugerens input

Etabler det visuelle udtryk

Til etablering af det visuelle udtryk kan man bruge HtmlTextWriter

 

MetodeBeskrivelse
AddAttributeTilføjer en attribut til det næste HTML element, der skal behandles
RenderBeginTagKlargør begyndelses tagget til et HTML element, der senere kan skrives med WriteLine metoden
RenderEndTagKargør slut tagget til et HTML element og skriver hele elementet sammen med eventuelle attributter
WriteSkriver en streng
WriteAttribute

Skriver en HTML attribut med det samme

WriteBeginTagSkriv med det samme et HTML start tag
WriteEndTagSkriv med det samme slutningen af et HTML tag
WriteFullBeginTagSkriver begyndelses tagget til et HTML element inklusive >
WriteLineSkriver en indholdslinje inklusive et linjeskift

 

Et eksempel

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

//
namespace Klassebibliotek
{
 public class Renderet : System.Web.UI.WebControls.WebControl
 {
  protected override void Render(HtmlTextWriter output)
  {
   output.Write("<h3>En HTML kontrol</h3>");
   output.WriteBeginTag("INPUT");
   output.WriteAttribute("value","En knap");
   output.WriteAttribute("type", "button");
   output.WriteAttribute("onclick", "javascript:alert('Hej med dig')");
   output.WriteEndTag("INPUT");
  }
 }
}

Det samme kan også skrives sådan her:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
//
namespace Klassebibliotek
{
 public class Renderet : System.Web.UI.WebControls.WebControl
 {
  protected override void Render(HtmlTextWriter output)
  {
   output.Write("<h3>En HTML kontrol</h3>");
   output.AddAttribute("value","En knap");
   output.AddAttribute("type", "button");
   output.AddAttribute("onclick", "javascript:alert('Hej med dig igen')");
   output.RenderBeginTag("INPUT");
   output.RenderEndTag();
  }
 }
}

Gemme egenskaber

Vi bliver nødt til at bruge ViewState, hvis vi vil gemme informationer mellem sidevisninger:

  public string Text
  {
   get
   {
   if (ViewState["Text"] != null)
    return ViewState["Text"].ToString();
   else
    return null;
   }
   set
   {
    ViewState["Text"] = value;
   }
  }

Adgang til tekst på siden

For at få adgang til indholdet af de html tags, der er på en custom kontrol gøres følgende:

  1. Tilføj en ParseChildren attribut til kontrollens klasse definition
  2. Impelementer INamingContainer interfacet til klassen
  3. Hent teksten ved at bruge Controls samlingen

Et ekempel:

[ParseChildren(false)]
 public class Center : System.Web.UI.WebControls.WebControl, INamingContainer
 {
  protected override void Render(HtmlTextWriter output)
  {
   output.AddAttribute("align","center");
   output.AddStyleAttribute("BACKGROUND-COLOR","red");
   output.RenderBeginTag("div");
   foreach (Control ctrItem in Controls)
   {
    ctrItem.RenderControl(output);
   }
   output.RenderEndTag();
  }
 }

Denne kontrol vil centere og give rød baggrundsfarve på alle koder inde i kontrollen:

<cc1:Center id="Center" runat="server"><h2>Hej med dig</h2></cc1:Center>

Reagere på bruger handlinger

Vi har, som bekendt to typer af events vi kan reagere på

  1. Cached events, der kan blive rejst fra koden
  2. Post-Back events må rejses på klienten gennem et script kontrollen skaber

Cached events

Vi skal gøre to ting for at rejse en cached event:

  1. Definere en event vi til rejse
  2. Rejse eventet et sted i koden

Et eksempel:

 [DefaultEvent("Change")]
 public class Events : System.Web.UI.WebControls.WebControl
 {
  public event EventHandler Change;
  //
  public string Text 
  {  
   get  
   {  
    if (ViewState["Text"] != null)    
     return ViewState["Text"].ToString();  
    else   
     return null;  
   }  
   set   
   {   
    ViewState["Text"] = value;  
    OnChange(EventArgs.Empty);
   } 
  }
  //
  protected virtual void OnChange(EventArgs e)
  {
   if (Change != null)
    Change(this,e);
  }
  //
  protected override void Render(HtmlTextWriter output)
  {
   output.AddAttribute("value", this.Text);
   output.RenderBeginTag("input");
   output.RenderEndTag();
  }
 }

Og koden her kan bruges til at håndtere hændelsen:

private void txtTest_Change(object sender, System.EventArgs e)
  {
   Response.Write("Teksten er ændret");
  }

PostBack events

For at rejse et postback event fra en kontrol skal følgende gøres:

  1. Implementer IPostBackEventHandler interfacet på kontrollen
  2. Erklær et event der skal rejses
  3. Etabler en html kontrol, der kan reagere på client-side events
  4. Tilføj en attribut til det html element, der sørger for at poste siden tilbage til serveren
  5. Rejs eventet fra RaisePostBackEvent metoden, der er en del af IPostBackEventHandler interfacet

Et eksempel

 [DefaultEvent("Click")]
 public class Events : System.Web.UI.WebControls.WebControl, IPostBackEventHandler
 {
  public event EventHandler Change;
  public event EventHandler Click;
  //
  public string Text 
  {  
   get  
   {  
    if (ViewState["Text"] != null)    
     return ViewState["Text"].ToString();  
    else   
     return null;  
   }  
   set   
   {   
    ViewState["Text"] = value;  
    OnChange(EventArgs.Empty);
   } 
  }
  //
  protected virtual void OnChange(EventArgs e)
  {
   if (Change != null)
    Change(this,e);
  }
  //
  protected override void Render(HtmlTextWriter output)
  {
   output.Write("<h3>Rendered kontrol</h3>");
   output.AddAttribute("value","En knap");
   output.AddAttribute("type","button");
   output.AddAttribute("onclick","javascript:alert('Hej med dig');"+
       Page.GetPostBackEventReference(this));
   output.RenderBeginTag("INPUT");
   output.RenderEndTag();
   output.AddAttribute("value", this.Text);
   output.RenderBeginTag("input");
   output.RenderEndTag();
  }
  //
  public void RaisePostBackEvent(string eventArgument)
  {
   OnClick(EventArgs.Empty);
  }
  //
  protected virtual void OnClick(EventArgs e)
  {
   if (Click != null)
    Click(this,e);
  }
 }

Og som ovenfor kan man skrive en eventhandler til at håndtere hændelsen:

private void txtTest_Click(object sender, System.EventArgs e)
  {
   Response.Write("Klik");
  }

Hente data fra brugeren

Disse kontroller bevarer ikke automatisk data, som brugeren har indtastet. Det kan man se, hvis man danner en Tekstboks kontrol ved at bruge et <input> element - indholdet vil forsvinde hver gang siden har været rundt om serveren.

Får at komme dette problem til livs skal man gøre følgende:

  1. Implementer IPostPackDataHandler interfacet
  2. Tilføje en name attribut for at kunne identificere html elementet
  3. Overskriv LoadPostBackData metoden fra IPostBackDataHandler interfacet. Brug denne metode til at få fat i informationerne fra brugeren
  4. Overskriv RaisePostDataChangedEvent metoden fra IPostBackDataHandler interfacet - man behøver ikke at skrive kode for denne metode, men man må overskrive det fordi det er en del af interfacet
  5. Rejs en event for at indikere, at data er blevet ændret (dette behøver man ikke at gøre)

Et eksempel:

[DefaultProperty("Text"), DefaultEvent("Change")]
 public class BevarData : System.Web.UI.WebControls.WebControl, IPostBackDataHandler
 {
  public event EventHandler Change;
  //
  [DefaultValue("")]
  public string Text
  {
   get
   {
    if (ViewState["Text"] != null)
     return ViewState["Text"].ToString();
    else
     return null;
   }
   set
   {
    ViewState["Text"] = value;
    OnChange(EventArgs.Empty);
   }
  }
  //
  protected override void Render(HtmlTextWriter output)
  {
   output.AddAttribute("value",this.Text);
   output.AddAttribute("name",this.UniqueID);
   output.RenderBeginTag("Input");
   output.RenderEndTag();
  }
  //
  public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
  {
   if (this.Text != postCollection[postDataKey])
   {
    this.Text = postCollection[postDataKey];
    return true;
   }
   else
    return false;
  }
  //
  public void RaisePostDataChangedEvent()
  {
   OnChange(EventArgs.Empty);
  }
  //
  public virtual void OnChange(EventArgs e)
  {
   if (Change != null)
    Change(this,e);
  }
 }

   
Spacer Spacer Spacer Spacer