To demonstrate the use of themes and skins, you’ll create a new web site (Themes) but you will use Copy Web Site to bring over all the personalization code from the previous example and set the start page to Welcome.aspx. Test the application to make sure it still works as expected.
To begin modifying your application, you’ll need some controls whose look and feel you can set.
Open Welcome.aspx, and drag on some new controls, as shown in Figure 12-44.
Figure 12-44.Welcome.aspx new controls
There are four labels (each with names beginning withlbl):ListBox,RadioButtonList,Calendar, andTextBox. Use the default properties (other than the names) for all, except remove all text fromTextBox1’sTextproperty.
You’ll also need to click on the smart tag for bothlbItems(theListBox) andRadioButtonList1(theRadioButtonList). For each of these, choose Edit the List items, as shown in Figure 12-45.
Figure 12-45.Choose Edit the List items
In the ListItem Collection Editor add four items to the list box, and six items to theRadioButtonList, as shown back in Figure 12-44.
You will use themes to change the look and feel of the new controls.
Themes are stored in your project in a folder named App_Themes. To create this folder, go to Solution explorer, right-click on the project folder, and choose Add Folder -> Theme Folder. Name the new folder Dark Blue—the folder App_Themes will be created automatically, with a Theme folder named Dark Blue immediately under it. Right-click on App_Themes and create a second theme folder, named Psychedelic.
Right-click on the Dark Blue theme folder and choose Add New Item. From the template lists, choose Skin File and name it Button.skin (to hold all the button skins for your Dark Blue theme), as shown in figure Figure 12-46.
Figure 12-46.Creating the skin file
Each skin file is just a text file that contains a definition for the control type, but with no ID. Thus, your Label.skin file for the Dark Blue theme might look like this:
Create skin files for each of the following types in both themes:
Button.skin
Calendar.skin
Label.skin
ListBox.skin
RadioButton.skin
Text.skin
At this point, your solution should look more or less like Figure 12-47.
Figure 12-47.Themes and skins in your project
You can experiment with adding attributes to these new skin files and see the effects they produce on your user interface. Start by copying the text from Label.skin, then modifying it so it affects the appropriate control type (asp:Buttonin Button.skin,asp:Calendarin Calendar.skin,asp:ListBoxin ListBox.skin, etc.).
To let your users choose the theme they like and have their preference stored in their profile, you need to add a single line to the properties element in the profile element of Web.config:
<add name="Theme" />
Save and rebuild your application.
Specify Themes for Your Page
You can set the themes on your page either declaratively or programmatically. To set a theme declaratively, add the Theme attribute to the Page directive:
You can also set the theme programmatically, either by hard coding it or (even better) by setting it from the user’s profile.
StyleSheet themes are set by overriding theStyleSheetThemeproperty for the page. IntelliSense will help you with this. Open Welcome.aspx.vb and scroll to the bottom of the class. Type the word overrides and all the overridable members are shown. Start typing sty and IntelliSense will scroll to the property you want:StyleSheetTheme, as shown in Figure 12-48.
Figure 12-48.Overriding a method
Once IntelliSense finds the property you want, press Tab to accept it. Fill in the accessors, as shown in Example 12-22.
Example 12-22. Setting a StylesheetTheme property
Public Overrides Property StyleSheetTheme() As String Get If Profile.IsAnonymous = False And Profile.Theme IsNot Nothing Then Return Profile.Theme Else Return "Dark Blue" End If End Get Set(ByVal value As String) Profile.Theme = value End Set End Property
If you are going to set a customization theme programmatically, however, you must do so from thePreInitevent handler for the page,* because the theme must be set before the controls are created. APreInitevent handler is shown in Example 12-23.
Example 12-23. Welcome page PreInit event handler
Protected Sub Page_PreInit( _ ByVal sender As Object, ByVal e As System.EventArgs) _ Handles Me.PreInit If Profile.IsAnonymous = False Then Page.Theme = Profile.Theme End If End Sub
Setting the theme inPreInitcreates a bit of a difficulty when you want to allow the user to change the theme at runtime. If you create a control that posts the page back with a new theme, thePreInit code runs before the event handler for the button that changes the theme, and so by the time the theme is changed, the controls have already been drawn.
* The pre-init event is new in Visual Basic 2005.
To overcome this you must, unfortunately, refresh the page again. An alternative is to set the themes in another page. For example, add two buttons to the ProfileInfo.aspx page (at the bottom of the table at the bottom of the page). Set the properties of the first button to:
Notice that the two buttons share a single Click event handler,Set_Theme, shown in Example 12-24. An easy way to have Visual Studio 2005 set up that event handler for you is to switch to Design view and click on one of the buttons. Click on the lightning bolt in the Properties window to go to the events, and double-click on theSet_Themeevent. You are now ready to implement the event handler. You’ll cast the sender to the button and check its text, setting the theme appropriately.
Example 12-24. Common Click event handler for ThemeBlue and ThemePsychedelic buttons
Protected Sub Set_Theme( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles ThemePsych.Click Dim btn As Button = CType(sender, Button) If btn.Text = "Psychedelic" Then Profile.Theme = "Psychedelic" Else Profile.Theme = "Dark Blue" End If End Sub
When the user is not logged on, the Welcome page’s default theme will be used. Once the user sets a theme in the profile, that theme will be used when you return to the Welcome page. Create skins for your two themes and then run the application to see the effect of applying the themes.
You can override the theme for particular controls by using named skins.
Set the lblRadioButtonListlabel to be red even in the Deep Blue theme, by using a named skin. To accomplish this, create two Label skins in the Label.skin file within the Deep Blue folder.
The first skin is the default; the second is a named skin, because it has aSkinIDproperty set toRed. Click on theRadioButtonListcontrol in Design view and set theSkinIDproperty toRed. Or, open the source for Welcome.aspx and find theRadioButtonListand add the attributeSkinID="Red":
When you log in and set your theme to Dark Blue, you’ll find that the label for theRadioButtonListisRed, as shown in Figure 12-49. (You didn’t get stuck with a black & white book, did you?)
Web Parts allow your users to reconfigure sections of your site to meet their own needs and preferences. Many information providers allow the user to pick which content they want displayed and in which column to display it. Web Parts allow you to provide that functionality with drag-and-drop “parts” of your page.
Create a New Site
To learn about Web Parts, create a new web site (call it WebParts) and copy the SitePersonalization web site from the beginning of this chapter (not the Themes web site you just completed).
Set the Welcome page as the start page and make sure you can log in with an account you created previously (or, alternatively, setCreateAccountas the start page and create a new account to work with).
Web Parts Architecture
Web Parts are created and managed on top of personalization using the WebPartManager control to manage the interaction of Web Parts, and normal ASP UI Controls to create the user-managed interface.
Creating Zones
A page that uses Web Parts is divided into zones: areas of the page that can contain content and controls that derive from the Part class (Part controls). They can also contain consistent UI elements (header and footer styles, border styles, etc.) known as the chrome of the control.
It is typical (though certainly not required) to organize these zones using tables.
To see a simple example of Web Parts at work, follow these steps:
Create a new page called WebPartsDemo.aspx.
Open the WebParts section of your Toolbox, and drag aWebPartManageronto your page.
The job of theWebPartManageris to track and coordinate all the Web Part controls on the page. It will not be visible when the page is running.
Add a new table, with two rows and three columns. Rearrange the columns so that they are not of even size.
Drag aWebPartZoneinto each of the six table cells. EachWebPartZonewill have a default name (e.g.,WebPartZone6) and a default heading. You can easily modify either or both of these properties in the Properties window, as shown in Figure 12-50.
Set theHeaderTextproperty on the first Web Part control toNews.
Adding Controls to Zones
Drag a Label control into the zone. The normal ASP.Label control is automatically wrapped in a Web Part control, and its title is set to Untitled, as shown in Figure 12-51.
Figure 12-50.Web Parts Zones
Figure 12-51.Label Web Part
Switch to Source view and set theTitleproperty of the label to Today’s News and the text to<br/>New Translation of In Search Of <em>Lost Time</em> Sets English World On Fire.
Title is not normally a property of the Label control, and will not show up in the Properties window or IntelliSense. However, when you add it to aWebPartZoneit is wrapped, at runtime, in aGenericWebPart control that does recognize this property. Ignore intelliSense and press on.
Switch back to Design view and drag aListBoxcontrol intoWebPartZone3. Set the header text for theWebPartZonetoSponsors. Click on theListBox, and then on its smart tag and then click on Edit Items to open the ListItems Collection Editor. Add a few items to theListBox. Back in Source view, set theTitle property toOur Sponsors. (This control, like theLabelcontrol, does not inherently have aTitle property, so IntelliSense will complain, but as the note above explains, all will be well.)
Add a link in theLoggedInTemplatein Welcome.aspx, to take the user to your new page and run the program. Login using one of the accounts you set up previously and click on the link to the new Web Parts page.
You should see two Web Parts, as shown in Figure 12-52.
Figure 12-52.Two Web Parts visible
Minimizing and Restoring
Click on the tag next to the title and a menu appears allowing you to minimize or close the Web Part, as shown in Figure 12-53.
Figure 12-53.Minimize or Close
If you choose Minimize, the Web Part is minimized to its title, and the minimize tag offers the choices of Restore or Close, as shown in Figure 12-54.
Figure 12-54. Restore or close
Exit the application. Start it again, sign back in, and navigate back to these pages. Aha! The minimized zone remains minimized. Each individual’s personalized Web Parts are automagically persisted through the personalization database.
Web Parts
Web Part controls derive from the Part class and are the essential UI of a Web Parts page. You can create custom Web Part controls or you can use existing ASP.NET server controls, user controls, and custom controls, all of which will be wrapped for you in a generic Web Parts control.
Web Parts provide users with the ability to change the layout of the Web Part controls by dragging them from zone to zone. You may also allow your users to modify the appearance of the controls, their layout and their behavior.
The built-in Web Parts control set provides basic editing of any Web Part control on the page. You can also create custom editor controls that allow users to do more extensive editing.
Creating a User Control to Enable Changing Page Layout
To edit the contents of zones or move controls from one zone to another, you need to be able to enter Edit and Design mode. To do so, you will create a new user control called DisplayModeMenu.ascx, that will allow the user to change modes among Browse, Edit, and Design, as shown in Figure 12-55.
Figure 12-55.Display Mode user control
Right-click on the web project in the Solution explorer and choose Add New Item. Select Web User Control and name the new user controlDisplayModeMenu.
User controls are described in detail in Chapter 13.
Add the highlighted code listed in in Example 12-25 to the content file of your new user control.
This code creates a panel, and within that panel it adds a single drop-down list (ddlDisplayMode). It also sets the event handler for when the Selected item changes in the drop-down list. To support this page, open the code-behind file (DisplayModeMenu. ascx.vb) and add the code shown in Example 12-26.
Example 12-26. DisplayModeMenu.ascx.vb
Imports System.Web.UI Partial Class DisplayModeMenu Inherits System.Web.UI.UserControl
Dim myWebPartManager As WebPartManager
Protected Sub Page_Init(_ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Init AddHandler Page.InitComplete, AddressOf Page_InitComplete End Sub
Protected Sub Page_InitComplete( _ ByVal sender As Object, _ ByVal e As System.EventArgs)
For Each mode As WebPartDisplayMode In _ myWebPartManager.SupportedDisplayModes Dim modeName As String = mode.Name If mode.IsEnabled(myWebPartManager) Then Dim myListItem As ListItem = _ New ListItem(modeName, modeName) ddlDisplayMode.Items.Add(myListItem) End If Next End Sub
Protected Sub ddlDisplayMode_SelectedIndexChanged( _ ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles ddlDisplayMode.SelectedIndexChanged Dim selectedMode As String = ddlDisplayMode.SelectedValue Dim mode As WebPartDisplayMode = _ myWebPartManager.SupportedDisplayModes(selectedMode) If (mode IsNot Nothing) Then myWebPartManager.DisplayMode = mode End If End Sub
Protected Sub Page_PreRender( _ ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.PreRender Dim items As ListItemCollection = ddlDisplayMode.Items Dim selectedIndex As Integer = _ items.IndexOf(items.FindByText(myWebPartManager.DisplayMode.Name)) ddlDisplayMode.SelectedIndex = selectedIndex End Sub End Class
Open theWebPartsDemopage in Design mode and make a space between theWebPartManagerand the table of zones. Drag the DisplayModeMenu.ascx file from the Solution explorer into that space. Change to Source view and notice that Visual Studio 2005 has done two things for you: it has registered the new control:
Before testing this, delete the Web Part Zone in the lower righthand cell in the table and drag an Editor Zone into that cell. Drag an AppearanceEditorPart and a LayoutEditorPart onto the Editor Zone. To make the Editor Zone stand out, click on its smart tab and choose AutoFormat and then Professional. Your design page should look more or less like Figure 12-56.
Figure 12-56.Editor Zone
Moving a Part
Run the application. When you log in and go to the Web Parts page, you are in Browse mode. Use the Display mode drop-down list to switch to Design mode and all the zones (except the Editing Zone) appear. You can now click on any Web Part (e.g., Today’s News) and drag it to any other zone, as shown in Figure 12-57.
Next, change the drop-down list to Edit mode. Nothing much happens, but click on the drop-down tag on one of the Web Part controls. A menu appears that now includes Edit, as shown in Figure 12-58.
Click Edit and the Edit Zone appears, allowing you to edit the current Web Part, as shown in Figure 12-59.
The Appearance editor lets you change the title and look of the Web Part, while the Layout lets you change, among other things, the zone where the Web Part will appear.
Figure 12-57.Dragging a Web Part
Figure 12-58.Edit mode
Adding Parts from a Catalog
You may want to provide a catalog of Web Parts that your users can add to the various zones. To do so, open WebPartsDemo.aspx and find Zone 4. Remove it from the cell so that the cell is empty. Next, drag a CatalogZone control into newly empty cell. Click on the zone and in the Properties window make sure the HeaderText property is set to Catalog Zone. Drag a DeclarativeCatalogPart control into the zone, as shown in Figure 12-60.
Click the smart tag on theDeclarativeCatalogPartand select Edit Templates. From the standard tab of the Toolbox drag on a Calendar and a File Upload control, as shown in Figure 12-61.
Figure 12-59.Editor Zone in action
Figure 12-60. Adding a DeclarativeCatalogPart control
Figure 12-61.Dragging controls into the Declarative Template
Before you run your program, switch to Source view and find the catalog zone you’ve added. Within the<WebPartsTemplate>element, add aTitleattribute to both theCalendarand theFile Uploadcontrols, as shown in Example 12-27. (Again, IntelliSense will not like this attribute, but be strong and do it anyway.)
Run the application. Drop down the display mode and notice that the Catalog mode has been added, as shown in Figure 12-62.
Figure 12-62.Catalog added to Display mode
When you select Catalog, the Catalog Zone is displayed. You may select one of the controls and decide which zone to place it in, as shown in Figure 12-63.
Figure 12-63.Adding a control from the catalog
Once you’ve picked your control and the zone to add it to, click Add and the control instantly appears in the designated zone.