Creating Custom Editor Zones


Editor Zones contain the Editor Parts you can use to edit the properties of your Web Parts. The Web Part Framework contains a standard set of Editor Part controls that can be used to edit the standard properties of a Web Part: the AppearanceEditorPart, the BehaviorEditorPart, and the LayoutEditorPart controls.

If your Web Part has custom properties, and you want to edit these properties with an Editor Part, then you have two choices. You can use the PropertyGridEditorPart control or build your own custom Editor Part. In most cases, you won't want to use the PropertyGridEditorPart because it does not provide any support for form validation or advanced layout. When using the PropertyGridEditorPart, for any property other than a Boolean or Enum property, you get a single-line text box and there isn't anything you can do about it.

Note

Another option is to edit a Web Part's properties inline. In other words, you can add an edit form to the Web Part itself and display the edit form only when the page is in Edit Display Mode. You can detect whether a page is in Edit Display Mode within a Web Part by retrieving the current instance of the WebPartManager control with the WebPartManager.GetCurrentWebPartManager(Page) method and checking the value of the DisplayMode property.


This section explores two methods of creating custom Editor Parts. First, to clarify the concepts involved, we'll create a simple Editor Part designed to edit the properties of a particular Web Part. Next, you'll learn how to create a templated Editor Part you can use when editing any Web Part control regardless of the types of properties that it contains.

How Editor Zones Work

As in other types of Web Zones, three types of objects are involved in rendering an Editor Zone: the EditorZone control, the EditorPartChrome class, and the EditorPart control.

The EditorZone control appears only when a page is in Edit Display Mode. When the page is in Edit Display Mode, the Editor Zone still does not display any Editor Parts until you select the Edit menu option on a particular Web Part.

When you select a Web Part to edit, two types of Editor Parts are displayed. First, any Editor Parts declared in the Editor Zone are displayed. Second, if the Web Part implements the IWebEditable interface or derives from the base WebPart class, then any Editor Parts returned from the Web Part's CreateEditorParts() method are displayed.

Note

The BehaviorEditorPart appears only when a page is in Shared Personalization scope and the Web Part being edited is shared among all users.


Finally, the EditorPartChrome class is actually responsible for rendering each Editor Part. An instance of the EditorPartChrome class is created by an Editor Zone, and then the Editor Zone calls the EditorPartChrome control's RenderEditorPart() method to render each Editor Part.

If you want to modify the appearance of an Editor Zone or the chrome that appears around each Editor Part, then you need to modify the EditorZone and EditorPartChrome classes. If you want to modify the appearance of the Editor Parts themselves, then you need to modify the properties of a particular Editor Part control.

Creating a Simple Custom Editor Part

Let's start by creating the Web Part that we will edit. The FeaturedBookPart is contained in Listing 30.18.

Listing 30.18. FeaturedBookPart.ascx

[View full width]

<%@ Control Language="VB" ClassName="FeaturedBookPart" %> <%@ Implements Interface="System.Web.UI.WebControls.WebParts.IWebEditable" %> <%@ Implements Interface="myControls.IFeaturedBook" %> <%@ Import Namespace="System.Collections.Generic" %> <%@ Import Namespace="myControls" %> <script runat="server">     Private _bookTitle As String     Private _datePublished As DateTime     Private _price As Decimal     Public ReadOnly Property WebBrowsableObject() As Object Implements IWebEditable .WebBrowsableObject         Get             Return Me         End Get     End Property     Public Function CreateEditorParts() As EditorPartCollection Implements IWebEditable. CreateEditorParts         Dim editorParts As New List(Of EditorPart)()         Dim editor As New FeaturedBookEditorPart()         editor.ID = "FeaturedEditor1"         editorParts.Add(editor)         Return New EditorPartCollection(editorParts)     End Function     <Personalizable()> _     Public Property BookTitle() As String Implements IFeaturedBook.BookTitle         Get             Return _bookTitle         End Get         Set(ByVal Value As String)             _bookTitle = Value         End Set     End Property     <Personalizable()> _     Public Property DatePublished() As DateTime Implements IFeaturedBook.DatePublished         Get             Return _datePublished         End Get         Set(ByVal Value As DateTime)             _datePublished = Value         End Set     End Property     <Personalizable()> _     Public Property Price() As Decimal Implements IFeaturedBook.Price         Get             Return _price         End Get         Set(ByVal Value As Decimal)             _price = Value         End Set     End Property     Private Sub Page_PreRender()         lblBookTitle.Text = _bookTitle         lblDatePublished.Text = _datePublished.ToString("D")         lblPrice.Text = _price.ToString("c")     End Sub </script> Title: <asp:Label          Runat="server" /> <br /> Published: <asp:Label          Runat="server" /> <br /> Price: <asp:Label          Runat="server" /> 

Notice that the FeaturedBookPart control implements two interfaces: the IWebEditable and the IFeaturedBook interfaces. Implementing the first interface enables you to associate the FeaturedBookPart with a custom EditorPart control. The IWebEditable interface has two members:

  • WebBrowsableObject This property represents the object that is edited. Normally, the property should just return a reference to the current control.

  • CreateEditorParts This method returns the collection of EditorPart controls associated with the current Web Part.

The FeaturedBookPart also implements the IFeaturedBook interface that we create in a moment. The custom EditorPart control needs some method of identifying the properties exposed by the FeaturedBookPart. The IFeaturedBook interface provides the EditorPart with this information. (You don't need to create an interface when creating a Web Part with a custom control rather than a User Control.)

The custom Editor Part is contained in Listing 30.19.

Listing 30.19. FeaturedBookEditorPart.vb

[View full width]

Imports System Imports System.Web.UI Imports System.Web.UI.WebControls Imports System.Web.UI.WebControls.WebParts Namespace myControls     ''' <summary>     ''' Describes the properties of the     ''' FeaturedWebPart control     ''' </summary>     Public Interface IFeaturedBook         Property BookTitle() As String         Property DatePublished() As DateTime         Property Price() As Decimal     End Interface     ''' <summary>     ''' Custom Editor for FeaturedBookPart     ''' </summary>     Public Class FeaturedBookEditorPart         Inherits EditorPart         Private _txtBookTitle As TextBox         Private _calDatePublished As Calendar         Private _txtPrice As TextBox         Private _valPrice As CompareValidator         Private _title As String = "Featured Book Editor"         ''' <summary>         ''' Create standard title         ''' </summary>         Public Overrides Property Title() As String             Get                 Return _title             End Get             Set(ByVal Value As String)                 _title = Value             End Set         End Property         ''' <summary>         ''' Utility method that returns the child control         ''' in the case of a GenericWebPart         ''' </summary>         Private ReadOnly Property ControlToEdit() As Control             Get                 If TypeOf (Me.WebPartToEdit) Is GenericWebPart Then                     Return (CType(WebPartToEdit, GenericWebPart)).ChildControl                 Else                     Return Me.WebPartToEdit                 End If             End Get         End Property         ''' <summary>         ''' Called when you click OK or Apply to         ''' apply the Web Part property changes         ''' </summary>         Public Overrides Function ApplyChanges() As Boolean             Dim success As Boolean = False             EnsureChildControls()             Page.Validate()             If Page.IsValid Then                 CType(ControlToEdit, IFeaturedBook).BookTitle = _txtBookTitle.Text                 CType(ControlToEdit, IFeaturedBook).DatePublished = calDatePublished .SelectedDate                 CType(ControlToEdit, IFeaturedBook).Price = Decimal.Parse(_txtPrice.Text)                 success = True             End If             Return success         End Function         ''' <summary>         ''' Called when the Web Part Framework         ''' has initialized the Web Part being edited         ''' </summary>         Public Overrides Sub SyncChanges()             EnsureChildControls()             _txtBookTitle.Text = (CType(ControlToEdit, IFeaturedBook)).BookTitle             _calDatePublished.SelectedDate = (CType(ControlToEdit, IFeaturedBook)) .DatePublished             _txtPrice.Text = (CType(ControlToEdit, IFeaturedBook)).Price.ToString()         End Sub         ''' <summary>         ''' Adds the controls rendered by this Editor Part         ''' to the controls collection.         ''' </summary>         Protected Overrides Sub CreateChildControls()             ' Add Book Title             _txtBookTitle = New TextBox()             _txtBookTitle.ID = "txtBookTitle"             Controls.Add(_txtBookTitle)             ' Add Date Published             _calDatePublished = New Calendar()             _calDatePublished.ID = "calDatePublished"             Controls.Add(_calDatePublished)             ' Add Price             _txtPrice = New TextBox()             _txtPrice.ID = "txtPrice"             _txtPrice.Columns = 5             Controls.Add(_txtPrice)             ' Add Price Validator             _valPrice = New CompareValidator()             _valPrice.ID = "valPrice"             _valPrice.ControlToValidate = _txtPrice.ID             _valPrice.Operator = ValidationCompareOperator.DataTypeCheck             _valPrice.Type = ValidationDataType.Currency             _valPrice.Text = "(Must be currency)"             Controls.Add(_valPrice)         End Sub         ''' <summary>         ''' Renders the User Interface for the Editor Part         ''' </summary>         ''' <param name="writer"></param>         Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)             ' Render Book Title             RenderLabel(writer, "Book Title:", _txtBookTitle.ClientID)             writer.WriteBreak()             _txtBookTitle.RenderControl(writer)             writer.WriteBreak()             writer.WriteBreak()             ' Render Date Published             RenderLabel(writer, "Date Published:", _calDatePublished.ClientID)             writer.WriteBreak()             _calDatePublished.RenderControl(writer)             writer.WriteBreak()             writer.WriteBreak()             ' Render Price             RenderLabel(writer, "Price:", _txtPrice.ClientID)             _valPrice.RenderControl(writer)             writer.WriteBreak()             _txtPrice.RenderControl(writer)             writer.WriteBreak()         End Sub         ''' <summary>         ''' Renders an accessible Label for the         ''' form fields         ''' </summary>         Private Sub RenderLabel(ByVal writer As HtmlTextWriter, ByVal labelText As String,  ByVal associatedControlId As String)             writer.AddAttribute(HtmlTextWriterAttribute.For, associatedControlId)             writer.RenderBeginTag(HtmlTextWriterTag.Label)             writer.Write(labelText)             writer.RenderEndTag()         End Sub     End Class End Namespace 

The class in Listing 30.19 inherits from the base EditorPart class. It overrides two methods from the base class: SyncChanges() and ApplyChanges().

The SyncChanges() method is called automatically when the EditorPart is displayed and the Web Part being edited has been initialized. Listing 30.19 takes advantage of this method to synchronize the editor form with the current property values of the Web Part being edited.

The ApplyChanges() method is automatically called when the user clicks the Apply or OK button in the Editor Zone. This method updates the properties of the Web Part being edited with the values from the editor form.

Note

The ApplyChanges() and SyncChanges() methods are executed during the processing of postback data after the Page Load event and before the PreRender event.


Notice that both the SyncChanges() and ApplyChanges() methods take advantage of a property named ControlToEdit, which also is defined in the class in Listing 30.19. This property returns a different control depending on whether the Web Part being edited is a GenericWebPart or a "true" Web Part. When you create a Web Part by using a User Control or any control that does not derive from the WebPart class, the Web Part Framework automatically wraps the control in a GenericWebPart control. In the case of a GenericWebPart control, you want to edit the properties of the first child control of the Web Part and not the properties of the Web Part itself.

The bulk of the work in Listing 30.19 is devoted to building the custom editor form. Two TextBox controls and one Calendar control are created in the CreateChildControls() method. These controls are actually rendered in the RenderContents() method.

Finally, Listing 30.20 contains a page that displays the FeaturedBookPart and FeaturedBookEditorPart controls.

Listing 30.20. ShowFeaturedBookEditorPart.aspx

<%@ Page Language="VB" %> <%@ Register TagPrefix="custom" Namespace="myControls" %> <%@ Register TagPrefix="user" TagName="FeaturedBookPart"   src="/books/3/444/1/html/2/~/FeaturedBookPart.ascx" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server">     Protected Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)         WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <style type="text/css">         .column         {             float:left;             width:30%;             height:200px;             margin-right:10px;             border:solid 1px black;             background-color: white;         }         .menu         {             margin:5px 0px;         }         html         {             background-color:#eeeeee;         }     </style>     <title>Show Help Display Mode</title> </head> <body>     <form  runat="server">     <asp:WebPartManager                  Runat="server" />         <asp:Menu                          OnMenuItemClick="Menu1_MenuItemClick"             Orientation="Horizontal"             Css             Runat="server">             <Items>             <asp:MenuItem Text="Browse" />             <asp:MenuItem Text="Design" />             <asp:MenuItem Text="Edit" />             </Items>         </asp:Menu>         <asp:WebPartZone                          Css             Runat="server">             <ZoneTemplate>             <user:FeaturedBookPart                                  Title="Featured Book"                 runat="Server" />             </ZoneTemplate>         </asp:WebPartZone>         <asp:WebPartZone                          Css             Runat="server"/>         <asp:EditorZone                          Css             runat="server">             <ZoneTemplate>             <asp:LayoutEditorPart                                  runat="server" />             </ZoneTemplate>         </asp:EditorZone>     </form> </body> </html> 

After you open the page in Listing 30.20, you can click the Edit link and then select the Edit menu option on the FeaturedBookPart. When you edit the FeaturedBookPart, both our custom FeaturedBookEditorPart and the standard LayoutEditorPart will appear in the Editor Zone (see Figure 30.7). Notice that an instance of the LayoutEditorPart control was declared in the Editor Zone contained in the page.

Figure 30.7. Displaying a custom editor.


It took a lot of work to create the custom Editor Part control. Too much work to simply display an editor form. In the next section, you'll learn how to avoid doing any of this work in the future. In the next section, we create a templated Editor Part.

Creating a Templated Editor Part

In this section, we create the last Editor Part that you'll ever need to make. We will create a Templated Editor Part, which will enable you to easily build any type of editor form that you need. You can create the custom form for the Templated Editor Part with a form defined in a user control file.

The Templated Editor Part is contained in Listing 30.21.

Listing 30.21. TemplatedEditorPart.vb

Imports System Imports System.Web.UI Imports System.Web.UI.WebControls.WebParts Namespace myControls     ''' <summary>     ''' Enables you to use templates when     ''' editing Web Parts     ''' </summary>     Public Class TemplatedEditorPart         Inherits EditorPart         Private _editTemplateUrl As String         Private _editTemplate As ITemplatedEditorPart         ''' <summary>         ''' Loads the user control that contains         ''' the Edit Template         ''' </summary>         Protected Overrides Sub CreateChildControls()             _editTemplate = CType(Page.LoadControl(_editTemplateUrl), ITemplatedEditorPart)             Controls.Add(CType(_editTemplate, Control))         End Sub         ''' <summary>         ''' Utility method that returns the child control         ''' in the case of a GenericWebPart         ''' </summary>         Private ReadOnly Property ControlToEdit() As Control             Get                 If TypeOf Me.WebPartToEdit Is GenericWebPart Then                     Return (CType(WebPartToEdit, GenericWebPart)).ChildControl                 Else                     Return Me.WebPartToEdit                 End If             End Get         End Property         ''' <summary>         ''' Called when the user clicks Apply or OK         ''' in the Editor Zone         ''' </summary>         ''' <returns></returns>         Public Overrides Function ApplyChanges() As Boolean             EnsureChildControls()             Return _editTemplate.ApplyChanges(ControlToEdit)         End Function         ''' <summary>         ''' Called when the Editor Template         ''' displays current Web Part property         ''' values.         ''' </summary>         Public Overrides Sub SyncChanges()             EnsureChildControls()             _editTemplate.SyncChanges(ControlToEdit)         End Sub         ''' <summary>         ''' Pass the Editor Part Title and Template         ''' URL to the constructor         ''' </summary>         Public Sub New(ByVal title As String, ByVal editTemplateUrl As String)             Me.Title = title             _editTemplateUrl = editTemplateUrl         End Sub     End Class     ''' <summary>     ''' Defines the contract that any Edit Template     ''' must satisfy     ''' </summary>     Public Interface ITemplatedEditorPart         Function ApplyChanges(ByVal controlToEdit As Control) As Boolean         Sub SyncChanges(ByVal controlToEdit As Control)     End Interface End Namespace 

The constructor for the TemplatedEditorPart class takes a title and editTemplateUrl parameter. The editTemplateUrl parameter specifies the location of a user control that contains the edit form used by the TemplatedEditorPart control. The user control is loaded in the CreateChildControls() method.

Notice that the TemplatedEditorPart control derives from the base EditorPart class. It implements the ApplyChanges() and SyncChanges() from the base class. In this case, however, the control simply calls methods with the same name in the user control that it loads.

The Web Part in Listing 30.22 uses the TemplatedEditorPart control.

Listing 30.22. FeaturedVideoPart.ascx

[View full width]

<%@ Control Language="VB" ClassName="FeaturedVideoPart" %> <%@ Implements Interface="System.Web.UI.WebControls.WebParts.IWebEditable" %> <%@ Import Namespace="System.Collections.Generic" %> <%@ Import Namespace="myControls" %> <script runat="server">     Private _videoTitle As String     Private _director As String     Private _price As Decimal     Public ReadOnly Property WebBrowsableObject() As Object Implements IWebEditable .WebBrowsableObject         Get             Return Me         End Get     End Property     Public Function CreateEditorParts() As EditorPartCollection Implements IWebEditable .CreateEditorParts         Dim editorParts As New List(Of EditorPart)()         Dim editor As New TemplatedEditorPart("Featured Video Editor", "~ /FeaturedVideoEditTemplate.ascx")         editor.ID = "Editor1"         editorParts.Add(editor)         Return New EditorPartCollection(editorParts)     End Function     <Personalizable> _     Public Property VideoTitle() As String     Get          Return _videoTitle     End Get     Set (ByVal Value As String)          _videoTitle = value     End Set     End Property     <Personalizable> _     Public Property Director() As String     Get          Return _director     End Get     Set (ByVal Value As String)          _director = value     End Set     End Property     <Personalizable> _     Public Property Price() As Decimal     Get         Return _price     End Get     Set (ByVal Value As Decimal)          _price = value     End Set     End Property     Private  Sub Page_PreRender()         lblVideoTitle.Text = _videoTitle         lblDirector.Text = _director         lblPrice.Text = _price.ToString("c")     End Sub </script> Title: <asp:Label          Runat="server" /> <br /> Director: <asp:Label          Runat="server" /> <br /> Price: <asp:Label          Runat="server" /> 

The Web Part in Listing 30.22 displays a featured video. Notice that the Web Part implements the IWebActionable interface with its CreateEditorParts() method and WebBrowsableObject property.

The CreateEditorParts() method returns an instance of the TemplatedEditorPart control. The TemplatedEditorPart is initialized with the path to a user control named FeaturedVideoEditTemplate. This user control contains the template for editing the Web Part, and it is contained in Listing 30.23.

Listing 30.23. FeaturedVideoEditTemplate.ascx

[View full width]

<%@ Control Language="VB" ClassName="FeaturedVideoEditTemplate" %> <%@ Reference Control="~/FeaturedVideoPart.ascx" %> <%@ Implements Interface="myControls.ITemplatedEditorPart" %> <%@ Import Namespace="myControls" %> <script runat="server">     Public Sub SyncChanges(ByVal controlToEdit As Control) Implements ITemplatedEditorPart .SyncChanges         Dim part As ASP.FeaturedVideoPart = CType(controlToEdit, ASP.FeaturedVideoPart)         txtVideoTitle.Text = part.VideoTitle         txtDirector.Text = part.Director         txtPrice.Text = part.Price.ToString()     End Sub     Public Function ApplyChanges(ByVal controlToEdit As Control) As Boolean Implements  ITemplatedEditorPart.ApplyChanges         Dim success As Boolean = False         Page.Validate()         If Page.IsValid Then             Dim part As ASP.FeaturedVideoPart = CType(controlToEdit, ASP.FeaturedVideoPart)             part.VideoTitle = txtVideoTitle.Text             part.Director = txtDirector.Text             part.Price = Decimal.Parse(txtPrice.Text)             success = True         End If         Return success     End Function </script> <asp:Label          Text="Video Title:"     AssociatedControl     Runat="server" /> <br /> <asp:TextBox          Runat="server" /> <br /><br /> <asp:Label          Text="Director:"     AssociatedControl     Runat="server" /> <br /> <asp:TextBox          Runat="server" /> <br /><br /> <asp:Label          Text="Price:"     AssociatedControl     Runat="server" /> <br /> <asp:TextBox          Runat="server" /> <asp:CompareValidator          ControlToValidate="txtPrice"     Display="dynamic"     Text="(Must be Currency)"     Type="Currency"     Operator="DataTypeCheck"     Runat="server" /> <asp:RequiredFieldValidator      ControlToValidate="txtPrice"     Display="dynamic"     Text="(Required)"     Runat="server" /> 

Notice that the user control in Listing 30.23 implements the ITemplatedEditorPart interface with its SyncChanges() and ApplyChanges() methods. The SyncChanges() method initializes the form fields in the user control with the current values of the properties of the Web Part being edited. The ApplyChanges() method updates the Web Part being edited with changes made in the edit form.

The page in Listing 30.24 uses the TemplatedEditorPart control to edit the FeaturedVideoPart control.

Listing 30.24. ShowTemplatedEditorPart.aspx

<%@ Page Language="VB" %> <%@ Register TagPrefix="custom" Namespace="myControls" %> <%@ Register TagPrefix="user" TagName="FeaturedVideoPart"   src="/books/3/444/1/html/2/~/FeaturedVideoPart.ascx" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server">     Protected Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)         WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)     End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head  runat="server">     <style type="text/css">         .column         {             float:left;             width:30%;             height:200px;             margin-right:10px;             border:solid 1px black;             background-color: white;         }         .menu         {             margin:5px 0px;         }         html         {             background-color:#eeeeee;         }     </style>     <title>Show Templated Editor Part</title> </head> <body>     <form  runat="server">     <asp:WebPartManager                  Runat="server" />         <asp:Menu                          OnMenuItemClick="Menu1_MenuItemClick"             Orientation="Horizontal"             Css             Runat="server">             <Items>             <asp:MenuItem Text="Browse" />             <asp:MenuItem Text="Design" />             <asp:MenuItem Text="Edit" />             </Items>         </asp:Menu>         <asp:WebPartZone                          Css             Runat="server">             <ZoneTemplate>             <user:FeaturedVideoPart                                  Title="Featured Video"                 runat="server" />             </ZoneTemplate>         </asp:WebPartZone>         <asp:WebPartZone                          Css             Runat="server" />         <asp:EditorZone                          Css             Runat="server" />     </form> </body> </html> 

After you open the page in Listing 30.24, you can view the TemplatedEditorPart by clicking the Edit link and selecting a Web Part to edit (see Figure 30.8).

Figure 30.8. Using the Templated Editor Part.


The nice thing about the TemplatedEditorPart control is that you can associate a different edit template with each of the different types of Web Parts in a page. Just pass the path to a different template when initializing the TemplatedEditorPart in each Web Part's CreateEditorParts() method.




ASP. NET 2.0 Unleashed
ASP.NET 2.0 Unleashed
ISBN: 0672328232
EAN: 2147483647
Year: 2006
Pages: 276

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net