Wednesday, December 30, 2009

Silverlight Templates: Hot Sheet

Just added the 'Hot Sheet' for silverlight developers at SilverlightTemplates.com. So now, Registered designers can have their contact info listed on our hot sheet. All you need to do is register and upload at least one template. Check it out at http://www.silverlighttemplates.com/Home/Developers.

Wednesday, December 16, 2009

Getting Started With SilverlightTemplates

Check out SilverlightTemplates.com and its Getting Started Guide for Silverlight designers. If you follow this link: Getting Started it should give you all the information you need to start using the site.

The intent with SilverlightTemplates.com is to give Silverlight designers/developers a community portal to get their work out in front of as large an audience as possible. To that end, we are working hard with bloggers, user groups and other commercial sites to spread the word. If you belong to a Silverlight-oriented group, please spread the word. They will gladly do a "link exchange" (you know, you link to us and we'll link to you) as this is a great way to build a strong community.

Contact them at Info@SilverlightTemplates.com

Thursday, November 5, 2009

Load a Xap file from Binary

Recently I was faced with a situation where I needed to load a .xap file from a database and preview the file using Silverlight. Typically, to display a Silverlight app hosted in a web site, one would use the
tag. A detailed description of how to use this with all the available parameters can be found here.

The .xap file, which is really just a compressed package of all the necessary bits needed to run a Silverlight application, typically is stored in the file system and is referenced using the src attribute of the tag. So right there is the problem. Our .xap files are not stored in the file system, but rather in binary fields in our SQL Server 2008 database. The src property is a string indicating the path and file name of the .xap package. Argh.

To deal with this, what was needed is a way to reference the .xap file (stored in the database) with a relative url. A Silverlight application has a mime type of application/x-silverlight. This is important to note because of an interesting way one can use an .aspx page to render binary content. Prior to this, I had used an .aspx page to render jpeg images from a binary stream. Basically, this is done by clearing the response content completely in the code-behind of the page and writing the bits to the response content stream. Set the content-type and your good to go.

Well, as it turns out, this technique not only works for images, but *any* binary format that has an associated mime type. A comprehensive list of mime types can be found here. In the case of images, to set the image source to a binary file stored in a database all you do is create a page as I described and then set the src property to the url of that page. So let's say you want to retrieve an image from your database and render it using an img tag and the url of your page is ../mySite/ImageLoader.aspx. You could call the page passing it the id of the record you want to load and render the image like so:
<img src="..mySite/ImageLoader.aspx?imgId=42" />

That's it. Simple.

See where I'm going with this? How is that different from:


<object type="application/x-silverlight-2"
data="data:application/x-silverlight," width="450" height="220">
<param name="source" value="../mySite/ImageLoader.aspx?xapId=42"/>
object>



Answer: It's not. Just have the page set the content type to application/x-silverlight and you are good to go. For reference, here's the code that rewrites the output stream:

int bufferSize = 1024 * 100; // load 100KB at a time
byte[] buffer = new byte[bufferSize];
int bytesRead = 0;
long bytesToRead;
MemoryStream ms = new MemoryStream(src.ToArray());

// src is the binary file to read. How you load that is a story for another day

bytesToRead = src.Length;
Response.ContentType = this.GetContentType(filetype);
try
{
while (bytesToRead > 0)
{
if (Response.IsClientConnected)
{
bytesRead = ms.Read(buffer, 0, bufferSize);
Response.OutputStream.Write(buffer, 0, bytesRead);
Response.Flush();

bytesToRead -= bytesRead;

// re-initialize the buffer and counter
bytesRead = 0;
Array.Clear(buffer, 0, buffer.Length);
}
else
{
// make sure to break out of the loop if the client disconnects prematurely
bytesToRead = -1;
}
}
}
catch (Exception ex)
{
string err = ex.Message;
Response.Write("" + ERROR_READING_FILE + "");
}
finally
{
if (ms != null)
{
ms.Close();
}
}


Friday, October 23, 2009

Silverlight Templates

Well, it's finally here. I am proud to announce the launch of a new site: SilverlightTemplates.com. This site is a portal for designers/developers to show off their stuff and give them a place to sell their wares. It's a place for people looking for web site templates using Silverlight to hook up with talent from around the world to get some of the hottest site templates money can buy. Are there free Silverlight tempates available. Absolutely. And, you get what you pay for. With SilverlightTemplates.com, you not only get top-quality web site templates using Silverlight, but also a portal to the vast resources in the world of Silverlight and .NET development in general. Check it out and register: SilverlightTemplates.com

Tuesday, September 29, 2009

The Chronicles of George

If you have some time to fall off your chair in tears laughing, this is a must read.



Friday, July 3, 2009

Generate A Schema from a SQL Server Table

Xml Serialization can help if you have to save some very complex data from the web. This is the process:
  1. Post an xml document representing the business object(s) of what you want to save. This should conform to a valid schema (which I'll show you how to generate in just a second).
  2. Deserialize (unmarshall) the xml document on the server.
  3. Save the data to the database
  4. Return something (depends on your specific requirements).
So, to start with, you'll need a valid schema for the tables(s) to which you want to save data. Here's the code (in the form of a console application) to generate those schemas (unless you have some sick affinity with writing these by hand):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;

namespace GenSchema
{
class Program
{
static void Main(string[] args)
{
string constr = @"Data Source=YOURSERVER\;Initial Catalog=YOURDB;Integrated Security=True";
string table = "yourTable";
SqlConnection conn = new SqlConnection(constr);
using (conn)
{
SqlDataAdapter sql = new SqlDataAdapter("SELECT * FROM " + table, conn);

sql.TableMappings.Add("Table", table);
DataSet ds = new DataSet("NewDataset");
sql.FillSchema(ds, SchemaType.Mapped);
ds.WriteXmlSchema(table + ".xsd");
}
}
}
}

Of course, you would fill in the information for your connection string and the table with which you want to work.

Next, to deserialize the data, you must pass in an xml document that conforms to the schema you just generated. That may require some testing, but once you get it right you're golden. If you haven't already, use the xsd.exe utility to generate the C# class from your schema. You'll notice that there are various xml attributes assigned to each property. These will be used in the deserialization process. If you already have the classes (if you're using LINQ to SQL, for example) then simply rename this new class to something else. It's only purpose is to hold the deserialized information temporarily anyway. Here's the code to deserialize your data:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.Xml;
using System.Xml.Serialization;
using System.Text;
namespace GenSchema
{
class Program
{
static void DeSerialize(string xDoc)
{
XmlSerializer ser = new XmlSerializer(typeof(MyObject));
XmlTextReader reader = new XmlTextReader(xDoc);
MyObject obj = (MyObject)ser.Deserialize(reader);
reader.Close();
// Save using whatever method you choose.
}
}

Certainly, your situation will require some modifications to the above code, but this should at least get you started in the right direction. Hope it helps.

Wednesday, May 20, 2009

Right From the Get Go

Ever hear someone use the expression "Right from the Get Go"? What does that mean? Get Go? What am I supposed to be getting? Where have I gone? Well, after a little research, I have discovered the roots of this seemingly silly expression.

Turns out that just before the Renaissance, it was customary to start off large projects with gifts exchanged between all project members. These gifts would generally be of the exotic type - silk, exotic plants, even exotic animals. One of the most coveted gifts, usually only given on the eve of the most important projects, was the gecko. Yes, the little lizard of Geico fame. Soon it became so customary to receive one of these cute reptiles that the giving of a gecko soon became associated with the start of any substantial project - temples, major works of art, opera, etc. Over the centuries, the expression "Right From the Gecko" was transformed through translation and dialect (and perhaps lack of geckos) to "Right From the Get Go".

There you have it.

Thursday, April 30, 2009

Resolving Cannot generate SSPI context.

While there are some pretty complete explanations regarding this error (see links below), if you're looking for a post that forgoes the lengthy explanations and just gets to the good bits ...

You are out of luck on this one :)

That being said, I know that I would have benefited from someone mentioning some of the more basic places to look. In my team's case, the SQL Server account that our web app was using had the password expire on us. When we set up the account we inadvertently neglected to check off the bit about having the password never expire. In a production environment that's probably a good thing. But this is our test server.

Here are those helpful links I mentioned earlier:
How to troubleshoot the "Cannot generate SSPI context" error message
Cannot generate SSPI context” error message, when connect to local SQL Server outside domain

Friday, April 24, 2009

Filter Lists With JQuery

Here's a little snippet that will filter a list as the user types as well as bold the search expression within the list.


$("#searchMyProjects").keyup(function() {
var filter = $(this).val(), count = 0;
$("span.projectSelectionName").each(function() {
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).parent().parent().hide();
$(this).hide();
} else {
$(this).parent().parent().show();
$(this).html($(this).text().replace(new RegExp(filter, "i"), "<b>" + filter + "</b>"));
$(this).show();
count++;
}
});
$("#filterCount").text(count);
});


The filter expression s updated with <b> tags to highlight the search expression within the text. You can use whatever styling you want, of course.

Enjoy.

Monday, April 20, 2009

Upgrading A Subversion Repository

I recently had to move several Subversion repositories from one server to another. Normally, this isn't a big deal, but these repositories were using an old version of Subversion (1.4.something) and had to be upgraded to 1.6.1 which was an entirely different file format. I was able to find the following documentation which fortunately made the process very simple. The following is taken from the Collabnet site. I actually only needed steps 1 and 2. Hope this helps.

HOW TO UPGRADE/DOWNGRADE YOUR REPOSITORY:
----------------------------------------

1. Use an 'svnadmin' binary from a release with the same schema version
as your repository to create a dumpfile of your repository:

$ mv myrepos old-repos
$ svnadmin dump old-repos > dumpfile

2. Use an 'svnadmin' binary from a release with the same schema version
as you want your repository to have to load the dumpfile into a new
repository:

$ svnadmin create myrepos
$ svnadmin load myrepos < dumpfile

OR, if you're feeling saucy, you can do it all at once with a pipe:

$ svnadmin-new create myrepos
$ svnadmin-old dump old-repos | svnadmin-new load myrepos

(If you are running at least version 1.4 and would like to make a
format 3 repository, pass the --pre-1.4-compatible flag to
"svnadmin create".)

3. [OPTIONAL] Loading a dumpfile is both time- and disk-consuming,
as it replays every commit. If your new repository is a BDB
respository, then after the load is complete, you may want to
free up some disk space by removing unused BerkeleyDB logfiles:

$ svnadmin list-unused-dblogs newrepos | xargs rm

Note: If you're using BerkeleyDB 4.2 or newer this will be done
automatically for you, unless you've configured the repository
not to behave this way.

4. Don't forget to copy over any hook scripts (and DB_CONFIG for BDB
repositories, if you changed it) from the old to the new
repository:

$ cp old-repos/hooks/* repos/hooks/
$ cp old-repos/db/DB_CONFIG repos/db/

Monday, April 13, 2009

Setting Up a Subversion Server With Port Forwarding

Requirements: VisualSVN Server

Setting up a Subversion repository, like anything else, is really easy if you know how to do it. Fortunately, VisualSVN Server handles most of the painful stuff that used to have to be done manually. Now it's as simple as installing and setting up your router.

So first, install VisualSVN Server. It comes with it's own set of instructions that are very easy to follow.

Next, open up the admin console to your router and find the section that handles port forwarding. VisualSVN Server gives you the option of using either port 8080 or 8443 for a secure connection. I'd recommend going the secure route, just because. Enter the ip address of the machine on which VisualSVN Server is installed and enter 8443 as the start and end for the ip range. If needed, enter HTTPS as the service type.

That's it. Done. So now you should be able to access your repository from the internet using https://[router_ip_address]:8443/svn/. So let's say your router's ip address is 79.168.199.4 and you have a repository called MyCoolStuff. The url to your repository (from outside your network) would be https://79.168.199.4:8443/svn/MyCoolStuff.

Monday, March 2, 2009

Using RenderPartial() to Recursively Display Data

Scenario: You have hierarchical structure with n number of levels. This data must be displayed in nested divs/tables/lists.

Using the ASP.NET MVC framework (currently at RC1), this can easily be achieved using partial views. Here's the jist of it:

In the .aspx view page:

<% foreach(Thing parent in ViewData.Model) { %>

<% Html.RenderPartial("ThingControl", parent); %>
<% } %>

And then in the partial view:


<!-- display single item here -->

<% if (parent.children.Count > 0){ %>
<% Html.RenderPartial("ThingControl", parent); %>
<% } %>


So the exit condition for the recursion is when parent.children.Count is zero. You can include some styling to indent the nested levels if you want, or not. It's very flexible. Once again, ASP.NET MVC proves it is miles above ASP.NET 2.0.

Tuesday, February 17, 2009

Solving the Late Binding Dilemma With the Factory Pattern

The scenario: Create an instance of a class polymorphically by evaluating a string at runtime.

This could be done by calling Type.GetType("typename"), but this will only work if the type in question is COM visible. For example,

Dim oExcell as Object = Type.GetType("Excel.Application")

is the typical way of getting a reference to an Excel object. But if you want to create an instance of a custom class, there's a lot of complexity that you will need to add to your project. Why can't it just work? (How many times have I found myself asking *that* question?) The following is a concise alternative that will solve the problem.

Here, we have a number of different report classes all based on a common base class. The PrintJobReportFactory class will return the correct instance based on a string.

While most of the time, using hard-coded strings to control program flow impedes scalability, as Tom Cruise said "You know, Bill, there's one thing I learned in all my years. Sometimes you just gotta say, "What the ...".

Of course, he also said "Porche, there is no substitute" to which I would answer with "Mustang GT 500".



Public Class PrintJobReportFactory
Public Shared Function GetReportInstance(ByVal type As String) As PrintJobBase

Dim retVal As PrintJobBase = Nothing
Select Case type
Case "WebDenialsStud"
retVal = New WebDenial()

Case "WebDenialsCoBor"
retVal = New WebDenial()

Case "WebCertifications"
retVal = New WebCertification()

Case "WebApprovals"
retVal = New WebDisclosers()

Case Else
retVal = Nothing
End Select

Return retVal
End Function
End Class

Monday, February 16, 2009

VB.NET Using custom configuration settings

Once again I am surprised at the lack of *working* examples of vb.net code. In this particular case, that may or may not be a completely fair statement because the examples I found (and there were quite a few) could very well have worked, they were just incomplete. Here is a complete example of using an app.config file to define a collection of reports. This will create a parent object with specific configuration information in it, and a collection of child elements which also have custom properties. While no two situations are alike, this should provide you with something that you can modify to suit your own needs. As it turns out, the most complete example I did find was on the msdn site. This is the example that I followed: ConfigurationElementCollection Class

In your app.config...


<configsections>
<section name="ServerReports" type="assemblyName.RSPrintSetup, assemblyName" allowdefinition="Everywhere" allowExeDefinition="MachineToApplication" restartOnExternalChanges="true" />
</configsections>

<serverreports name="PrivateLoanLetters" lockallelementsexcept="Reports" servername="http://rijb-sql2/ReportServer/?" tempfolder="C:\Plexus\Private Loans Letters\Private Loans Letters\Temp\">
<reports>
<clear>
<add name="WebApprovals" reporttype=".pdf" runtime="4:00:00" />
<add name="WebDenialsS" reporttype=".pdf" runtime="2:00:00" />
<add name="WebDenialsC" reporttype=".pdf" runtime="2:00:00" />
<add name="WebCertifications" reporttype=".pdf" runtime="4:00:00" />
</reports>
</serverreports>


And the VB.NET Classes...

Imports System
Imports System.Configuration
Imports System.Collections
Imports System.Collections.Generic
Imports System.Collections.Specialized
Imports System.Reflection
Imports System.Text


Public Class RSReport
Inherits ConfigurationElement

' Test flag.
Private Shared _displayIt As Boolean = False


Public Sub New()

End Sub 'New

_
Public Property Name() As String
Get
Return CStr(Me("name"))
End Get
Set(ByVal value As String)
Me("name") = value
End Set
End Property

_
Public Property RunTime() As String
Get
Return CStr(Me("RunTime"))
End Get
Set(ByVal value As String)
Me("RunTime") = value
End Set
End Property

_
Public Property ReportType() As String
Get
Return CStr(Me("ReportType"))
End Get
Set(ByVal value As String)
Me("ReportType") = value
End Set
End Property


Protected Overrides Sub DeserializeElement(ByVal reader As System.Xml.XmlReader, ByVal serializeCollectionKey As Boolean)
MyBase.DeserializeElement(reader, serializeCollectionKey)

' Enter your custom processing code here.
If _displayIt Then
Console.WriteLine( _
"UrlConfigElement.DeserializeElement({0, {1) called", _
IIf(reader Is Nothing, "null", _
reader.ToString()), _
serializeCollectionKey.ToString())
End If

End Sub 'DeserializeElement

Protected Overrides Function SerializeElement(ByVal writer _
As System.Xml.XmlWriter, _
ByVal serializeCollectionKey As Boolean) As Boolean

Dim ret As Boolean = MyBase.SerializeElement(writer, serializeCollectionKey)

' Enter your custom processing code here.
If _displayIt Then
Console.WriteLine( _
"UrlConfigElement.SerializeElement({0, {1) called = {2", _
IIf(writer Is Nothing, "null", _
writer.ToString()), _
serializeCollectionKey.ToString(), _
ret.ToString())
End If

Return ret

End Function 'SerializeElement


Protected Overrides Function IsModified() As Boolean
Dim ret As Boolean = MyBase.IsModified()

' Enter your custom processing code here.
Console.WriteLine("UrlConfigElement.IsModified() called.")

Return ret

End Function 'IsModified

End Class

_
Public Class ReportsCollection
Inherits ConfigurationElementCollection

Public Sub New()
Dim url As RSReport = CType(CreateNewElement(), RSReport)

' Testing: Manually add the element to the collection.
'Add(url)

End Sub 'New

Public Overrides ReadOnly Property CollectionType() _
As ConfigurationElementCollectionType
Get
Return ConfigurationElementCollectionType.AddRemoveClearMap
End Get
End Property

Protected Overloads Overrides Function CreateNewElement() As ConfigurationElement
Return New RSReport()

End Function 'CreateNewElement


Protected Overloads Overrides Function CreateNewElement(ByVal elementName As String) As ConfigurationElement
Return New RSReport(elementName)

End Function 'CreateNewElement

Protected Overrides Function GetElementKey( _
ByVal element As ConfigurationElement) As [Object]
Return CType(element, RSReport).Name

End Function 'GetElementKey

Public Shadows Property AddElementName() As String
Get
Return MyBase.AddElementName
End Get
Set(ByVal value As String)
MyBase.AddElementName = value
End Set
End Property

Public Shadows Property ClearElementName() As String
Get
Return MyBase.ClearElementName
End Get
Set(ByVal value As String)
MyBase.AddElementName = value
End Set
End Property

Public Shadows ReadOnly Property RemoveElementName() As String
Get
Return MyBase.RemoveElementName
End Get
End Property

Public Shadows ReadOnly Property Count() As Integer

Get
Return MyBase.Count
End Get
End Property

Default Public Shadows Property Item( _
ByVal index As Integer) As RSReport
Get
Return CType(BaseGet(index), RSReport)
End Get
Set(ByVal value As RSReport)
If Not (BaseGet(index) Is Nothing) Then
BaseRemoveAt(index)
End If
BaseAdd(index, value)
End Set
End Property

Default Public Shadows ReadOnly Property Item( _
ByVal Name As String) As RSReport
Get
Return CType(BaseGet(Name), RSReport)
End Get
End Property

Public Function IndexOf( _
ByVal rpt As RSReport) As Integer
Return BaseIndexOf(rpt)

End Function 'IndexOf

Public Sub Add(ByVal rpt As RSReport)
BaseAdd(rpt)
' Add custom code here.
End Sub 'Add

Protected Overrides Sub BaseAdd( _
ByVal element As ConfigurationElement)
BaseAdd(element, False)
' Add custom code here.
End Sub 'BaseAdd

Public Overloads Sub Remove( _
ByVal url As RSReport)
If BaseIndexOf(url) >= 0 Then
BaseRemove(url.Name)
End If

End Sub 'Remove

Public Sub RemoveAt(ByVal index As Integer)
BaseRemoveAt(index)

End Sub 'RemoveAt

Public Overloads Sub Remove(ByVal name As String)
BaseRemove(name)

End Sub 'Remove

Public Sub Clear()
BaseClear()

End Sub 'Clear ' Add custom code here.
End Class

Public Class RSPrintSetup
Inherits ConfigurationSection

Public Sub New()
Me.OutputOptions = New List(Of String)
End Sub

_
Public Property Name() As String

Get
Return CStr(Me("name"))
End Get
Set(ByVal value As String)
Me("name") = value
End Set
End Property

_
Public Property TempFolder() As String

Get
Return CStr(Me("TempFolder"))
End Get
Set(ByVal value As String)
Me("TempFolder") = value
End Set
End Property

' Declare a collection element represented
' in the configuration file by the sub-section
'
' Note: the "IsDefaultCollection = false"
' instructs the .NET Framework to build a nested
' section like ....
_
Public ReadOnly Property Reports() _
As ReportsCollection
Get
Dim urlsCollection _
As ReportsCollection = _
CType(Me("Reports"), ReportsCollection)
Return urlsCollection
End Get
End Property

Protected Overrides Sub DeserializeSection( _
ByVal reader As System.Xml.XmlReader)

MyBase.DeserializeSection(reader)
' Enter custom processing code here.
End Sub 'DeserializeSection

Protected Overrides Function SerializeSection( _
ByVal parentElement As ConfigurationElement, _
ByVal name As String, _
ByVal saveMode As ConfigurationSaveMode) As String

Dim s As String = _
MyBase.SerializeSection(parentElement, _
name, saveMode)
' Enter custom processing code here.
Return s
End Function 'SerializeSection

End Class

Monday, February 9, 2009

Saving PDF reports from SQL Server Reporting Services using VB.NET

While there are plenty of C# examples, there are surprisingly few *working* examples of vb.net code to print reports from Reporting Services via code. Hopefully this will help to fill that void. This sample uses SSRS 2005 and VB.NET and should prove to be a welcome change from using third-party com objects for generating pdf files.



Dim strCreateUrl As String = yourServer + yourReportFolder + "?" + yourReportName + "&rs:Command=Render&rs:format=PDF"

Dim webRequest As System.Net.WebRequest = System.Net.WebRequest.Create(strCreateUrl)
webRequest.Credentials = System.Net.CredentialCache.DefaultCredentials

' Return the response.
Dim webResponse As System.Net.HttpWebResponse = CType(webRequest.GetResponse(), System.Net.HttpWebResponse)
Dim ReceiveStream As System.IO.Stream = webResponse.GetResponseStream()

Dim binByte As Byte()
Dim rdBinaryReader As BinaryReader = New BinaryReader(webResponse.GetResponseStream)
binByte = rdBinaryReader.ReadBytes(webResponse.ContentLength)
rdBinaryReader.Close()

Dim outstream As New MemoryStream()
outstream.Write(binByte, 0, binByte.Length)

Dim buffer(binByte.Length) As Byte
Using stream As FileStream = File.OpenWrite(outputName)

stream.Write(binByte, 0, binByte.Length)
webResponse.Close()

End Using

Tuesday, February 3, 2009

MVC RC1 Released!

We're in the end game, folks!

Coolest features (IMO):
1. Add Controller Command
2. Scaffolding
3. Adding and Customizing Scaffold Templates
4. Quick navigation with Go To Controller / Go To View
5. MSBuild Task for Compiling Views - no more waiting until run time to find view errors.
6. Cross Site Request Forgery (CSRF) Protection with Html.AntiForgeryToken()
7. File Uploading Support

Read all about it...
MVC RC1 Released!

Monday, January 12, 2009

Event Bubbling in JQuery

The scenario: Nested divs representing an outline structure. When the user clicks a heading, the sub-nodes should toggle.

The code would look something like this:


$(".OutlineHeading1 > label").click(function(){
$(this).nextAll(".OutlineHeading2").toggle('slow');
});
$(".OutlineHeading2 > label").click(function(){
$(this).nextAll(".OutlineHeading3").toggle('slow');
});
$(".OutlineHeading3 > label").click(function(){
$(this).nextAll(".OutlineHeading4").toggle('slow');
});
$(".OutlineHeading4 > label").click(function(){
$(this).nextAll(".OutlineHeading5").toggle('slow');
});
$(".OutlineHeading5 > label").click(function(){
$(this).nextAll(".OutlineHeading6").toggle('slow');
});


The problem: In Internet Explorer, the click event gets fired multiple times in the nested divs because of event bubbling.

The solution: return false. As in:

$(".OutlineHeading1 > label").click(function(){
$(this).nextAll(".OutlineHeading2").toggle('slow');
return false;
});
$(".OutlineHeading2 > label").click(function(){
$(this).nextAll(".OutlineHeading3").toggle('slow');
return false;
});
$(".OutlineHeading3 > label").click(function(){
$(this).nextAll(".OutlineHeading4").toggle('slow');
return false;
});
$(".OutlineHeading4 > label").click(function(){
$(this).nextAll(".OutlineHeading5").toggle('slow');
return false;
});
$(".OutlineHeading5 > label").click(function(){
$(this).nextAll(".OutlineHeading6").toggle('slow');
return false;
});


Simple as that.