A couple of weeks ago I had a look at a "module" for EPiServer CMS 5. It's going to be a part of our new package called Create+, and is called InteractiveScene. It basically gives the editor the ability to add and configure Flash-based content using EPiServer.
So, how does this end up being an entry on my blog? Well, it got me thinking. But first off I have is to say that I'm not here to replace InteractiveScene in any way. Neither am I here to tell you to do it. My concept builds on top of InteractiveScene, using it, not replacing it. It would of course be possible to use my thoughts to use this outside of EPiServer, in which case you would have to build the parts that I use from InteractiveScene manually.
So, back to the question, why am I blogging about a third party application for EPiServer? And why the @#!*% am I blogging about something that is using Flash? Everybody knows what I think about Flash... I love it, but don't know how to use it. The whole idea about how to use Flash is built around people who have minds that don't work in the same way as mine. So...thats actually the answer to the question. The "education" I got in "IS" was mostly based around the editors interface. All the cool development is actually made in Flash and just configured through EPiServer and thats no good for me. So I do of course have to find a way to tweak the system to use Silverlight instead of Flash.
So, how does "IS" work? Well, it's a standard EPiServer solution. It uses pages in EPiServer to "tell" the Flash what to do and show. Basically it is a slideshow player, but it lets you use Flash-files (.swf) as slides giving you a lot of possibilities. The solution to "telling" the Flash what to do is to let the pages render as XML. Then the Flash makes a call to the page on the server, requesting it in XML-mode. It then parses the XML and does whatever processing is necessary using it.
The actual slideshow builds around the concept of a playlist with slides. In EPiServer the playlist is actually an EPiServer page as well as each one of the slides. But my focus here isn't actually the EPiServer integration so I'll leave that area a bit untouched. The actual application is a Flash-application that works as a host. The host uses that playlist to get hold of the slides. Each of the slide pages contains a reference to an SWF-file that should be used as a slide. It then downloads that slide and adds it to the application. Then there is possibility to set the slideshow timers as well as transition effects between the slides. This is of course a very simplified version of "IS", but it is the core of my thoughts.
I immediately started asking myself questions about Silverlight. "How can I load external UserControls?" was my first one. The developers have to be able to create UserControls, dump them on the server, OUTSIDE of the XAP-file. The XAP can only contain the core application, the actual host. The rest of the controls must be downloaded dynamically. Can this be done? It has to...it's so simple. So what do a good developer do when he needs a solution to a problem. Well, I open Google, but I might not a good programmer. I Googled my question and found AssemblyPart...
AssemblyPart is a class that is basically made for the scenario I'm talking about. It can create an instance of the Assembly-class from a stream. From that assembly object you can then create instances af all classes inside the assembly. The only issue is that you can only create instances of controls using a parameterless constructor. But that will suffice. The actual constructor parts can be solved by creating an interface. So I created a Silverlight Classlibrary to hold my interfaces. The resulting assembly from this project will be in the XAP file and as such available to the dynamically created objects. So inside the library project I created a single interface to begin with and called it IInitializableControl. This interface declares a single method, void Initialize(XElement xml). This method will be called by the host after instantiation. Of course I will first have to check if the control implements the interface, since it would be possible to create a slide that didn't need initialization and therefore didn't implement it. The method takes an XElement object as parameter, making it possible to pass in the xml-configuration for that specific slide. The library project is referenced by both the host application project and the projects containing the slides.
A basic example of downloading a UserControl and instantiating it could look as the following:
[code:c#]
public HostControl()
{
InitializeComponent();
WebClient client = new WebClient();
client.OpenReadCompleted += new OpenReadCompletedEventHandler(AssemblyDownloaded);
client.OpenReadAsync(url to assembly, name of assembly);
}
void AssemblyDownloaded(object sender, OpenReadCompletedEventArgs e)
{
string assemblyName = (string)e.UserState;
_assembliesToDownload.Remove(assemblyName);
AssemblyPart assPart = new AssemblyPart();
Assembly ass = assPart.Load(e.Result);
UserControl ctrl = (UserControl)ass.CreateInstance(classname);
if (ctrl != null)
{
IInitializableControl initCtrl = ctrl as IInitializableControl;
if (initCtrl != null)
initCtrl.Initialize(slide.ConfigXML);
}
}
[/code]
This is the foundation to my slideshow. Hopefully I will finish it in the near future, and when I do I will publish the source code here. Unfortunately my slideshow started out as a simple little thing, but grew as I added features and all of the sudden my design didnt quite work and it got all messy. So I decided to rebuild it and make the design more flexible. Unfortunately that means that the publication of the source code is a bit delayed.