Creating a widget for BlogEngine.NET 1.5
February 1, 2010Note: this also applies to BlogEngine.NET 1.6
New widget zones have been added, but widget architecture remains the same.
BlogEngine.NET has a nice and simple plug-in model for “widgets” (those areas you see to the right of this blog) and this article will show you how simple it is to create your own with version 1.5.
If you open up the source code you can see the widget architecture is based on the following conventions: widgets must be contained in a folder of the same name within the widgets folder, and consist of a (required) widget.ascx user control and an (optional) edit.ascx user control. All of the built-in and custom widgets reside here.
A simple widget
Create a folder named “TestWidget” and add to it a user control named “widget”. In the code-behind, change the control to inherit WidgetBase instead of System.Web.UI.UserControl. Provide an implementation for the 3 abstract WidgetBase members: Name, IsEditable, and LoadWidget().
Some notes about the these WidgetBase members:
- Name: This must be the same as the folder name the widget resides in, in this case, “TestWidget”.
- IsEditable: This tells BE.NET whether to serve up a custom edit control for administering the widget. Set to false for now.
- LoadWidget(): This is the method that fires when the widget is loaded and should be the entry point for the widget’s logic.
A simple “Hello World” example is below. Not shown is a Label control added to the .ascx page titled “lblTest”.
public partial class widgets_TestWidget_widget : WidgetBase
{
public override string Name
{
get { return "TestWidget"; }
}
public override bool IsEditable
{
get { return false; }
}
public override void LoadWidget()
{
lblTest.Text = "Hello World!";
}
}
Note: Even without providing any edit functionality, BE.NET allows you to edit (or hide) the title of the widget within the application. In this case, we might want to add a space in the title.
A slightly more complex widget
Any normal ASP.NET server control can be used within a widget, even those with their own events such as a GridView or Repeater. Please note that when attempting to use a button or any other control that causes a postback, it “worked,” but caused a script error (in IE7 at least: Line 6, Char 3314, 'BlogEngine' is undefined) for me. For that reason, I’d suggest you avoid any use of postbacks. A widget control really shouldn’t be interactive through postbacks anyway.
Here’s an example of a slightly more complex widget that uses a Repeater control, an OnItemCreated event, and a custom data class:
Markup:
<asp:Repeater ID="rTest" runat="server"
onitemcreated="rTest_ItemCreated" >
<ItemTemplate>
<%#Eval("Name") %><br />
</ItemTemplate>
</asp:Repeater>
Codebehind:
public override void LoadWidget()
{
List<TestClass> collection = new List<TestClass>();
collection.Add(new TestClass("item1"));
collection.Add(new TestClass("item2"));
collection.Add(new TestClass("item3"));
rTest.DataSource = collection;
rTest.DataBind();
}
protected void rTest_ItemCreated(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
((TestClass)e.Item.DataItem).Name = ((TestClass)e.Item.DataItem).Name + " - DataBound!";
}
}
public class TestClass
{
public TestClass(string name){
_Name = name;
}
private string _Name;
public string Name { get { return _Name; } set { _Name = value; } }
}
The Result:
Defining and editing custom properties
To give blog administrators the ability to edit custom defined widget properties, a user control named edit must be added to the widget’s folder. This control must inherit the WidgetEditBase class and implement a single method, Save().
Each widget can use a StringDictionary to get and save settings pertaining to it. The WidgetEditBase class exposes a GetSettings() and SaveSettings() method to do so. Please note that SaveSettings() must be called after you change any settings, or else they will not be committed. The following is a simple example demonstrating this:
Markup:
A Text Field: <asp:TextBox ID="txtTest" runat="server"></asp:TextBox> <br /> A Check Box: <asp:CheckBox ID="cbTest" runat="server" />
Codebehind:
public partial class widgets_TestWidget_edit : WidgetEditBase
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
StringDictionary settings = GetSettings();
if (settings.ContainsKey("test1"))
txtTest.Text = settings["test1"];
if (settings.ContainsKey("test2"))
cbTest.Checked = Convert.ToBoolean(settings["test2"]);
}
}
public override void Save()
{
StringDictionary settings = GetSettings();
settings["test1"] = txtTest.Text.ToString();
settings["test2"] = cbTest.Checked.ToString();
SaveSettings(settings); //commit changes
}
}
Editing the widget:
Utilizing custom properties
It should be no surprise that the widget user control can access its settings in the very same way. Here’s an example of how this same widget would retrieve and display these two settings demonstrated above:
public override void LoadWidget()
{
StringDictionary settings = GetSettings();
lblTest.Text = settings["test1"] + "<br/>" + settings["test2"];
}
Widget inspiration
BlogEngine.NET has a number of solid widgets built in, plus there is a codeplex project containing links to a number of other custom ones: http://blogenginewidgets.codeplex.com/
I’d encourage you to poke through the source code of any of these to see how they work under the hood. They are quite straightforward once you understand the basic requirements.
I started working on a “Delicious Bookmarks” widget today, modeled after the built-in Twitter widget (which is essentially just an RSS reader specifically branded for tweet feeds). It is implemented just as described above, but of course with a bit more code do do the RSS retrieval, caching, etc. Stay tuned, as I might release the source code on an upcoming post, but here’s a preview:
Tags: widget
Categories: BlogEngine.NET
