1. Trang chủ
  2. » Công Nghệ Thông Tin

Wrox Professional Web Parts and Custom Controls with ASP.NET 2.0 phần 10 potx

57 303 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 57
Dung lượng 1,04 MB

Nội dung

tc = New System.Web.UI.WebControls.TableCell tc.Controls.Add(lblNameLb) tr.Cells.Add(tc) tc = New System.Web.UI.WebControls.TableCell tc.Controls.Add(lblName) tr.Cells.Add(tc) tbl.Rows.Add(tr) In C#: System.Web.UI.WebControls.Table tbl = new System.Web.UI.WebControls.Table(); System.Web.UI.WebControls.TableCell tc; System.Web.UI.WebControls.TableRow tr; tr = new System.Web.UI.WebControls.TableRow(); tc = new System.Web.UI.WebControls.TableCell(); tc.Controls.Add(lblNameLb); tr.Cells.Add(tc); tc = new System.Web.UI.WebControls.TableCell(); tc.Controls.Add(lblName); tr.Cells.Add(tc); tbl.Rows.Add(tr); The final step is to add the Table (rather than the individual controls) to the Control’s collection of the custom control as this Visual Basic 2005 code does: Me.Controls.Add(tbl) In C#: this.Controls.Add(tbl) The result is shown in Figure 12-8. Figure 12-8 398 Chapter 12 19_57860x ch12.qxd 10/4/05 9:28 PM Page 398 Rather than repeat this code over and over, a smarter approach is to write a routine that, when passed two labels and the table, adds the labels to the Table in a new row. The Visual Basic version of that rou- tine looks like this: Private Function AddToTable(ByVal Table As System.Web.UI.WebControls.Table, _ ByVal Label As System.Web.UI.WebControls.Label, _ ByVal Data As System.Web.UI.WebControls.Label) As WebControls.Table Dim tc As System.Web.UI.WebControls.TableCell Dim tr As System.Web.UI.WebControls.TableRow tr = New System.Web.UI.WebControls.TableRow tc = New System.Web.UI.WebControls.TableCell tc.Controls.Add(Label) tr.Cells.Add(tc) tc = New System.Web.UI.WebControls.TableCell tc.Controls.Add(Data) tr.Cells.Add(tc) Table.Rows.Add(tr) Return Table End Function In C#: private WebControls.Table AddToTable(System.Web.UI.WebControls.Table Table, System.Web.UI.WebControls.Label Label, System.Web.UI.WebControls.Label Data) { System.Web.UI.WebControls.TableCell tc; System.Web.UI.WebControls.TableRow tr; tr = new System.Web.UI.WebControls.TableRow(); tc = new System.Web.UI.WebControls.TableCell(); tc.Controls.Add(Label); tr.Cells.Add(tc); tc = new System.Web.UI.WebControls.TableCell(); tc.Controls.Add(Data); tr.Cells.Add(tc); Table.Rows.Add(tr); return Table; } The routine is called by passing the two labels that go into a row and the table that the row is to be added to. The routine returns the updated Table object so that it can be passed to the routine for the next call (this avoids having to declare the Table object as a module level variable). In Visual Basic 2005: tbl = AddToTable(tbl, lblNameLb, lblName) tbl = AddToTable(tbl, lblEmailLb, lblEmail) rest of the labels 399 A Custom Control Case Study 19_57860x ch12.qxd 10/4/05 9:28 PM Page 399 In C#: tbl = AddToTable(tbl, lblNameLb, lblName); tbl = AddToTable(tbl, lblEmailLb, lblEmail); Using Absolute Positioning A third option is to use cascading stylesheet absolute positioning. This option, while providing the finest-grained control, is also the solution most likely to have compatibility problems among browsers (especially, of course, with older browsers that don’t support CSS). In this solution, the code adds three attributes to each constituent control’s Style object: ❑ absolute: Set to “position” ❑ top: Set to the distance that the constituent control is to be placed from the top of the custom control ❑ left: Set to the distance that the constituent control is to be placed from the left-hand side of the custom control This Visual Basic 2005 code positions the data control for the name 5 pixels from the top of the control and 15 pixels from the left-hand edge: lblName.Style.Add(“position”,”absolute”) lblName.Style.Add(“top”,”5px”) lblName.Style.Add(“left”,”15px”) In C#: lblName.Style.Add(“position”, “absolute”); lblName.Style.Add(“top”, “5px”); lblName.Style.Add(“left”, “15px”); At run time, your custom control is represented by a <span> tag. The positions of your constituent con- trols will be calculated as offsets from the upper-left corner of your custom control. Tweaking the various positions of your controls can be time-consuming. A faster method is to open a new form, turn on absolute positioning, and then drag and drop controls onto the user control to match the final layout of your control. You can then, in Source view, read the values generated by Visual Studio 2005 and use those in your code. While absolute positioning provides a solution for some of the positioning problems in a custom control, there are some problems with using absolute positioning: ❑ Older browsers may not handle absolute positioning correctly (or at all). ❑ Controls that use absolute positioning can display oddly in WebPartZones. ❑ It can be difficult for developers to manipulate controls with absolute positioning in Visual Studio 2005 display controls at design time. 400 Chapter 12 19_57860x ch12.qxd 10/4/05 9:28 PM Page 400 There aren’t solutions to the first two problems (other than to use the previous two mechanisms for posi- tioning constituent controls). However, the third problem does have a solution. At design time, with absolute positioning, your control is represented as a tiny square in the upper-left corner of the control, with the constituent controls spread out below that “anchor” square. Figure 12-9 shows the CustomerInformation control, using absolute positioning. Developers can find it difficult to figure out where to click so that they can drag the control on the page. Figure 12-9 If you do decide to use absolute positioning, to make life easier for developers using your control you should consider creating a panel and adding all of your constituent controls to the panel (after setting the constituent control’s positioning settings). You need to make sure that you size the panel so that it is large enough to hold all of the controls. After the panel has had the constituent controls added to it, you add the panel to the custom control’s Controls collection. This Visual Basic 2005 code creates a panel, adds the first two labels to it, sets the panel’s size, and adds the panel to custom control’s Controls collection: Dim pnl As New System.Web.UI.WebControls.Panel pnl.Controls.Add(lblNameLb) pnl.Controls.Add(lblName) add the rest of the labels to the panel pnl.Height = 150 pnl.Width = 320 Me.Controls.Add(pnl) In C#: System.Web.UI.WebControls.Panel pnl = new System.Web.UI.WebControls.Panel(); pnl.Controls.Add(lblNameLb); pnl.Controls.Add(lblName); add the rest of the labels to the panel pnl.Height = 150; pnl.Width = 320; this.Controls.Add(pnl); 401 A Custom Control Case Study 19_57860x ch12.qxd 10/4/05 9:28 PM Page 401 The result, at design time, is shown in Figure 12-10. While there is no change to the display in the browser (unless you override the Panel control’s default style settings), at design time the control appears with a border around it. Developers can now click the border to drag your control on the page. Figure 12-10 As with the table-based solution, it makes sense to create a routine that handles positioning the con- stituent controls. This Visual Basic 2005 routine accepts a number that specifies which line the control appears on and the two labels to be positioned on the line. The code calculates the vertical setting for the control by multiplying the line number by a fixed amount and then sets the positioning properties on the controls passed to the routine: Private Sub AddPositioning(ByVal LineNumber As Integer, _ ByVal Label As System.Web.UI.WebControls.Label, _ ByVal Data As System.Web.UI.WebControls.Label) Dim intVerticalOffset As Integer intVerticalOffset = LineNumber * 25 Label.Style.Add(“position”, “absolute”) Label.Style.Add(“top”, intVerticalOffset.ToString & “px”) Label.Style.Add(“left”, “0px”) Data.Style.Add(“position”, “absolute”) Data.Style.Add(“top”, intVerticalOffset.ToString & “px”) Data.Style.Add(“left”, “70px”) End Sub In C#: private void AddPositioning(int LineNumber, System.Web.UI.WebControls.Label Label, System.Web.UI.WebControls.Label Data) 402 Chapter 12 19_57860x ch12.qxd 10/4/05 9:28 PM Page 402 { int intVerticalOffset; intVerticalOffset = LineNumber * 25; Label.Style.Add(“position”, “absolute”); Label.Style.Add(“top”, intVerticalOffset.ToString() + “px”); Label.Style.Add(“left”, “0px”); Data.Style.Add(“position”, “absolute”); Data.Style.Add(“top”, intVerticalOffset.ToString() + “px”); Data.Style.Add(“left”, “70px”); } The Visual Basic 2005 code to add the name and e-mail text boxes with their labels looks like this: AddPositioning(0, lblNameLb, lblName) AddPositioning(1, lblEmailLb, lblEmail) In C#: AddPositioning(0, lblNameLb, lblName); AddPositioning(1, lblEmailLb, lblEmail); Switching Between Display and Update Modes Because the CustomerInformation control is also intended to allow developers to switch between a dis- play mode and an update mode, the control needs to have a Mode property that allows a developer using the control to change modes. Three design decisions were made when selecting the name for this property: ❑ Using a generic term such as Mode provides less guidance to developers than using a more spe- cific name (such as DisplayOrUpdate). However, it also makes it possible to add other modes in the future without changing the control’s interface to the developer. ❑ Having a single Mode property ensures that the control can’t be given conflicting commands. Conflicting commands would have been possible if, for instance, the control had been given two properties: one to put the control in DisplayMode and one to put the control in UpdateMode. ❑ Once a noun is chosen to implement mode switching, it makes sense to put the code in a prop- erty (most functions have names that begin with verbs). A good case can also be made for creat- ing a method to handle this functionality (for example, ToggleMode or SwitchMode). The code inside the routine would have been very similar in either case. Because there are only two values (Display and Update), it’s a good practice to set up an enumerated value that holds values for those two settings as this Visual Basic 2005 code does: Public Enum ciModeSettings ciUpdate ciDisplay End Enum 403 A Custom Control Case Study 19_57860x ch12.qxd 10/4/05 9:28 PM Page 403 In C#: public enum ciModeSettings { ciUpdate, ciDisplay } In order to store the value of the Mode property, a private variable needs to be declared. In Visual Basic 2005: Private _Mode As ciModeSettings In C# private ciModeSettings _Mode; The Mode property can now be written with Get and Set routines that return the enumerated value, as in this Visual Basic 2005 example: Public Property Mode() As ciModeSettings Get Return _Mode End Get Set (value As ciModeSettings) _Mode = value End Set End Property In C#: public ciModeSettings Mode { get { return _Mode; } set { _Mode = value; } } Because the Mode property uses this enumerated value, a developer using the control will find the val- ues displayed in the IntelliSense drop-down lists when setting the property (as shown in Figure 12-11) and in the Visual Studio .NET Property List (as shown in Figure 12-12). Figure 12-11 404 Chapter 12 19_57860x ch12.qxd 10/4/05 9:28 PM Page 404 Figure 12-12 In the next section, you see how to add the code to store the control’s information. However, for a prop- erty like Mode, there’s no need to take any action—the property is automatically stored as an attribute on the HTML generated for the control both at design time and at run time. Here’s a typical example: <cc1:CustomerInformation ID=”CustomerInfo” runat=”server” Mode=”ciDisplay” Style=”z-index: 100; left: 38px; position: absolute; top: 15px” /> The CreateChildControls routine must include the code to switch between the two modes. The code must check the Mode property and create TextBoxes instead of Labels to hold the customer information. As with the Label controls, the TextBoxes need to have their Id property set and their Style property merged with the ControlStyle object used to format the control. In Visual Basic 2005: Dim txtName As New System.Web.UI.WebControls.TextBox Dim txtEmail As New System.Web.UI.WebControls.TextBox rest of TextBox declarations If Me.Mode = ciModeSettings.ciUpdate Then txtName.ID = “txtName” txtName.Attributes(“DisplayType”) = “data” txtName.Width = 100 txtName.MergeStyle(st) txtEmail.ID = “txtEmail” txtEmail.Attributes(“DisplayType”) = “data” txtEmail.Width = 100 txtEmail.MergeStyle(st) rest of textbox controls Else lblName.ID = “txtName” lblName.Attributes(“DisplayType”) = “data” lblName.Width = 100 lblName.MergeStyle(st) lblEmail.ID = “txtEmail” lblEmail.Attributes(“DisplayType”) = “data” lblEmail.Width = 100 405 A Custom Control Case Study 19_57860x ch12.qxd 10/4/05 9:28 PM Page 405 lblEmail.MergeStyle(st) rest of Label controls End If In C#: System.Web.UI.WebControls.TextBox txtName = new System.Web.UI.WebControls.TextBox(); System.Web.UI.WebControls.TextBox txtEmail = new System.Web.UI.WebControls.TextBox(); rest of TextBox declarations if(this.Mode == ciModeSettings.ciUpdate) { txtName.ID = “txtName”; txtName.Attributes[“DisplayType”] = “data”; txtName.Width = 100; txtName.MergeStyle(st); txtEmail.ID = “txtEmail”; txtEmail.Attributes[“DisplayType”] = “data”; txtEmail.Width = 100; txtEmail.MergeStyle(st); rest of TextBox controls } else { lblName.ID = “lblName”; lblName.Attributes[“DisplayType”] = “data”; lblName.Width = 100; lblName.MergeStyle(st); lblEmail.ID = “lblEmail”; lblEmail.Attributes[“DisplayType”] = “data”; lblEmail.Width = 100; lblEmail.MergeStyle(st); rest of Label controls } In the discussion of how to position the controls on the page, I recommended that you set up standard routines to either add controls to a table or to set absolute positioning. Those routines were originally written to accept two Label controls but now need to be extended to handle either a Label or a TextBox control as their second parameter. Because the only properties being manipulated in these routines are the properties common to all WebControls, the simplest solution is just to declare the second parameter of the routines as being of type System.Web.UI.WebControls.WebControl. 406 Chapter 12 19_57860x ch12.qxd 10/4/05 9:28 PM Page 406 Tailoring the Control for the Developer With much of the control’s basic functionality established, now is a good time to set attributes on the control that will make it easier for the developer to use. At the module level, you can insert a TagPrefix attribute to specify the prefix that is to be used when your custom control’s tag is generated at run time. The TagPrefix attribute must be passed the Namespace for your control and the prefix to be used. This Visual Basic 2005 example sets the prefix to csc: <Assembly: TagPrefix(“CaseStudyControls”, “csc”)> <ToolboxData(“<{0}:CustomerInformation runat=server></{0}:CustomerInformation>”)> _ Public Class CustomerInformation In C#: [assembly: TagPrefix(“CaseStudyControls”, “csc”)] [ToolboxData(“<{0}:CustomerInformation runat=server></{0}:CustomerInformation>”)] public class CustomerInformation { The HTML for your control at design time now looks like this: <%@ Register Assembly=”CaseStudyControlsVB” Namespace=”CaseStudyControls” TagPrefix=”csc” %> <csc:CustomerInformation ID=”CustomerInfo” runat=”server” Style=”z-index: 100;left: 66px; position: absolute; top: 15px” /> Without a TagPrefix, the prefix for your control defaults to cc. When you first create a control, it’s hard to predict which properties of the control a developer will use the most. However, for the CustomerInformation control it seems likely that the Mode property will be one that developers will want to set as soon as they add the control to a page. This Visual Basic 2005 code uses the DefaultProperty attribute on the Class declaration to make Mode the default property in the Visual Studio .NET IntelliSense drop-down lists, as shown in Figure 12-13: <DefaultProperty(“Mode”), _ ToolboxData(“<{0}:CustomerInformation runat=server></{0}:CustomerInformation>”)> _ Public Class CustomerInformation In C#: [DefaultProperty(“Mode”)] [ToolboxData(“<{0}:CustomerInformation runat=server></{0}:CustomerInformation>”)] public class CustomerInformation On the Mode property itself, the DefaultValue attribute lets you specify an initial value for the Mode property and the Category attribute allows you to specify where the Property appears in the Visual Studio .NET Property List when the list is sorted by category. This Visual Basic 2005 code sets the default value for the control to ciDisplay and puts the property in the Behavior category of the Property List: <DefaultValue(ciModeSettings.ciDisplay), Category(“Behavior”)> _ Public Property Mode() As ciModeSettings 407 A Custom Control Case Study 19_57860x ch12.qxd 10/4/05 9:28 PM Page 407 [...]... 12-15): _ Public Property CustomerId() As String In C#: [System .Web. UI.WebControls.WebParts.WebDescription( Controls the customer displayed.”)]... System .Web. UI.WebControls.WebParts.WebPartVerb vrbUpdate = new System .Web. UI.WebControls.WebParts.WebPartVerb(“Update”, this.UpdateCustomer); System .Web. UI.WebControls.WebParts.WebPartVerb[] vrbsUpdate = new System .Web. UI.WebControls.WebParts.WebPartVerb[0]; System .Web. UI.WebControls.WebParts.WebPartVerbCollection vrbs; vrbUpdate.Text = “Update Customer”; vrbUpdate.Description = “Update customer information with data... _ Public Property CustomerId() As String 425 Chapter 12 In C#: [System .Web. UI.WebControls.WebParts.WebBrowsable()] [System .Web. UI.WebControls.WebParts.Personalizable()] public string CustomerId With these two attributes added to the CustomerId property, the property can now be edited using the PropertyEditor WebPartEditor... ReadOnly Property Verbs() As _ WebControls.WebParts.WebPartVerbCollection Get Dim vrbUpdate As New WebControls.WebParts.WebPartVerb( _ “Update”, AddressOf Me.UpdateCustomer) Dim vrbsUpdate As WebControls.WebParts.WebPartVerbCollection Dim vrbs(0) As WebControls.WebParts.WebPartVerb vrbUpdate.Text = “Update Customer” vrbUpdate.Description = _ “Update customer information with data from the control”; vrbsUpdate(0)... New WebControls.WebParts.WebPartVerbCollection(vrbsUpdate) Return vrbs End Get End Property Private Sub UpdateCustomer(ByVal sender As Object, _ ByVal e As System .Web. UI.WebControls.WebParts.WebPartEventArgs) code to update the customer information from the postData structure End Sub In C#: public override System .Web. UI.WebControls.WebParts.WebPartVerbCollection Verbs { get { System .Web. UI.WebControls.WebParts.WebPartVerb... displayed.”)] 426 A Custom Control Case Study [System .Web. UI.WebControls.WebParts.WebDisplayName(“Customer Number”)] [System .Web. UI.WebControls.WebParts.WebBrowsable()] [System .Web. UI.WebControls.WebParts.Personalizable()] public string CustomerId Figure 12-15 Setting the control’s Title property allows you to provide a meaningful name for the custom control Adding Verbs In addition to displaying customer information,... passes it to the GetCustomer routine to retrieve the customer information from the ICustInfo interface’s CustomerId property: _ Public Sub ICustInfoConsumer(ByVal cs As ICustInfo) _CustomerId = cs.CustomerId GetCustomerInformation(_CustomerId) End Sub In C#: WebControls.WebParts.ConnectionConsumer(“Consumer for CustomerIds”)] public... IPostBackDataHandler interface In Visual Basic 2005, this code implements the interface: Public Class CustomerInformation Inherits System .Web. UI.WebControls.WebParts.WebPart Implements IPostBackDataHandler In C#: public class CustomerInformation : System .Web. UI.WebControls.WebParts.WebPart, IPostBackDataHandler The user data returned from the browser can be saved in the same data structure as was used... information with data from the control”; vrbsUpdate[0] = vrbUpdate; vrbs = new System .Web. UI.WebControls.WebParts.WebPartVerbCollection(vrbsUpdate); return vrbs; } } private void UpdateCustomer(object sender, 428 A Custom Control Case Study System .Web. UI.WebControls.WebParts.WebPartEventArgs e) { code to update the customer information from the postData structure } Figure 12-16 shows the result Figure... interface and a property that the interface defines The Visual Basic 2005 code to add the ICustInfo interface to the control (along with the already implemented IPostBackDataHandler interface) looks like this: Public Class CustomerInformation Inherits System .Web. UI.WebControls.WebParts.WebPart Implements IPostBackDataHandler Implements ICustInfo In C#: public class CustomerInformation : System .Web. UI.WebControls.WebParts.WebPart, . System .Web. UI.WebControls.Label Label, System .Web. UI.WebControls.Label Data) 4 02 Chapter 12 19_57860x ch 12. qxd 10/ 4 /05 9 :28 PM Page 4 02 { int intVerticalOffset; intVerticalOffset = LineNumber * 25 ; Label.Style.Add(“position”,. shown in Figure 12- 11) and in the Visual Studio .NET Property List (as shown in Figure 12- 12) . Figure 12- 11 404 Chapter 12 19_57860x ch 12. qxd 10/ 4 /05 9 :28 PM Page 404 Figure 12- 12 In the next section,. saving its data. In 4 10 Chapter 12 19_57860x ch 12. qxd 10/ 4 /05 9 :28 PM Page 4 10 Visual Basic 20 05, the code to check the mode, retrieve the controls from the custom control’s Controls collection,

Ngày đăng: 06/08/2014, 09:20