Tải bản đầy đủ (.pdf) (10 trang)

Professional ASP.NET 3.5 in C# and Visual Basic Part 129 pdf

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (91.12 KB, 10 trang )

Evjen c26.tex V2 - 01/28/2008 3:48pm Page 1241
Chapter 26: User and Server Controls
Now that you can create a postback, you may want to add events to your control that execute dur-
ing the page postback. To raise server-side events from a client-side object, you implement the Sys-
tem.Web.IPostBackEventHandler interface. Listing 26-31 shows how to do this for a button control. You
also create a server-side Click event you can handle when the page posts back.
Listing 26-31: Handling postback events in a server control
VB
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
<DefaultProperty("Text")> _
<ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")> _
Public Class ServerControl1
Inherits System.Web.UI.WebControls.WebControl
Implements IPostBackEventHandler
’. . . Code removed for clarity . . .
Public Event Click()
Public Sub OnClick(ByVal args As EventArgs)
RaiseEvent Click()
End Sub
Public Sub RaisePostBackEvent(ByVal eventArgument As String) _
Implements System.Web.UI.IPostBackEventHandler.RaisePostBackEvent
OnClick(EventArgs.Empty)
End Sub
End Class
C#


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ServerControl1
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
public class ServerControl1 : WebControl, IPostBackEventHandler
{
//. . . Code removed for clarity . . .
#region IPostBackEventHandler Members
1241
Evjen c26.tex V2 - 01/28/2008 3:48pm Page 1242
Chapter 26: User and Server Controls
public event EventHandler Click;
public virtual void OnClick(EventArgs e)
{
if (Click != null)
{
Click(this,e);
}
}
public void RaisePostBackEvent(string eventArgument)
{
OnClick(EventArgs.Empty);

}
#endregion
}
}
Now, when the user clicks the button and the page posts back, the server-side Click event fires, allowing
you to add server-side handling code to the event.
Handling PostBack Data
Now that you have learned how to store data in ViewState and add postback capabilities to a control,
look at how you can enable the control to interact with data the user enters into one of its form fields.
When a page is posted back to the server by ASP.NET, all the form data is also posted to the server. If the
control can interact with data that is passed with a page, you can store the information in ViewState and
complete the illusion of a stateful application.
To interact with postback data, your control must be able to access the data. To do this, it implements
the System.Web.IPostBackDataHandler interface. This interface allows your control to examine the form
data that is passed back to the server during the postback.
The IPostBackDataHandler interface requires that you implement two methods:
LoadPostData
and
RaisePostBackDataChangedEvent
.The
LoadPostData
method is called for all server controls on the page
that have postback data. If a control does not have any postback data, the method is not called; however,
you can explicitly ask for the method to be called by using the
RegisterRequiresPostBack
method.
Listing 26-32 shows how you implement the IPostBackDataHandler interface method in a text box.
Listing 26-32: Accessing Postback data in a server control
VB
Imports System

Imports Sustem.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
<DefaultProperty("Text")> _
1242
Evjen c26.tex V2 - 01/28/2008 3:48pm Page 1243
Chapter 26: User and Server Controls
<ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")> _
Public Class ServerControl1
Inherits SystemWebControl
Implements IPostBackEventHandler, IPostBackDataHandler
’. . . Code removed for clarity . . .
Public Function LoadPostData(ByVal postDataKey As String, _
ByVal postCollection As _
System.Collections.Specialized.NameValueCollection) _
As Boolean Implements System.Web.UI.IPostBackDataHandler.LoadPostData
Me.Text = postCollection(postDataKey)
Return False
End Function
Public Sub RaisePostDataChangedEvent() _
Implements System.Web.UI.IPostBackDataHandler.RaisePostDataChangedEvent
End Sub
End Class
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;

using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ServerControl1
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
public class ServerControl1 : WebControl,
IPostBackEventHandler, IPostBackDataHandler
{
//. . . Code removed for clarity . . .
public bool LoadPostData(string postDataKey,
System.Collections.Specialized.NameValueCollection postCollection)
{
this.Text = postCollection[postDataKey];
return false;
}
public void RaisePostDataChangedEvent()
{
}
}
}
1243
Evjen c26.tex V2 - 01/28/2008 3:48pm Page 1244
Chapter 26: User and Server Controls
As you can see, the
LoadPostData
method passes any form data submitted to the method as a name

value collection that the control can access. The
postDataKey
parameter allows the control to access
the postback data item specific to it. You use these parameters to save text to the
Text
property of the
TextBox control. If you remember the earlier ViewState example, the
Text
property saves the new value
to ViewState; when the page renders, the TextBox value automatically repopulates.
In addition to the input parameters, the
LoadPostData
method also returns a Boolean value. This
value indicates whether the
RaisePostBackDataChangedEvent
method is also called after the
LoadPostData
method completes execution. In the sample, it returns
false
because no events exist,
but if you create a
TextChanged
event to indicate the Textbox text has changed, you raise that event in
the
RaisePostDataChangedEvent
method.
Composite Controls
So far, in looking at Server controls, you have concentrated on emitting a single HTML control; but
this can be fairly limiting. Creating extremely powerful controls often requires that you nest several
HTML elements together. ASP.NET allows you to easily create controls that serve as a container for other

controls.Thesetypesofcontrolsarecalledcomposite controls.
To demonstrate how easy creating a composite control can be, try to change an existing control into a
composite control. Listing 26-33 shows how you can do this.
Listing 26-33: Creating a composite control
VB
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
<DefaultProperty("Text")> _
<ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")> _
Public Class ServerControl1
Inherits System.Web.UI.WebControls.CompositeControl
Protected textbox As TextBox
Protected Overrides Sub CreateChildControls()
Me.Controls.Add(textbox)
End Sub
End Class
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
1244
Evjen c26.tex V2 - 01/28/2008 3:48pm Page 1245

Chapter 26: User and Server Controls
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ServerControl1
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
public class ServerControl1 : CompositeControl
{
protected TextBox textbox = new TextBox();
protected override void CreateChildControls()
{
this.Controls.Add(textbox);
}
}
}
A number of things in this listing are important. First, notice that the control class is now inheriting
from
CompositeControl
, rather than
WebControl
. Deriving from
CompositeControl
gives you a few
extra features specific to this type of control.
Second, notice that no
Render
method appears in this code. Instead, you simply create an instance of
another type of server control and add that to the
Controls

collection in the
CreateChildControls
method. When you run this sample, you see that it renders a text box just like the last control did. In fact,
the HTML that it renders is almost identical.
Exposing Child Control Properties
When you drop a composite control (such as the text box from the last sample) onto the design sur-
face, notice that even though you are using a powerful ASP.NET TextBox control within the control,
none of that control’s properties are exposed to you in the Properties Explorer. In order to expose
child control properties through the parent container, you must create corresponding properties in the
parent control. For example, if you want to expose the ASP.NET text box
Text
property through
the parent control, you create a
Text
property. Listing 26-34 shows how to do this.
Listing 26-34: Exposing control properties in a composite control
VB
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
<DefaultProperty("Text")> _
<ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")> _
Public Class ServerControl1
Inherits System.Web.UI.WebControls.CompositeControl
Protected textbox As TextBox
Public Property Text() As String

1245
Evjen c26.tex V2 - 01/28/2008 3:48pm Page 1246
Chapter 26: User and Server Controls
Get
EnsureChildControls()
Return textbox.Text
End Get
Set(ByVal value As String)
EnsureChildControls()
textbox.Text = value
End Set
End Property
Protected Overrides Sub CreateChildControls()
Me.Controls.Add(textbox)
Me.ChildControlsCreated=True
End Sub
End Class
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ServerControl1
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]

public class ServerControl1 : CompositeControl
{
protected TextBox textbox = new TextBox();
public string Text
{
get
{
EnsureChildControls();
return textbox.Text;
}
set
{
EnsureChildControls();
textbox.Text = value;
}
}
protected override void CreateChildControls()
{
this.Controls.Add(textbox);
this.ChildControlsCreated=true;
}
}
}
1246
Evjen c26.tex V2 - 01/28/2008 3:48pm Page 1247
Chapter 26: User and Server Controls
Notice that you use this property simply to populate the underlying control’s properties. Also notice
that before you access the underlying control’s properties, you always call the
EnsureChildControls
method. This method ensures that children of the container control have actually been initialized before

you attempt to access them.
Templated Controls
In addition to composite controls, you can also create templated controls. Templated controls allow the user
to specify a portion of the HTML that is used to render the control, and to nest other controls inside of a
container control. You might be familiar with the Repeater or DataList control. These are both templated
controls that let you specify how you want the bound data to be displayed when the page renders.
To demonstrate a templated control, the following code gives you a simple example of displaying a mes-
sage from a user on a Web page. Because the control is a templated control, the developer has complete
control over how the message is displayed.
To get started, create the Message server control that will be used as the template inside of a container
control. Listing 26-35 shows the class which simply extends the existing Panel control by adding two
additional properties, Name and Text, and a new constructor.
Listing 26-35: Creating the templated control’s inner control class
VB
Public Class Message
Inherits System.Web.UI.WebControls.Panel
Implements System.Web.UI.INamingContainer
Private _name As String
Private _text As String
Public Sub New(ByVal name As String, ByVal text As String)
_text = text
_name = name
End Sub
Public ReadOnly Property Name() As String
Get
Return _name
End Get
End Property
Public ReadOnly Property Text() As String
Get

Return _text
End Get
End Property
End Class
C#
using System;
using System.Text;
using System.Web;
1247
Evjen c26.tex V2 - 01/28/2008 3:48pm Page 1248
Chapter 26: User and Server Controls
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ServerControl1
{
public class Message : Panel, INamingContainer
{
private string _name;
private string _text;
public Message(string name, string text)
{
_text = text;
_name = name;
}
public string Name
{
get { return _name;}
}
public string Text
{

get { return _text;}
}
}
}
As you will see in a moment, you can access the public properties exposed by the
Message
class in
order to insert dynamic content into the template. You will also see how you can display the values
of the
Name
and
Text
properties as part of the rendered template control.
Next, as shown in Listing 26-36, create a new server control which will be the container for the
Message
control. This server control is responsible for rendering any template controls nested in it.
Listing 26-36: Creating the template control container class
VB
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
<DefaultProperty("Text")> _
<ToolboxData("<{0}:TemplatedControl runat=server></{0}:TemplatedControl>")> _
Public Class TemplatedControl
Inherits System.Web.UI.WebControls.WebControl
Private _name As String

Private _text As String
1248
Evjen c26.tex V2 - 01/28/2008 3:48pm Page 1249
Chapter 26: User and Server Controls
Private _message As Message
Private _messageTemplate As ITemplate
<Browsable(False)> Public ReadOnly Property Message() As Message
Get
Return _message
End Get
End Property
<PersistenceMode(PersistenceMode.InnerProperty), _
TemplateContainer(GetType(Message))> _
Public Property MessageTemplate() As ITemplate
Get
Return _messageTemplate
End Get
Set(ByVal value As ITemplate)
_messageTemplate = value
End Set
End Property
<Bindable(True), DefaultValue("")> Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
<Bindable(True), DefaultValue("")> Public Property Text() As String

Get
Return _text
End Get
Set(ByVal value As String)
_text = value
End Set
End Property
Public Overrides Sub DataBind()
CreateChildControls()
ChildControlsCreated = True
MyBase.DataBind()
End Sub
Protected Overrides Sub CreateChildControls()
Me.Controls.Clear()
_message = New Message(Name, Text)
If Me.MessageTemplate Is Nothing Then
Me.MessageTemplate = New DefaultMessageTemplate()
End If
1249
Evjen c26.tex V2 - 01/28/2008 3:48pm Page 1250
Chapter 26: User and Server Controls
Me.MessageTemplate.InstantiateIn(_message)
Controls.Add(_message)
End Sub
Protected Overrides Sub RenderContents( _
ByVal writer As System.Web.UI.HtmlTextWriter)
EnsureChildControls()
ChildControlsCreated = True
MyBase.RenderContents(writer)
End Sub

End Class
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ServerControl1
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:TemplatedControl runat=server></{0}: TemplatedControl >")]
public class TemplatedControl : WebControl
{
private string _name;
private string _text;
private Message _message;
private ITemplate _messageTemplate;
[Browsable(false)]
public Message Message
{
get
{
return _message;
}
}
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(Message))]

public virtual ITemplate MessageTemplate
{
get { return _messageTemplate;}
set { _messageTemplate = value;}
}
1250

×