by Piotrosz
31. October 2008
TemplateControl oddziela warstwę prezentacji kontrolki od danych, jakie ta kontrolka zawiera. Aby stworzyć własną TemplateControl należy:
1. Dodać do strony nową WebUserControl:
2. W pliku .ascx dodać kontrolkę PlaceHolder z ToolBoxa:
3. Nazwać PlaceHolder (tutaj PlaceHolder ma nazwę OsobaPlaceHolder):
4. W pliku code behind WebUserControl dodać właściwość ITemplate wraz z odpowiednimi atrybutami:
private ITemplate _osobaTemplate;
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(OsobaContainer))]
public ITemplate OsobaTemplate
{
get { return _osobaTemplate; }
set { _osobaTemplate = value; }
}
5. Dodać właściwości kontrolki reprezentujące dane (tutaj imie i nazwisko osoby):
private string _imie;
public string Imie
{
get { return _imie; }
set { _imie = value; }
}
private string _nazwisko;
public string Nazwisko
{
get { return _nazwisko; }
set { _nazwisko = value; }
}
6. Dodać kod w metodzie Page_Init:
public void Page_Init()
{
OsobaPlaceHolder.Controls.Clear();
if (OsobaTemplate == null)
{
LiteralControl lc = new LiteralControl();
lc.Text = "";
lc.Text += "Szablon kontrolki nie został jeszcze zdefiniowany!";
OsobaPlaceHolder.Controls.Add(lc);
return;
}
OsobaContainer s = new OsobaContainer(Imie, Nazwisko);
OsobaTemplate.InstantiateIn(s);
OsobaPlaceHolder.Controls.Add(s);
}
Pełny kod w pliku code behind:
public partial class Playground_Controls_TemplatedControl : System.Web.UI.UserControl
{
private ITemplate _osobaTemplate;
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(OsobaContainer))]
public ITemplate OsobaTemplate
{
get { return _osobaTemplate; }
set { _osobaTemplate = value; }
}
private string _imie;
public string Imie
{
get { return _imie; }
set { _imie = value; }
}
private string _nazwisko;
public string Nazwisko
{
get { return _nazwisko; }
set { _nazwisko = value; }
}
public void Page_Init()
{
OsobaPlaceHolder.Controls.Clear();
if (OsobaTemplate == null)
{
OsobaPlaceHolder.Controls.Add(new LiteralControl("Szablon kontrolki nie został jeszcze zdefiniowany!"));
return;
}
OsobaContainer s = new OsobaContainer(Imie, Nazwisko);
OsobaTemplate.InstantiateIn(s);
OsobaPlaceHolder.Controls.Add(s);
}
}
7. Dodać do katalogu App_Code klasę dziedziczącą po Control i implementującą INamingContainer (tutaj to klasa o nazwie OsobaContainer):
public class OsobaContainer : Control, INamingContainer
{
public OsobaContainer(string imie, string nazwisko)
{
this._imie = imie;
this._nazwisko = nazwisko;
}
private string _imie;
public string Imie
{
get { return _imie; }
set { _imie = value; }
}
private string _nazwisko;
public string Nazwisko
{
get { return _nazwisko; }
set { _nazwisko = value; }
}
}
Używanie kontrolki:
Po dodaniu kontrolki na stronę (bez zdefiniowania szablonu powiwieni pokazać się komunikat zdefiniowany wcześniej w metodzie Page_Init kontrolki:
Po zdefiniowaniu szablonu i dodaniu do metody Page_Load wywołania DataBind():
Imie: <%# Container.Imie %>
Nazwisko: <%# Container.Nazwisko %>
public void Page_Load()
{
DataBind();
}
Zobacz wynik
by Piotrosz
29. October 2008
Przykład wyjaśniający jak działają metody HtmlEncode i HtmlDecode. Na stronie aspx jest etykieta o nazwie lbl oraz pole tekstowe o nazwie txt.

Podgląd w debuggerze właściwości Text etykiety i pola tekstowego:
Wynik działania strony:
Zobacz wynik
by Piotrosz
28. October 2008
Aby zdefiniować własny atrybut należy najpierw stworzyć własną klasę dziedziczącą z System.Attribute:
using System;
using System.Collections.Generic;
using System.Text;
namespace CustomAttributes
{
// Określenie do jakich elementów można zastosować atrybut i czy można stosowac go wielokrotnie
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field |
AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)]
public class CustomComment : System.Attribute
{
public CustomComment (string person, string date)
{
this.person = person;
this.date = date;
}
private string comment;
public string Comment
{
get { return comment; }
set { comment = value; }
}
private string date;
public string Date
{
get { return date; }
}
private string person;
public string Person
{
get { return this.person; }
}
}
}
Przykład zastosowania atrybutu dla jakiejś klasy:
[CustomComment("Piotr", "2008-10-10", Comment="Pierwszy atrybut")]
[CustomComment("Piotr", "2008-10-11", Comment="Drugi atrybut")]
public class ClassTest
{
}
Wyświetlenie atrybutów dla stworzonej w programie klasy ClassTest poprzez zastosowanie refleksji:
class Program
{
static void Main(string[] args)
{
ClassTest ct = new ClassTest();
MemberInfo minf = typeof(ClassTest);
object [] attribs = minf.GetCustomAttributes(typeof(CustomComment), false);
foreach (object var in attribs)
{
CustomComment cc = (CustomComment)var;
Console.WriteLine(string.Format("Osoba: {0}", cc.Person));
Console.WriteLine(string.Format("Data: {0}", cc.Date));
Console.WriteLine(string.Format("Komentarz: {0}", cc.Comment));
}
}
}
Wynik działania:

by Piotrosz
21. October 2008
Aby w stronie z zawartością w łatwy sposób odwołać się do MasterPage należy:
1. Zdefiniować publiczną zmienną w klasie strony MasterPage (Tutaj jest to zmienna UlubionyOwoc).
public partial class MasterPage_MasterPage : System.Web.UI.MasterPage
{
public string UlubionyOwoc
{
get { return ddlOwoce.SelectedValue; }
}
}
Oczywiście na stronie MasterPage.master jest kontrolka DropDownList z listą owoców.
2. Na stronie, z zawartością chcemy dotać się do zmiennej zdefiniowanej w pliku MasterPage.master.cs. W tym celu dodajemy dyrektywę:
<%@ MasterType VirtualPath="~/MasterPage.master" %>
Ta dyrektywa sprawia, że właściwość klasy MasterPage jest typowana. Dodać można teraz np. taki fragment kodu:
public partial class MasterPage_AccessingMasterPageProperty : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
lbl1.Text = "W MasterPage zaznaczyłeś: " + Master.UlubionyOwoc;
}
}
Zobacz wynik
by Piotrosz
18. October 2008
Kod w pliku .aspx:
Przywitaj się oficjalnie
Przywitaj się nieoficjalnie
Kod w pliku .cs:
public partial class CommandButtonTest : System.Web.UI.Page
{
protected void WykonanieKomendy(object sender, CommandEventArgs e)
{
switch (e.CommandName)
{
case "PokazDateCzas" :
switch (e.CommandArgument.ToString())
{
case "Data" :
Label1.Text = string.Format("Data: {0}", DateTime.Now.ToString("yyyy-MM-dd"));
break;
case "Czas" :
Label1.Text = string.Format("Czas: {0}", DateTime.Now.ToString("HH:mm:ss"));
break;
default:
break;
}
break;
case "PrzywitajSie" :
switch (e.CommandArgument.ToString())
{
case "Oficjalnie" :
Label1.Text = "Dzień dobry";
break;
case "Nieoficjalnie" :
Label1.Text = "Cześć";
break;
default :
break;
}
break;
default :
break;
}
}
}
Zobacz wynik
UPDATE: Przekazanie numeru wiersza GridView do metody GridView_RowCommand:
by Piotrosz
17. October 2008
Dynamiczne dodawanie kontrolek serwera (web server controls) w metodzie Page_Init:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Init(object sender, EventArgs e)
{
Label lbl1 = new Label();
lbl1.ID = "lbl1";
lbl1.Text = "Dynamicznie dodana etykieta <br/>";
lbl1.BackColor = System.Drawing.Color.Red;
lbl1.ForeColor = System.Drawing.Color.White;
lbl1.Visible = true;
form1.Controls.Add(lbl1);
TextBox txt1 = new TextBox();
txt1.ID = "txt1";
txt1.Width = 300;
txt1.Visible = true;
form1.Controls.Add(txt1);
}
}
Wynik działania po wyświetleniu strony:
Zobacz wynik
Do umiejscowienia dynamicznie dodanych kontrolek można wykorzystać kontrolkę PlaceHolder:
Drugi przykład który uwzględnia także dynamiczne tworzenie kodu html przy użyciu kontrolki LiteralControl i stworzenie UpdatePanel:
PlaceHolder1.Controls.Add(new LiteralControl("<table><tr><td>"));
TextBox txt = new TextBox();
txt.ID = "txt1";
txt.Text = "Hello";
PlaceHolder1.Controls.Add(txt);
PlaceHolder1.Controls.Add(new LiteralControl("</td></tr></table>"));
Jeszcze jedna uwaga. Po PostBacku dynamicznie dodane kontrolki są usuwane z pamięci. Trzeba je więc tworzyć w metodzie Page_Init lub PagePreInit niezależnie od wartości właściwości
Page.IsPostBack.
by Piotrosz
16. October 2008
Przykład procedury składowanej, która dynamicznie tworzy zapytanie SQL. Zapytanie wykonywane jest za pomocą polecenia EXEC:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE sp_SelectPeople
@FirstName varchar(20)
@LastName varchar(100)
@Status varchar(20)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @WhereClause varchar(250)
SET @WhereClause = 'WHERE 1=1 '
IF @FirstName <> ''
SET @WhereClause = @WhereClause + ' AND FirstName =''' + @FirstName + ''''
IF @LastName <> ''
SET @WhereClause = @WhereClause + ' AND LastName = ''' + @LastName + ''''
IF @Status <> ''
SET @WhereClause = @WhereClause + ' AND Status IN (' @Status + ')'
DECLARE @sqlQuery varchar(550)
SET @sqlQuery = 'SELECT [FirstName], [LastName], [Status] FROM [People] '
SET @sqlQuery = @sqlQuery + @WhereClause
-- Aby Visual Studio zserializował kolumny w TableAdapterze
-- Dzięki temu będzie można używać "typed DataSet"
-- SELECT FirstName, LastName, Status FROM [People] WHERE id = -1
-- Takie wykonanie jest niebezpieczne ze względu na możliwość ataku SQL injection
--EXEC(@sqlQuery);
EXEC sp_executesql @sqlQuery, N'@FirstName varchar(20),@LastName varchar(100),
@Status varchar(20)',@FirstName,@LastName,@Status
END
GO