Dr.NETjes

Dion Olsthoorn on ASP.NET

September 2004 - Posts

Introducing PortalFx (ASP.NET 2.0 webpart extensions)

The goal of PortalFx -one of my 'home' projects- is to extend the default functionality of the ASP.NET 2.0 portal framework and its webparts. What triggered me was the '[WebBrowsable]' attribute in ASP.NET Whidbey, which allows you to add custom web-editable properties to a WebPart. When editing the WebPart, these custom properties are added to the 'Custom Settings' box. However, just plain textboxes are shown to edit the values of the custom properties. And of course, I want much more than just  textboxes :) So PortalFx was born...

Some things PortalFx offers so far:
* 'Add New Page' functionality (adding a new aspx portal page on the fly)
* Custom EditorParts (dropdown, rich text editor, date selector using regional settings, etc.)
* Validators (so the data entered in the custom editors can be validated)
* CSS classes, which you can use to give the editor-parts look&feel from a stylesheet
* ListItemProviders, which are used to fill the dropdown lists with values

PortalFx mainly based on Macaw's XPortal framework (http://www.macaw.nl) and also uses HtmlArea v2.03 (http://www.interactivetools.com/products/htmlarea/). My regards go to XPortal's creators: Roel Bergsma, Richard Kuperus and Vincent van Proosdij.

Screenshot 1: Adding a new portal page

Screenshot 2: Editing a PortalFx WebPart

To make use of this additional functionality, I've created a PortalFxWebPart baseclass. Once your webpart inherits from this baseclass, you can add the special PortalFx attributes to the editable properties in your webpart. For instance, if you need a rich textbox the edit the text in your property, you've only got to add a attribute [PortalFxBrowsable(EditorStyle.RichText)] to your class property. That's all!

Example 1: RichText editor
[Personalizable]
[PortalFxBrowsable(EditorStyle.RichText, "Body text")]
public string MyRichText {
  get {return _myRichText;}
  set {_myRichText = value;}
}

Example 2: Required text editor
[Personalizable]
[PortalFxBrowsable(EditorStyle.Text, "Required text", "RequiredTextCssClass")]
[PortalFxValidator (ValidatorType.RequiredField, "Please enter some text!")]
public string MyText {
  get {return _myText;}
  set {_myText = value;}
}

Example 3: Date editor
[Personalizable]
[PortalFxBrowsable (EditorStyle.Date, "Birthdate")]
public DateTime BirthDate {
  get {return _birthDate;}
  set {_birthDate = value;}
}

Example 4: Dropdown of values
[Personalizable]
[PortalFxBrowsable (EditorStyle.DropDown, "Dropdown of values")]
[PortalFxListItems (typeof(ListItemProviders.StringValueListItemProvider), new object[] {"value1","value2"})]
public string MyChoice {
  get {return _myChoice;}
  set {_myChoice = value;}
}

I will post the source-code soon on my weblog!
Postscript: We're building a commercial portal-solution on this code now, so I can't release the sources. I suggest you try the 'WebPart components' project by Fredrik Normen, which has simular features (see overview here).

Adding a 'ValueChangedOnPostback' property to TextBox, DropDownList, CheckBox, RadioButton, etc.

For my current project I'm building a framework that automatically saves all form-data on a page postback. Because a save-operation is time consuming, I want the framework only to save the information when the user really changed the data on the page.

For this, the ASP.NET framework offers a 'changed' event for each editor (TextBox, DropDownList, etc.) . E.g. when a user has changed the value in a textbox, the TextChanged event will be fired somewhere after the Page_Load and before the Page_OnPreRender event. This basically was my problem: I needed to know if the textbox was changed in the Page_Load eventhandler, not after. The TextChanged event of the TextBox just fired to late for me.

My solution was to write my own edit-controls that all inherited from their corresponding System.Web.UI.WebControls classes. All my custom edit-controls implement the IPostBackDataHandler interface, so the ASP.NET framework will call the LoadPostData method somewhere between the Init and the Load event. Also, I added my own IPostBackDataChanged interface, containing the boolean property 'ValueChangedOnPostback'. This property I can now read on the Page_Load event to know if the data of the TextBox was changed by the user.

Example code for my custom TextBox:

namespace MyProject.Web.UI.WebControls
{
   public class TextBox : System.Web.UI.WebControls.TextBox, IPostBackDataHandler, IPostBackDataChanged
   {
      private bool _valueChangedOnPostback = false;
      public bool ValueChangedOnPostback
      { 
         
get { return _valueChangedOnPostback; }
      }

      bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection)
      {
         string text1 = this.Text;
         string text2 = postCollection[postDataKey];
         if (!text1.Equals(text2))
         {
            this.Text = text2;
            _valueChangedOnPostback = true;
         }
         return _valueChangedOnPostback;
      }
      void IPostBackDataHandler.RaisePostDataChangedEvent()
      {
         this.OnTextChanged(EventArgs.Empty);
      }
   }
}

Posted: Sep 18 2004, 09:18 AM by Dr.NETjes | with no comments
Filed under:
More Posts