Thursday, February 15, 2007

Tutorial: Create your own Sitecore Wizard

This post applies to Sitecore 5.3 It's really quite logical - if you're writing your own wizards for sitecore they always look better if they are real sitecore wizards, so here's a quick tutorial on how to make your own. We're gonna go thru this in 5 steps:
  • Create a custom wizard sheer ui / xaml code
  • Create the CodeBeside class for our wizard
  • Create a Command that we can later use to launch it with
  • Edit the Web.Config and Commands.Config file
  • Create a context menu extension that launches our wizard
Still interested? well, let's start then! Step 1: Wizard XML code Create a folder somewhere beneath \sitecore modules\shell where you're going to store the code to your new wizard. The sheer ui / xaml code for the wizard is built using Sitecores WizardForm, WizardFormFirstPage, WizardFormPage & WizardFormLastPage controls so it'll look great and take advantage of all the existing features they provide, like intro & exit pages, navigation, events and so on. here's the code:
<?xml version="1.0" encoding="utf-8" ?> <control xmlns:def="Definition" xmlns="http://schemas.sitecore.net/Visual-Studio-Intellisense"> <ExampleWizard> <WizardForm CodeBeside="Interfolio.Examples.ExampleWizardForm,Interfolio.Examples"> <WizardFormFirstPage ID="FirstPage" Icon="People/48x48/user1.png"> <Border Class="scWizardWelcomeTitle"> <Literal Text="Example Wizard"/> </Border> <Literal Text="This wizard will help you:"/> <ul> <li> <Literal Text="Create your own wizard."/> </li> <li> <Literal Text="Understand the sitecore wizard."/> </li> </ul> </WizardFormFirstPage> <WizardFormPage ID="WizardPageOne" Header="Page 1" Text="Select one of the available options. When done, click next to continue." Icon="People/48x48/user1.png"> <WizardFormIndent> <GridPanel ID="FieldsAction" Columns="2" Width="100%" CellPadding="2"> <Literal Text="I want to.." GridPanel.NoWrap="true" Width="100%" /> <Combobox ID="SelectActions" GridPanel.Width="100%" Width="100%"> <ListItem ID="create" Header="Keep looking at this example" Value="newsite" /> <ListItem ID="edit" Header="Do something, somewhere else" Value="editsite" /> <ListItem ID="delete" Header="Yeah, you get the idea.." Value="deletesite" /> </Combobox> </GridPanel> </WizardFormIndent> </WizardFormPage> <WizardFormPage ID="WizardPageTwo" Header="Page 2" Text="Specify some information. Name needs to be set before moving on. When done, click next to continue." Icon="People/48x48/user1.png"> <WizardFormIndent> <GridPanel ID="FieldsInformation" Columns="2" Width="100%" CellPadding="2"> <Literal Text="Name:" GridPanel.NoWrap="true"/> <Edit ID="Name" Width="100%" Change="OnNameChanged" GridPanel.Width="100%"/> <Literal Text="Location:" GridPanel.NoWrap="true"/> <Edit ID="Location" Width="100%" GridPanel.Width="100%"/> <hr GridPanel.ColSpan="2" /> <Literal Text="URL:" GridPanel.NoWrap="true"/> <Edit ID="URL" Disabled="true" Width="100%" GridPanel.Width="100%"/> <hr GridPanel.ColSpan="2" /> <Literal Text="Checks:" GridPanel.NoWrap="true" /> <Checkbox ID="Check1" Header="Check one" /> <Literal Text="" GridPanel.NoWrap="true" /> <Checkbox ID="Check2" Header="Another check" /> </GridPanel> </WizardFormIndent> </WizardFormPage> <WizardFormPage ID="WizardPageThree" Header="Page 3" Text="More things to do here. When done, click next to continue." Icon="People/48x48/user1.png"> <WizardFormIndent> <GridPanel ID="FieldsOthers" Columns="2" Width="100%" CellPadding="2"> <Literal Text="Something else:" GridPanel.NoWrap="true"/> <Edit ID="SomethingElse" Width="100%" Change="OnNameChanged" GridPanel.Width="100%"/> <Literal Text="More text:" GridPanel.NoWrap="true"/> <Edit ID="MoreText" Width="100%" GridPanel.Width="100%"/> </GridPanel> </WizardFormIndent> </WizardFormPage> <WizardFormLastPage ID="LastPage" Icon="People/48x48/user1.png"> <Border> <Literal Text="The wizard has completed."/> </Border> </WizardFormLastPage> </WizardForm> </ExampleWizard> </control>
Step 2: Wizard C# code Now, for our wizard to even show and do, well, anything, we need to define it and handle some example events, like validating a Edit control and enable/disable buttons. The class is based on sitecores own WizardForm in order to get all the already-existing (and great) functionality. here's the code:
namespace Interfolio.Examples { public class ExampleWizardForm : WizardForm { // specify each control we need to access from the xml as 'protected' and it'll be available protected Edit Name; public ExampleWizardForm() { } protected override void OnLoad(EventArgs e) { base.OnLoad(e); if (!Context.ClientPage.IsEvent) { // handle initial code here } } protected void OnNameChanged() { // check to make sure the name Edit is not empty (in a negative boolean style) bool IsOk = (this.Name.Value == null) (this.Name.Value.Length == 0); base.NextButton.Disabled = IsOk; if (IsOk) { Context.ClientPage.ClientResponse.Focus("Name"); } Context.ClientPage.ClientResponse.SetReturnValue(true); } protected override void ActivePageChanged(string page, string oldPage) { base.ActivePageChanged(page, oldPage); if (page == "WizardPageTwo") { // make sure next button is disabled unless the Name is entered this.OnNameChanged(); } else if (page == "LastPage") { base.BackButton.Disabled = true; } } protected override bool ActivePageChanging(string page, ref string newpage) { if (newpage == "LastPage") { // disable the back button since we've finished the wizard base.BackButton.Disabled = true; // return the boolean status of our 'commit' method return this.WhatWeWantToDo(); } return base.ActivePageChanging(page, ref newpage); } private bool WhatWeWantToDo() { // really do something else here, this is just an example.. return true; } } }
Step 3: Command C# code The purpose of this command is to make your newly created wizard launchable from pretty much anywhere you want. It is based on sitecores own Command. here's the code:
namespace Interfolio.Examples { [Serializable] public class OpenWizard : Command { public OpenWizard() { } public override void Execute(CommandContext context) { // get the uri of our wizard by finding the control using Sitecore's UIUtil string controlUrl = Sitecore.UIUtil.GetUri("control:ExampleWizard"); // broadcast the need to show the wizard to the sitecore shell Context.ClientPage.ClientResponse.Broadcast(Context.ClientPage.ClientResponse.ShowModalDialog(controlUrl), "Shell"); } public override CommandState QueryState(CommandContext context) { return base.QueryState(context); } protected void Run(Sitecore.Web.UI.Sheer.ClientPipelineArgs args) { } } }
Step 4: Config Additions Before using our code anywhere we need to tell Sitecore that it's available, which is normal since it's new code. In the Web.Config file, locate the section <controlsources> and add the source folder of your new code:
<source mode="on" namespace="Interfolio.Examples" folder="/sitecore modules/shell/interfolio/Examples" deep="true"> </source>
In the Commands.config file (located at \App_Config), add the following:
<command name="interfolio:examplewizard" type="Interfolio.Examples.OpenWizard,Interfolio.Examples" />
Save both files. As you may have noticed the example is located in interfolio\Examples, this is just where i stored it for this tutorial, you can have any folder you wish, just make sure that if you change the namespace or assembly or folders that you refactor the change onto the rest of your code. Step 5: Launching the wizard Now all the code is complete and we only need to have a way of launching it within sitecore. While this approach isn't really that durable unless your wizard is extremely generic it's still an easy way to quickly try something you've done.
  • Open Sitecore in your browser, login and switch database to 'core'
  • Navigate to Sitecore/System/Context Menus/Default and duplicate the 'New' item and name it 'ExampleWizard'
  • Change the fields DisplayName to 'ExampleWizard' and Message to 'interfolio:examplewizard(id=$Target)'
  • Save it and switch back to the 'master' database
That's it! If you've followed these steps correctly you should by now be able to right click an item in the Content Editor and click ExampleWizard which will launch your newly created wizard. Take care, P.

5 comments:

Sander Falise said...

Looks easy enough ... but WHERE do you put al that code? Into files created on the harddisk, into files created with SiteCore ... I'm a noob on this, but it seems you missed a few steps?

Unknown said...

if you follow the example step by step you'll be fine, i don't think there's anything left out.. if you could provide more specific details to your question i might understand it better.

regards,

P.

Sander Falise said...

Hi Peter,

First, I must admit that this is my second week working with SiteCore 5.3 and I have no experience with XAML so if I say I'm a noob, I'm not kidding :) I'll try to be as precise as I can.

Step 1:

You create a XAML file in \sitecore modules\shell, but what should the name of the file, where all the code goes in to, be?

Step 2 & 3:

Where does the C# code for the Wizzard and the Command go? If it's into files, where should I put them and what should they be named? If it's somewhere in the SiteCore Development Center, where should I put them and what should I name them?

Step 4:

No questions here; the namespace, folder, name and type attributes point to the namespace, folder and classnames created earlier.

Step 5:

I haven't gotten here yet ;)


Thanks for your time Peter!

Unknown said...

ok, let's see..

the file that holds the xaml/sheer ui code is an xml file, and i suggest name it something appropriate, i usually end them with Wizard.xml, like BlogWizard.xml

the C# code parts are class files that you'll need to compile with visual studio into a dll, then place the dll file in the \bin folder of the website. the name of the wizard class needs to be the same as referenced in the wizard xml file. look for the "CodeBeside" definition in that xml file. in the example it looks like this
CodeBeside="Interfolio.Examples.ExampleWizardForm,Interfolio.Examples". the class is ExampleWizardForm.cs and the dll is Interfolio.Examples.dll.

hope that was of some help to you, and if not just gimme a shout and i'll take another stab at it :)

regards,

Peter

bostian said...

i have a question... i am also new to sitecore. I know how to add items and edit them thrue .net c#. But how can i add code to for example news site, that is created in content manager? thanks