Extensions Made Easy v1.12: Fuzzy searching

Once you’ve grabbed EME v1.12.1 or higher, you can explore a new functionality that I ported from a client project to the extension called Fuzzy searching…  Although created months ago, published weeks ago, I never found the time to blog about this gimmick until minutes ago.  Time to post a small example, in VB.Net

What is Fuzzy searching?

Suppose there’s a patient tracker application, written in LightSwitch.  When I’m seeing the doctor, he has to enter my exact family name, or part of it, to find my record between the many Patient entities.  Chances are, I’m seeing the doctor because I have a sour throat or allergic reaction on my mouth, and I’m not in the mood for spelling out my last name, again (I ALWAYS have to spell out my last name… Well, about 99% of the cases anyways, my wife is called Kundry Annys, she has to spell it out in 100% of all cases)…  If the patient tracker application developer implemented fuzzy searching, he could make the doctor and his/her patients lives easier by implementing fuzzy searching…

Fuzzy searching is a technique where searching a list of items or entities is not done based on exact string match, but on “partial” or “metaphonic” match.  Basically, if the user enters a search term like “Hagen”, it’s convenient in some very particular scenarios to return all entities with a property that sounds like “Hagen”, including “Haeghen”, “Haegen” and “Hägen”.

Although this isn’t something you’d want to do for each search screen, some user scenarios definitely justify the use of a Fuzzy search.  Take my name for example: “Jan Van der Haegen”.  Although it might sound like an exotic name to the non-Dutch speaking audience, my name is literally translated as “John of the Hedge”.  You can imagine that this is quite a common family name in Belgium and the Netherlands, and thus, comes in a variety of notations across different families, from “Haägen” to “Verhaeghe” to “Van der Haegen” to…

Setting up a sample application

To test this fuzzy searching implementation, create a new LightSwitch application.

Note to self: Application798? Really? Get a life!

In the application, create a new entity called Patient.

As you might expect, the patient entity will contain some common fields like FamilyName, FirstName, and a computed field called FullName, for displaying purposes, which is computed as:

Namespace LightSwitchApplication

    Public Class Patient

        Private Sub FullName_Compute(ByRef result As String)
            ' Set result to the desired field value
            result = Me.FamilyName + ", " + Me.FirstName
        End Sub
    End Class

End Namespace

Making the entities fuzzy

To speed up the fuzzy searching, we won’t loop over the entities during the actual search.  Instead, we’ll add an extra property to our Patient entity, which will never be displayed except for this demo, where we store some “fuzzy” version of our entity.  When the end-user hits search, we’ll make the search term fuzzy as well, and look for exact matches between the fuzzy version of the search term, and the fuzzy version of our entity.

Add an extra property to the Patient entity called “FuzzyName”.  Make sure the maximum length is high enough to contain a fuzzy version (512 characters will do since our FirstName and FamilyName properties are 255 characters each).

This would make a valid candidate to be a computed field, but since computed fields aren’t stored (they are computed on the tier wherever they are called), we’ll “manually” keep this field in sync with the other properties on save (both insert and update), by writing some code (from the Write Code dropdown).

The code we’ll need to add is this:

Imports ExtensionsMadeEasy.Utilities.Extensions.StringExtensions

Namespace LightSwitchApplication
    Public Class ApplicationDataService

        Private Sub Patients_Updating(entity As Patient)
            entity.FuzzyName = entity.FullName.MakeFuzzy()
        End Sub

        Private Sub Patients_Inserting(entity As Patient)
            entity.FuzzyName = entity.FullName.MakeFuzzy()
        End Sub
    End Class

End Namespace

The imports statement at the top (using directive in c#) makes sure you can call an extension method called .MakeFuzzy() on any string.

I added a new screen (Lists and Details Screen template) to show the Patient entities, and in the list I’m showing both the FullName computed property and the FuzzyName property.

Again, this is done for demo purposes only, you’d normally never display this field to the end-user.

What we have done so far, will result in a behavior as in the screenshot below: for each entity, a value is stored that contains the FullName, but without vowels, diacritics, lower case letters, non-alphabetic characters, and with some special attention to how consonants are pronounced (for example: both “Haeghen” and “Haägen” will be stored as “HGN”).

In case you are wondering, the “MakeFuzzy” .Net implementation (source code) is based on this SQL implementation by Diederik Krols.  It’s supposedly Dutch specific, but I found it to work for English as well.  If you disagree, feel free to export a better algorithm (just export a class from your common project that implements  IMetaphonicStringValueConverter), or better yet: send it to me and I’ll gladly include your locale in EME.

However, this doesn’t solve anything yet.  If I misspell my name as “hagen”, the search result list is still empty…

Making the search term fuzzy

The last step, is to also grab the search term that is used in the list (or grid) on the screen, and replace it with it’s fuzzy version before it hits the server, so it can be compared to our fuzzy entities…

The bad news is that to do this, you must subscribe to the NotifyPropertyChanged event on the screens IVisualCollection, find the SearchTerms property on the IScreenCollectionPropertyLoader, and swap out the SearchTerms for their fuzzy counterparts, and be careful about threading in the process.  Thanks to Justin Anderson, for helping me get access to the “Search Pipeline”.

The good news, is that you can implement this from any screen, in the Screen_Created method (from the “Write Code” dropdown), as a one-liner:

Namespace LightSwitchApplication

    Public Class PatientsListDetail

        Private Sub PatientsListDetail_Created()
            ' Write your code here.
            ExtensionsMadeEasy.Presentation.Screens.ScreenCollectionFuzzySearch.MakeFuzzy(
                Me.Details.Properties.Patients)
        End Sub
    End Class

End Namespace

 

The result is that whenever the end-user (our dear doctor) hears my name, he/she can enter “Haagen”, “Haägen”, “Haaaaaaeeeeeeeeeghen”, …, our implementation will replace it with “HGN”, and match a whole set of records that sound like “Hagen” (and thus also have “HGN” in their FuzzyName property).

Succes! The name-spelling-era is finally over!

Extensions Made Easy: v1.12: Deep linking entities

I’ve been somewhat quiet on my blog lately (but have good excuses, as always), but tonight I’ll try to make it up with a little blogging spree…  Part one: what’s new in EME 1.12

Hooray, EME 1.12 is finally released…  It’s been a while since I worked on EME because I’ve been so busy.  Actually, EME 1.12 was released 2 weeks ago, but didn’t have the time at that point to show the goodies included!  A miniature “what’s included”…

Goody nr1: LS 11 (beta) support.

EME has been tested with VS LS 11 and works: commands, shell & theme exporting, the hole bunch.  I updated the manifest so you can actually install EME to target VS LS 11 beta!  Hooray!

Goody nr2: deep linking on entities.

For those of you that missed it, EME already allows deep linking on screens since a much earlier version.  I posted this in a sample (http://code.msdn.microsoft.com/silverlight/NavigationDemo-having-some-f2629c9c), but never gave it much attention.  

Deep linking is a technique in Silverlight where a user can interact with your application through the URL.  Basically, by passing parameters (the screen name) in the URL, the LightSwitch application opens up and navigates to the correct screen when fully loaded, for example:

LightSwitch doesn’t support deep linking out-of-the box, but if you install & activate Extensions Made Easy, it does!  That’s right, the only setup you need to do is to download Extensions Made Easy, and activate it.

Possible navigation commands:

* screens:  http://localhost:30325/default.htm?NavigateTo=StudentsListDetail

* entities: http://localhost:30325/default.htm?NavigateToEntity=Students&Id=1

* entities in the non-default datasource (or: you renamed the “ApplicationData”: http://localhost:30325/default.htm?NavigateToEntity=Students&Id=1&DataSourceName=ApplicationData

The funny thing about this “deep linking to entities” gimmick,  is that I was porting it to EME from a client specific project, at the very same time Chad77 was asking for this feature in the LightSwitch MSDN forums.  Funny, because that almost never happens.  Heck, that never happens!  Anyways, Chad77 was happy with the result, and I got a free beta tester! Double tap!

Goody nr3: Fuzzy searching

The third gimmick in EME is another functionality that I needed in a client specific LightSwitch project, and happily ported to EME for your convenience: fuzzy searching.  This one though, deserves a separate blog post, just because of it’s coolness… 🙂

 

 

How to make your required fields NOT have a bold label using Extensions Made Easy… (By Kirk Brownfield)

I’ll be honest, I haven’t spent much time on Extensions Made Easy lately.  I have good excuses though: I’m writing a “getting started with LightSwitch eBook” (link on the way), I founded a “LightSwitch exclusive startup“, I’m writing about LightSwitch for MSDN magazine, I’m working on my next extension called “LightSwitch Power Productivity Studio“, but mainly because I consider EME in its current form to be complete, in the way that it can do all that I intended it to do, all that I felt was missing/not easy enough in the LightSwitch RTM, and maybe even a bit more, like deep linking in a LightSwitch application

Ironically, just when I stopped writing about EME, other people started discovering the power behind the lightweight extension, and have been happily sharing…

Kirk recently mailed me with another question: “how can one make the required fields NOT have a bold label”?  For those of you that haven’t noticed, when you use the LightSwitch default shell & theme, required properties will have a bold label like in the screenshot below:

Adding Data

By the way, my apologies on the crappy graphics in my MSDN screenshots.  I turned ClearType off on my machine, as requested in the MSDN Magazine writer guidelines.  If you take a screenshot with ClearType on, it looks crappy on-screen but much better when printed.  Bad move for the MSDN Magazine web edition, obviously…

Before I could even answer his mail, a second mail came in from Kirk with the response to his own question.  Kirk later happily granted me the privilege of posting me the answer…

Firstly, set up your LightSwitch project so you can create a theme inside your LightSwitch application.  (Everyone hates the “Extension” debugging mess…)  A sample of how to do this can be found here.

Next up, since you want to do some control styling, not just mess with the colors and the fonts a bit, you need to export a new control style to the LightSwitch framework.  I wrote about this earlier, and Keith posted the VB.Net version!

The question of course is what control you need to style, and for this you need to understand a bit about LightSwitch’s Meta-data driven MVVM implementation (MV3).  Unfortunately, the joke is on you here, because there’s little to no documentation about the subject (hold your breath for exactly 7 days and there will be… 🙂) The very short preview: the LightSwitch default theme & shell provide Views that binds to ViewModelMetaData, which in turn binds to your ViewModels and Models.  The XAML (View) part that shows the label, is called an AttachedLabelPresenter.

Kirk actually found the control to style, by looking at the source code of the LightSwitch Metro Theme, reposted here for your convenience…

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:framework="clr-namespace:Microsoft.LightSwitch.Presentation.Framework;assembly=Microsoft.LightSwitch.Client"
xmlns:internalstyles="clr-namespace:Microsoft.LightSwitch.Presentation.Framework.Styles.Internal;assembly=Microsoft.LightSwitch.Client"
xmlns:internalconverters="clr-namespace:Microsoft.LightSwitch.Presentation.Framework.Converters.Internal;assembly=Microsoft.LightSwitch.Client"
xmlns:converters="clr-namespace:MetroThemeExtension.Presentation.Converters"
xmlns:windows="clr-namespace:System.Windows;assembly=System.Windows">

<internalstyles:RequiredFontStyleFontWeightConverter x:Key="RequiredFontStyleFontWeightConverter"/>
<converters:TextToUpperConverter x:Key="ToUpperCaseConverter"/>

<!-- The attached label presenter is the control that places labels next to controls. It is restyled here to put the label-->
text in upper case. The style is applied using implicit styles, so do not give the style a key -->
<Style TargetType="framework:AttachedLabelPresenter">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="framework:AttachedLabelPresenter">
<TextBlock x:Name="TextBlock"
Text="{Binding DisplayNameWithPunctuation, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ToUpperCaseConverter}}"
VerticalAlignment="Top"
HorizontalAlignment="Left"
TextWrapping="Wrap"
FontWeight="{Binding Converter={StaticResource RequiredFontStyleFontWeightConverter}}">
<windows:VisualStateManager.VisualStateGroups>
<windows:VisualStateGroup x:Name="AttachedLabelPositionStates">
<windows:VisualState x:Name="None"/>
<windows:VisualState x:Name="LeftAligned">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="Margin" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<windows:Thickness>0,3,5,0</windows:Thickness>
<!--DiscreteObjectKeyFrame.Value>
<!--DiscreteObjectKeyFrame>
<!--ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="HorizontalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Left"/>
<!--ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="VerticalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Top"/>
<!--ObjectAnimationUsingKeyFrames>
</Storyboard>
VisualState>
<windows:VisualState x:Name="RightAligned" >
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="Margin" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<windows:Thickness>0,3,5,0</windows:Thickness>
<!--DiscreteObjectKeyFrame.Value>
<!--DiscreteObjectKeyFrame>
<!--ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="HorizontalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Right"/>
<!--ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="VerticalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Top"/>
<!--ObjectAnimationUsingKeyFrames>
</Storyboard>
VisualState>
<windows:VisualState x:Name="Top" >
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="Margin" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<windows:Thickness>0,0,0,5</windows:Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="HorizontalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Left"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="VerticalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Bottom"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</windows:VisualState>
<windows:VisualState x:Name="Bottom">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="Margin" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<windows:Thickness>0,5,0,0</windows:Thickness>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="HorizontalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Left"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TextBlock" Storyboard.TargetProperty="VerticalAlignment" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0" Value="Top"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</windows:VisualState>
</windows:VisualStateGroup>
</windows:VisualStateManager.VisualStateGroups>

</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

The interesting bits are all near the top.  First thing to notice, is the comment:

<!-- The attached label presenter is the control that places labels next to controls. It is restyled here to put the label
text in upper case. The style is applied using implicit styles, so do not give the style a key -->

Ok, so that confirms what we thought: the AttachedLabelPresenter is the control that places labels next to control.  Good naming (Nomen est Omen)!

Also, the Metro theme puts all Labels in upper case, and for this exercise, we only wanted to get rid of the bold.  Let’s revert that by getting rid of the ToUpperCaseConverter a couple of lines below that comment line:

  Text="{Binding DisplayNameWithPunctuation, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ToUpperCaseConverter}}"

Nice, following all the links posted in this blog post, and removing that converter, we have a LightSwitch application where the way labels are represented, looks exactly like the standard theme, but is completely under our control.  One thing we can now accomplish, is to get rid of the functionality where required fields have a bold label.  This is accomplished by getting rid of the following line completely (not just the converter!):

 FontWeight="{Binding Converter={StaticResource RequiredFontStyleFontWeightConverter}}">

Awesomesauce, another mission accomplished!

As you might have suspected, I wrote this blog post myself, but titled it “By Kirk Brownfield” since he basically came up with the solution before I could even read his first mail. 🙂  He promised me to send information about some other LightSwitch hacking adventures he’s been undertaking, I’m personally looking forward to reading about it, and sharing it with you!

Keep rocking LS!

Creating a very dynamic LightSwitch shell extension in 15 minutes or less…

I just finished cooking, and eating a hearty prawns wok…  The recipe, which I’m proud to say I have discovered myself through trial-and-error (mostly error), is a one-liner:  heat up a stir-fry pan, throw in a packet of marinated prawns (remove the wrapping first), add some deep-frozen vegetables and half a box of rice vermicelli, and pour over a quarter of a can of bisque du homard (“lobster soup”).  Hey, I enjoy cooking and never buy TV meals, but also refuse to believe that a good meal should take hours to prepare.  Sometimes, by just throwing the content of a couple of boxes together, you can get the simplest but most delicious dinners…

The same is true for software development… (You didn’t really think I was going to do a blog post on cooking, did you?) Less then a week ago, I created a small LightSwitch application for someone.  He was a dream customer, from a LightSwitch point-of-view.  The application only included a dozen screens on even less entities, and if it wasn’t for some specific reports, could have been built without writing a single line of code… Needless to say I considered the project to be “easy money“, and the customer considered me “way too cheap compared to others“, a win-win situation.  The day after our first meeting, where we agreed on a price and what functionality the application should include,  I headed back to his office to go over the implementation together.   Again, all of his requests were surprisingly easy to implement.  Make a field read-only, or hide the label, using the runtime editor.  Check.  Make it a bit more colorful, using the metro theme.  Check.  Move the save & refresh buttons to the left, under the navigation tree… Check.

No wait… What?  It’s amazing how a “minor change” in the eye of the customer, can have a huge influence on the technical implementation.  To move the commands view (the ribbon that holds the save & refresh buttons), I would have to write a custom shell extension.  Out of all the extensions one can write for LightSwitch, the shell extension surely isn’t the easiest one, the result you get with the walkthrough doesn’t look very professional, and since we already agreed on a price I had no intend to spend a lot of time on this hidden requirement.

I asked the customer if I could take a small break, and much to my own surprise, came back fifteen minutes later with a LightSwitch shell extension where not only the commands view was located under the navigation view, but the end-user could drag and dock both views to whatever location he/she could want…  Sometimes, by just throwing the content of a couple of boxes together, you can get the simplest but most effective LOB applications…

Minute 1->4: “marinated prawns”: creating a shell extension

This is the obvious box, if we need a custom shell extension, we’re going to use the extensibility toolkit that came with our Visual Studio LightSwitch installation.

  • Create a new LightSwitch Extension Project, name it DockableShell.
  • Right click on the DockableShell.lspkg project, select Add>New Item…>Shell and name it DockableShell.  This will add all required classes and metadata for our extension.
  • Press F5 to debug the extension and see what we have so far, a new instance of visual studio will open in experimental mode… Really? Waiting for the visual studio instance to load, then open a new LightSwitch project just to test our extension, will kill productivity, so let’s fix that first.
  • Close the LightSwitch Extension Project

Minute 5 ->8: “deep-frozen vegetables”: using Extensions Made Easy to increase our shelling productivity

In case you’re new to my blog, and I have a feeling this post might attract a lot of first-timers,  let me show you how to use Extensions Made Easy, a light-weight extension that I have been working on, to boost your LightSwitch hacking experience…

  • Create a new LightSwitch project, name it DockableShellTestArea, and create a couple of dummy entities and screens.  Or open an existing LightSwitch project, obviously.
  • Download and activate Extensions Made Easy.
  • While you’re messing with your LightSwitch project’s properties, select the “EasyShell” as the selected shell.
  • Right click on the solution in the solution explorer, and select Add>Existing Item…  Add the client project from the extension that we made in the previous step.
  • Select your LightSwitch project, and change the view from “Logical View” to “File View”. (Highlighted with the red “circle” in the image below).
  • Add a project reference from your LightSwitch client project (DockableShellTestArea.Client) to your Extension’s client project (DockableShell.Client).
  • Change the visibility of the DockableShell class (found in the DockableShell.Client project under Presentation.Shells.Components), from internal to public.
  • And, lastly, export the shell to ExtensionsMadeEasy, by adding a new class to the DockableShellTestArea.Client project with the code below… (This is the only code we’ll write by the way… )
namespace LightSwitchApplication
{
    public class DockableShellExporter :
        ExtensionsMadeEasy.ClientAPI.Shell.EasyShellExporter
        <DockableShell.Presentation.Shells.Components.DockableShell>
    { }
}

All done, your solution should look a similar to this…

If you made it through these 4 minutes, you can now press F5 to see your LightSwitch application with your custom shell applied.

It doesn’t look so fancy yet, and that’s an overstatement, because we haven’t actually implemented our shell extension yet.  Move along fast, you’re over halfway there…

Minute 9 ->12: “rice vermicelli”: pandora’s box

Right, time to open pandora’s box.

Before you read on, realize that the kind of LightSwitch hacking we’re about to do, might damage your application, software, or cause your hardware to spontaniously self-ignite, and I won’t take responsability for it.  Seriously though, once you leave the path of published APIs, you should realize that no one can/will provide support for the errors you might encounter, and that your extensions can / will break in later versions of LightSwitch…

In the solution explorer, select your LightSwitch application’s client project and select “Open folder in windows explorer”.  Go up one level, and then down the ClientGenerated>Bin>Debug path.  You’ll find an assembly called Microsoft.LightSwitch.Client.Internal.DLL.   This assembly contains the files that are used by, for example, the LightSwitch default shell.  Instead of rolling our own shell, we’re going to tear apart and reuse the built-in LightSwitch default shell.  This scenario is in no way officially supported, and quite frankly I don’t believe you’re even allowed to do that, so do it at your own risk and don’t tell anyone about it, in a blog post or whatever… Crap…

  • Add a reference to Microsoft.LightSwitch.Client.Internal from your DockableShell.Client project.
  • Also add a reference to System.Windows.Controls
  • And a reference to System.Windows.Controls.Navigation
  • Open the file DockableShell.xaml and replace the contents with the following
<UserControl x:Class="DockableShell.Presentation.Shells.DockableShell"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:nav="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
     xmlns:stringsLocal="clr-namespace:Microsoft.LightSwitch.Runtime.Shell.Implementation.Resources;assembly=Microsoft.LightSwitch.Client.Internal"
     xmlns:DefaultShell="clr-namespace:Microsoft.LightSwitch.Runtime.Shell.Implementation.Standard;assembly=Microsoft.LightSwitch.Client.Internal"
     xmlns:ShellHelpers="clr-namespace:Microsoft.LightSwitch.Runtime.Shell.Helpers;assembly=Microsoft.LightSwitch.Client"
     xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
     xmlns:internalControls="clr-namespace:Microsoft.LightSwitch.SilverlightUtilities.Controls.Internal;assembly=Microsoft.LightSwitch.Client"
     xmlns:internalToolkit="clr-namespace:Microsoft.LightSwitch.Presentation.Framework.Toolkit.Internal;assembly=Microsoft.LightSwitch.Client"
     xmlns:framework="clr-namespace:Microsoft.LightSwitch.Presentation.Framework;assembly=Microsoft.LightSwitch.Client">

     <Grid x:Name="shellGrid" Background="{StaticResource NavShellBackgroundBrush}">
          <Grid.RowDefinitions>
               <RowDefinition Height="Auto"/>
               <RowDefinition Height="*"/>
               <RowDefinition Height="Auto"/>
          </Grid.RowDefinitions>

          <DefaultShell:CommandsView x:Name="_commandsView" ShellHelpers:ComponentViewModelService.ViewModelName="Default.CommandsViewModel"
               VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" HorizontalAlignment="Stretch" BorderThickness="0"
               HorizontalContentAlignment="Stretch" Margin="0"/>
          <Grid Grid.Row="1" >
               <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
               </Grid.ColumnDefinitions>
               <DefaultShell:NavigationView x:Name="NavigationView"
                    ShellHelpers:ComponentViewModelService.ViewModelName="Default.NavigationViewModel"
                    HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
                    Grid.Column="0"
                    VerticalAlignment="Stretch" VerticalContentAlignment="Top"/>

               <controls:GridSplitter Grid.Column="1" Width="6" Style="{StaticResource GridSplitterStyle}" IsTabStop="False"
                    Background="Transparent"
                    IsEnabled="{Binding ElementName=NavigationView,Path=IsExpanded, Mode=TwoWay}"
                    VerticalAlignment="Stretch" HorizontalAlignment="Left"/>

               <ContentControl Grid.Column="2" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Margin="6,3,6,6"
               VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" IsTabStop="False"
               ShellHelpers:ComponentViewService.ComponentContent="Default.ActiveScreensView"
               ShellHelpers:ComponentViewModelService.ViewModelName="Default.ActiveScreensViewModel"/>
          </Grid>
     </Grid>
</UserControl>

As you can see, we got three grids here, that hold together a bunch of controls in the DefaultShell namespace.  They are the actual views that are used in the default LightSwitch shell extension.  We’re also using ShellHelpers to do MVVM, the LightSwitch way.

You might get some red squigly lines in your xaml (errors), caused by the fact that the LightSwitch controls are internal and are not supposed to be used in your custom shell.  However, compiling and running, works just fine.  Press F5 to enjoy the result…

Basically, and given the implementation, it should come to no surprise, it looks exactly like we are using the Default shell.  We just spent 12 of our 15 minutes and from a functional point of view, end up with exactly the same result.  Not good.  However, from a technical point of view, we went from a simple LightSwitch application that uses the Default shell, to a simple LightSwitch application that uses a custom shell extension that looks, works and behaves exactly like the default LightSwitch shell.  Major difference!

Now, we have three minutes left on the clock before we should go back in the office and show the customer our results.  We could spend one minute to update the XAML posted above, swap the grids around until we reach the effect the customer wanted (save & close button under the navigation menu), and arrive two minutes early…

Or… Underpromise, overdeliver, and spend our 180 seconds opening box number four…

Minute 13 ->15: “bisque du homard”: Telerik RADControls for SilverLight

If you don’t have the Telerik RADControls for Silverlight installed, you can hop over to their website and download a trial, which should work just fine for this example.  I’m also giving away a licence at the end of this blog post!

  • Drag a RADDocking control on your DockableShell.xaml’s XAML.  I always forget the correct references to add, and this little trick does that for us.
  • Replace the contents of the DockableShell.xaml with the following…
<UserControl x:Class="DockableShell.Presentation.Shells.DockableShell"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:nav="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
     xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
     xmlns:internalControls="clr-namespace:Microsoft.LightSwitch.SilverlightUtilities.Controls.Internal;assembly=Microsoft.LightSwitch.Client"
     xmlns:internalToolkit="clr-namespace:Microsoft.LightSwitch.Presentation.Framework.Toolkit.Internal;assembly=Microsoft.LightSwitch.Client"
     xmlns:framework="clr-namespace:Microsoft.LightSwitch.Presentation.Framework;assembly=Microsoft.LightSwitch.Client"
     xmlns:stringsLocal="clr-namespace:Microsoft.LightSwitch.Runtime.Shell.Implementation.Resources;assembly=Microsoft.LightSwitch.Client.Internal"
     xmlns:DefaultShell="clr-namespace:Microsoft.LightSwitch.Runtime.Shell.Implementation.Standard;assembly=Microsoft.LightSwitch.Client.Internal"
     xmlns:ShellHelpers="clr-namespace:Microsoft.LightSwitch.Runtime.Shell.Helpers;assembly=Microsoft.LightSwitch.Client"
     xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

     <Grid x:Name="shellGrid" Background="{StaticResource NavShellBackgroundBrush}">
          <telerik:RadDocking x:Name="Docking" BorderThickness="0" Padding="0" telerik:StyleManager.Theme="Metro" >
               <telerik:RadDocking.DocumentHost>
                    <ContentControl HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Margin="6,3,6,6"
                    VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" IsTabStop="False"
                    ShellHelpers:ComponentViewService.ComponentContent="Default.ActiveScreensView"
                    ShellHelpers:ComponentViewModelService.ViewModelName="Default.ActiveScreensViewModel"/>
               </telerik:RadDocking.DocumentHost>

               <telerik:RadSplitContainer InitialPosition="DockedTop">
                    <telerik:RadPaneGroup>
                    <telerik:RadPane Header="Actions">
                              <DefaultShell:CommandsView x:Name="_commandsView"
                                   ShellHelpers:ComponentViewModelService.ViewModelName="Default.CommandsViewModel"
                                   VerticalAlignment="Stretch" VerticalContentAlignment="Stretch" HorizontalAlignment="Stretch" BorderThickness="0"
                                   HorizontalContentAlignment="Stretch" Margin="0"/>
                         </telerik:RadPane>
                    </telerik:RadPaneGroup>
               </telerik:RadSplitContainer>

               <telerik:RadSplitContainer InitialPosition="DockedLeft">
                    <telerik:RadPaneGroup>
                         <telerik:RadPane Header="Navigation" >
                              <DefaultShell:NavigationView x:Name="NavigationView"
                                   ShellHelpers:ComponentViewModelService.ViewModelName="Default.NavigationViewModel"
                                   HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
                                   VerticalAlignment="Stretch" VerticalContentAlignment="Top"/>
                         </telerik:RadPane>
                    </telerik:RadPaneGroup>
               </telerik:RadSplitContainer>
          </telerik:RadDocking>
     </Grid>
</UserControl>

(You might want to hit F5, and walk back inside the customer’s office, while you’re waiting for the build process to complete, or read the rest of the blog post…)  

Compared to the result we had 2 minutes and 45 seconds ago, we’re using the same views that we stole from the LightSwitch default shell implementation, but positioned them in Telerik RadPanes instead of in a simple grid.

Functionally, the end-user can now drag the “Actions” (business name for what we call the Commands View), and drag them anywhere he wants…

Or…

Mission accomplished, project delivered on time, customer is happy, and we made a nice amount of money… LightSwitch business as usual. 🙂

Win a Telerik RADControls for SilverLight license worth $799!

The Telerik licence has been won by @MatthieuFichefet, by being selected by Mojo, our judge (Video on the way, it’s hilarious), after tweeting:

Essential reading : Creating a very dynamic #LightSwitch shell extension in 15 minutes or less… http://wp.me/p1J0PO-9T@janvanderhaegen

In case you joined the contest but didn’t win, keep an eye out on the blog for new opportunities… Whenever I have anything to give away, I will!

Enjoy the hacking!

MyBizz Portal: The “smallest” LightSwitch application you have ever seen (Thank you!).

Time to get this blog on the road!  My life has known a fun but chaotic couple of weeks, with lots of crazy events and opportunities that you’ll hear about later… First things first, a little thank you is in order…

Only a couple of weeks ago, 10 days before the LightSwitch Star Contest on CodeProject was about to end, I posted a small article that stated:

“This weekend, I’m going to try to allocate most of my time into the submission of “MyBizz Portal”, […] My aim is to rank as high as possible in the category “Most Groundbreaking LightSwitch Application”, with an application that has one screen, a blank shell, the default LightSwitch theme and a single Silverlight Custom UserControl, so probably the smallest LightSwitch application you have ever seen.

I never assumed it to be even remotely possible that I would win any of the prizes, but then a first mail hit my inbox, stating that I won the first prize in the January edition of the contest, rewarding me an awesome bundle of LightSwitch specific software…  Most rewarding day of my life since I lost my virginity…

Until a second mail came… Apparently, not only did the judges like my entry, they liked it enough to award the “Grand Winner in the category Most Groundbreaking LightSwitch Application” label to MyBizz Portal!  I received the awesome Acer laptop this morning, and just finished installing LightSwitch on it…

I’m not ashamed to admit that the personal publicity and recognition, are very rewarding, and I had a smile on my face for the rest of the week after those two mails.  Also, the software licenses and the laptop will provide a nice financial boost to my startup (still on track to open virtual doors on April 2nd).  But perhaps the biggest reward of them all, came in the form of a third mail, from Jay Schmelzer (Principal Diractor Program Manager – VS LightSwitch), asking if I could do an interview with Beth Massi, our LightSwitch goddess

Since I knew she visiting The Netherlands the very next week, it made perfectly good sense to meet up for the interview and talk face-to-face.  Not only was it an honor to meet such a fantastic, charismatic, pragmatic and a little bit lunatic (aren’t we all?) person, she gave me some great real-life tips that will last a life time (such as “The Business doesn’t care”, or “How do you feel about that?” – but these tips deserve a separate blog post)!   Apparently, I left a good impression myself, as she blogged about our encounter in her latest trip report

Beth Massi's blog - my brother always says: "Screenshot or it didn't happen"...

Beth Massi's blog - my brother always says: "Screenshot or it didn't happen"...

 

So anyways, and I mean it from the bottom of my heart: thank you!

Thank you to Beth for meeting up, and for the amazing adventure, hope we can meet again!

Thank you to the LightSwitch team for the amazing product they have built!

Thank you to CodeProject for their contest, and the sponsors (First Floor Software, RSSBus, ComponentOne, and whoever sponsored the laptop) for the prizes!

And most of all… Thank you, to the LightSwitch community, and my blog readers, all 37 of you,  for being the virtual family that you are!  Without readers, there’s no satisfaction in writing a blog… Without this blog, I wouldn’t have met Beth, or have the crazy opportunities that I have now…  To thank all of you in particular, my next blog post will end with a $799 giveaway, so come back soon!

Centric RAD race: did the better technology win???

Maybe… Hard to say…  If LightSwitch won the competition, it would have been a well-ment: yes!  But we didn’t take the trophy home, the first two spots in the ranking were hijacked by teams using SharePoint+Nintex… 😦

Round 1: CRUD

Due to heavy snow storms, and the longest traffic jam Belgium has ever seen, we started the competition almost 45 minutes later than the other teams.  The assignment for round 1 was pretty straight-forward: create a system where one can manage software components (users, releases, usages, platforms, …).  There’s no framework like LightSwitch when it comes to CRUD operations, and under heavy time pressure we still managed to take second place in the overall rankings (points were awarded based on: teamwork, code maintainability and general functionality)!

Round 2: multi-tenancy

The goal for round 2 was to take the application built in round 1, and think about how different companies could use the application together.  Security was very important here, one company should be allowed to view components that have been marked as “public” from another company, and make a bid on it, which could be accepted, rejected, or responded to with a higher asking-price by the issuing company.

Because we relied on the Windows Authentication in round 1, we ended up having to create some extra entities (Company, User, …) and lost some time there.  After the small modifications, we created queries on all our entities so that the logged user could only see the private data from its own company.  A crucial thinking mistake really, we should just have created a second dataset (maybe even second LightSwitch app, and use a Portal Application) for the “market place” functionality.  That way, each company would have its own data, we could have stuck to the Windows Authentication, and simply publish to the public (common) dataset when a component is marked as “public”…

Round 3: social media integration

The last round was actually quite simple: add the ability to publish alerts about new components to any social media platform (Facebook, Twitter or Yammer), and the ability to follow components via RSS.

Although straight-forward, we lacked plug-and-play elements to implement this faster than the teams of professional SharePoint consultants…

In summary

It was a fun (and a bit stressful) night, and managed to defend LightSwitch’ honor well.   I must say that we ended up giving our chances for victory away because of the mess we made in round 2, and the lack of tools/experience in round 3.

I don’t feel like LightSwitch, as a technology, was the weaker link here: there were no brick walls hit, no “omg we simply can’t do this” moments.  I’m stronger than ever in my belief that, given some time to mature, LightSwitch has an extremely high market value in the future

And hey, there’s always next year!

— A special thanks to Centric for organizing this fun event (count me in for every future event that involves LightSwitch, free beer, free pizza, or a combination of!), and the LightSwitch community members that supported us through all kind of social media platforms!

LightSwitch twitter bot.

Hey guys ‘n guls,

I was reading some sites about LightSwitch yesterday and realized how hard it was to keep track of all the different blogs, articles, code samples, …

Because I’m on Twitter a lot (yes, a LOT), I created a Twitter-bot account (@LightSwitchNews) that monitors interesting LightSwitch-related sources, and tweets if a new blog post is written, a new extension or code sample is added to the gallery, …  The bot is created with “if this then that“, a website with the amazingly simple but effective concept that events on one platform (RSS, WordPress, GMail, GCalendar, whatever) can be configured to trigger an action on any other… (Really interesting, check it out!)

I created this user for my own purpose really (but feel free to follow if you find it interesting, ofcourse), whenever I have some spare time I can just see what the bot has been tweeting and stay updated about what’s going on in the community.  It’s my portal to the LightSwitch community… 😉

If you know any interesting LightSwitch community members, or if you are one and my bot’s not tweeting about you, let me know (@janvanderhaegen) and I’ll add you!

LightSwitch achievements: Chapter two (Events) – Classic events: “The observer”

In this blog post series, we’re going to create a fun extension that will stimulate the users of our LightSwitch applications by rewarding them with points and achievements when they use the application…

Also, in this particular post, I wrote my first VB.NET code ever, which seems to be the .NET language of choice of about 1/3rd of my readers… All comments on the VB.NET code will be considered positive feedback, no matter what you write or how you write it!

Functional POV

Conceptually, when talking about events in .NET, where are talking about a message that one object sends to zero-to-many other objects to let them know that something happened.  There’s four important elements here:

  • the sender (aka the source): the object that sends the message
  • the message: what happened
  • the timing: when did it happen
  • the event handlers (aka the listeners): the objects that want to take an action for the event

Most events will find their use in the presentation layer of our applications, where we want to execute code when the user clicks a button, hover the mouse cursor over an image, …

Semantics POV

It’s hard to talk code without a small example..

using System;

namespace ConsoleApplicationCSharp
{

    //1. Define the event "signature", usually (but NOT required) has two arguments: sender & event arguments.
    public delegate void ChangedEventHandler(object sender, EventArgs e);

    public class ClassWithEvent
    {
        //2. Define the event.
        public event ChangedEventHandler Changed;

        public void InvokeTheEvent()
        {
            Console.WriteLine("Firing the event");
            // 3. Invoking the event (can only be done from inside the class that defined the event)
            if (Changed != null)
                Changed(this, EventArgs.Empty);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var classWithEvent = new ClassWithEvent();
            //4. Adding an event handler to the event
            classWithEvent.Changed += new ChangedEventHandler(classWithEvent_Changed);
            classWithEvent.InvokeTheEvent();

            Console.ReadKey();
        }

        static void classWithEvent_Changed(object sender, EventArgs e)
        {
            Console.WriteLine("The event has fired");
        }
    }
}

And the same example in VB.NET (I think…)

Imports System

Namespace ConsoleApplicationVB

    '1. Define the event "signature", usually (but NOT required) has two arguments: sender & event arguments.
    Public Delegate Sub ChangedEventHandler(sender As Object, e As EventArgs)

    Public Class ClassWithEvent
        '2. Define the event.
        Public Event Changed As ChangedEventHandler

        Public Sub InvokeTheEvent()
            Console.WriteLine("Firing the event")
            ' 3. Invoking the event (can only be done from inside the class that defined the event)
            RaiseEvent Changed(Me, EventArgs.Empty)
        End Sub
    End Class

    Module Program

        Sub Main()
            Dim classWithEvent As New ClassWithEvent
            ' 4. Adding an event handler
            AddHandler classWithEvent.Changed, AddressOf classWithEvent_Changed
            classWithEvent.InvokeTheEvent()
            Console.ReadKey()
        End Sub

        Private Sub classWithEvent_Changed(sender As Object, e As EventArgs)
            Console.WriteLine("The event has fired")
        End Sub
    End Module

End Namespace

Just as the functional POV, the code samples reveal that when dealing with events, there are four important elements:

  1. What happened: the first step is to define the event “signature”, which happens in the form of a delegate.  There’s a lot of “standard” event signatures provided by the .NET framework and I would advise you to use them over custom events, but as the samples show, it’s really easy to roll your own.  Event signatures will often have two arguments: sender (a reference to the source, the object that raised the event), and (a subclass of) EventArgs (additional information about what happened).
  2. The sender: we add a property to the class that exposes the event, and add the .NET keyword “event”.  Conceptually, it’s ok to think of this property as a “collection of method references” that all match the signature from step1.  From a technical POV, what we actually do is add a property which is an empty delegate, aka method pointer that has no value yet.  On a traditional property, the compiler will generate two “subroutines”: “get” and “set”.  When we add the keyword “event” to the property declaration however, the compiler will add two “subroutines” called “add” and “remove”.  In the generated “add” subroutine, the value (new delegate) will be combined with the existing value, as opposed to a normal property, where the “set” will replace the existing value, and ofcourse the opposite happens in the “remove” “subroutine”.
  3. When it happened: raising the event is quite simple: do a null-reference check then call the delegate (C#, more technical) or use the (VB.Net, more descriptive) keyword RaiseEvent.  Conceptually, each method in our “collection of method references” from step 2 will be called.  Raising the event can only be done from inside the class that defined it, although often you will see classes that expose this functionality to anyone ( depending on the access modifier: private/public/…).
  4. The event handlers: these are the classes that subscribed to the event, in other words: told the sender they want to be notified when the event occurs, in the form of a method being called.  To do this, use the VB.Net keyword AddHandler, or the C# operator +=.  Both ways are just semantics that when compiled, result in the “add” subroutine from step 2 being called.

There’s a lot more technical aspects of events that I could discuss, the most important ones would be Garbage Collection (or more specifically: the prevention of GC on the event handlers) and thread safety, but let’s not forget that this is a LightSwitch blog, so let’s find out why this information is important for the Achievements extension that we are building in this blog post series…

LightSwitch POV

I wanted to take you in this shallow dive in events in .NET, because for our achievements extension, where most of the code resides in the model layer, not in the presentation layer, we’ll choose not to use this classic observer pattern, and use the event mediator pattern instead.  To justify exactly why we’ll go with a different pattern, it’s important to understand the conceptual and technical differences between the two…

However, the achievements extension will have a little bit of graphical artwork to it, and for this code (/XAML) there’s one event in particular that could use some special attention: INotifyPropertyChanged.

What’s INotifyPropertyChanged?

INotifyPropertyChanged is an interface that exposes just one property: the PropertyChanged event.  This event is extremely important in the MVVM pattern, because the bindings that we define in XAML recognize this event and will subscribe to it.  A Binding instance will update its value (“refresh the view”) if the source raises the event.

The viewmodel that implements this interface can use the PropertyChangedEventArgs in two ways:

  • Fill in the PropertyName: by doing this, the sender signifies to the listeners that one particular property has changed, and that all bindings on this property should update.
  • Leave the PropertyName blank: by doing this, the sender signifies to the listeners that the object changed so radically, that all bindings to any property on this object should update.  It’s basically requesting a general “refresh” of the view.
INotifyPropertyChanged has a brother called INotifyCollectionChanged, also recognized by bindings, useful for “ItemsSource” properties, …

An easy base class…

If you are using EME, (if you’re not: what the hell?) then there’s an easy base class included in the framework for your LightSwitch development convenience…

The ExtensionsMadeEasy.ClientAPI.Utilities.Base.NotifyPropertyChangedBase (source code here, it has been included for a while but never got around to blogging about it)  is a base class (based on the beautiful work by Rob Eisenberg) for your (/my) ViewModels. It exposes three (undocumented, sorry) methods:

namespace LightSwitchApplication
{
    public class SomeViewModel : ExtensionsMadeEasy.ClientAPI.Utilities.Base.NotifyPropertyChangedBase
    {
        private int myProperty;

        public int MyPublicProperty
        {
            get { return myProperty; }
            set {
                myProperty = value;
                base.Refresh(); //Refresh all bindings
                base.OnPropertyChanged("MyPublicProperty"); //Classic approach
                base.OnPropertyChanged(() => MyPublicProperty); //Approach with lambda expression
            }
        }        

    }
}

Or, in VB equivalent (I think…)

Public Class SomeViewModel
    Inherits ExtensionsMadeEasy.ClientAPI.Utilities.Base.NotifyPropertyChangedBase

    Private myProperty As Integer
    Public Property MyPublicProperty() As Integer
        Get
            Return MyProperty
        End Get
        Set(ByVal value As Integer)
            myProperty = value
            MyBase.Refresh() 'Refresh all bindings
            MyBase.OnPropertyChanged("MyPublicProperty") 'Classic approach
            MyBase.OnPropertyChanged(Function() MyPublicProperty) 'Approach with lambda expression
        End Set
    End Property

End Class

The first method (Refresh) raises the PropertyChanged event without a PropertyName on the EventArgs, all bindings on “SomeViewModel” will be refreshed.

The second method raises the PropertyChanged event with a hardcoded PropertyName (“MyPublicPropertyName”) on the EventArgs, all bindings on this property will be refreshed.  The string must match the actual property name exactly…

The third method does exactly the same as the second, but uses a lambda expression.  The major advantage is that the property is not hardcoded (ie: not a string), which gives you compile-time safety: you can not misspell the property name by accident or it won’t compile (happened to me many times before), but will also be updated automagically if you decide to refactor your class a bit, and rename the property.

To each his own of course, but I definitely prefer the latter.  Anyways, let’s see what this event mediator pattern is all about, and why it’s more suited for the model layer of our extension…

Dude, where’s my VB.Net code?

It came to my attention that a large part of the LightSwitch community prefers VB.Net over C#.  I always thought that C# and VB.NET are close enough together in semantics that any VB.NET developer can read C# and vica versa.  However, I must admit that I looked at the VB.NET version of my own samples, and once there’s generics & optional parameters involved, the VB.Net version becomes significantly different compared to its C# brother. To overcome this language barrier, thank god there’s tools online like “Google Translate”, which for .NET code, is provided to us for free by Telerik.

A special thanks to Telerik, Todd Anglin in particular, for providing us with this awesome translating power!

I’ll promise to do my best to post my samples in both C# and VB.Net in the future.

 

Update (16:40): Falkao correctly indicated in the comment section that this part of the community might be quite large… Let’s find out what the exact % is among my blog readers…

MyBizz Portal: The “smallest” LightSwitch application you have ever seen (LightSwitch Star Contest entry).

Dear blog reader, thank you (again) for taking the time to come to my blog and read about my LightSwitch adventures.  In this blog post series, you find my (elaborate) submission to the CodeProject LightSwitch Star Contest.  If you enjoy this article, it would like it if you tweet about it, link from your site to it or send me your firstborn daughter as a token of gratitude, however it would also mean a lot to me if you hopped over to the CodeProject site and voted on the submission as you see fit.  You can also leave any questions, remarks or comments there, however there’s a very good chance that (especially in the distant future) I’ll get your feedback much quicker if you just post on the bottom of this blog post.

Link to CodeProject submission

Addicted to the power of LightSwitch since the first time I ever saw a demo of it, I immediately realized that LightSwitch offered me a window of opportunity to found my own software company, which will officially be born on April 2nd 2012 (after office hours at first)…  LightSwitch is a truly unique tool to write small to medium-sized business applications in virtually no time, with enough flexibility to avoid hitting a “brick wall”, which is all-to-often the case in classic RAD frameworks.  The previous sentence contains a lot of LightSwitch praising and loving, but also contains one of my biggest worries.  What about large enterprise application?  What if my applications start off small, but become giant successes?  Will my beloved technology become a burden once business starts growing?

  • Can LightSwitch handle extremely large applications?  Is there a limit on how much functionality I can fit in one LSML?  Will an enterprise LightSwitch application load fast enough?
  • Can LightSwitch handle horizontal scaling scenarios?  Can I do a distributed installation of a LightSwitch application over several servers to support a massive amount of simultaneous users?
  • How can I reuse screens and entities between my customers when they have similar needs?  Is a VSIX extension really the only way?  And will I be able to partially update one functionality without fear of breaking other parts of the application?
  • LightSwitch can help me develop at lightning speed, but is that the only aspect of a smooth running company?  How can LightSwitch help me to align customers, developers, salesmen, …   Or help me keep track of versions, servers, feature requests, installations, …
  • How are multiple developers going to work on the same LightSwitch application?  Merging the LSML file on a daily bases will be a hell…

Will LightSwitch not only lift me up my feet, but still carry me once I hit cruise speed?

One night – for some reason, my best ideas always hit me about 4-5 hours before my alarm clock tells me to get up and get ready for work – I remembered an essay which contained the statement that “our vision on reality is shaped, and thus limited, by the language that we use“.  By simply using a different lingo (the one used when talking about enterprise service oriented architecture taxonomy), my vision of LightSwitch, and thus its limitations, drastically changed.

LightSwitch taxonomy 1o1

LightSwitch application (LS APP)

To try to speak the same language again, let’s have a quick look at the anatomy of one of the most “complex” LightSwitch applications that we can develop today.  Not mentioning cosmetic extensions, a LightSwitch application itself will generate three core components: a single SilverLight application, that connects to a single WCF service, which in turn connects to a single SQL database, and perhaps you’ll use one of three other datasources: an external database, a sharepoint database, or an external WCF RIA Service.

This is what we formerly called a LightSwich application, however from now on a LightSwitch app will be considered no more than a LightSwitch project structure in Visual Studio

When creating a new LightSwitch application, you can choose to think about the result as a “module”.  A LightSwitch “module” should immediately shape the mental picture that what you are designing is a well-scoped, reusable part of a greater organism.

LightSwitch Entity Module (LS EM)

A LightSwitch Entity Module is a LS APP that has the only responsibility to design simple database entities on which other modules can perform CRUD operations.  It contains no business logic or validation.  (Note: a LS APP will generate a WCF service and a rather empty SilverLight component as well, we’ll just never use them.)

External Process Module (EX PcM)

An External Process Module is any module that can provide access to external processes to the end-user, or to our LightSwitch Process Modules.  By external I am not necessarily trying to indicate that the source code of those modules is not under our control, but merely referring to the fact that they are not written in LightSwitch.

LightSwitch Process Module (LS PcM)

A LightSwitch Process Module is a LS APP that implements a particular business process.  It (optionally) contains its own entities, logic, screens, and references whatever LS EM, EX PcM or other LS PcM it needs to materialize that business process.

Any LightSwitch Module needs careful scoping / designing before development, but this is especially easy to violate when talking about LS PcM.  Consider the functionality of managing customers for my software company.  My sales force needs software to work with those customers, so that they can schedule meetings to talk about improvements or new feature requests.  The development team will need software to work with these customers as well, so that they can implement user stories for them, contact them to discuss that implementation, …  Engineering will also need software to work with these customers, as they’ll want to keep track of the installed software versions, the servers, staging areas, …  And finally, the accountant will need these customers in his accounting suite, so that he/she can bill the customer correctly.  Although it might seem a good idea to create a “Manage Customers LightSwitch Process Module”, it’s a much better and maintainable idea to create four separate LS PcM, because you are dealing with four separate business processes, each with its own logic, references and screens, and most likely with a shared “Customer LS EM” containing common “Customer” entities.  The four separate LS PcM will not only be smaller and more maintainable, but they will load faster too.

LightSwitch Utility Module (LS UM)

A LightSwitch Utility Module is a non-application specific module that provides some reusable functionality.  Ideally, but not always, you can package these as a VSIX extension.  Good examples are generic reporting extensions, logging functionality, or the built-in LightSwitch security module (users, groups & rights).

LightSwitch Portal Module (LS PtM)

A lot of the popular application frameworks, such as PRISM or Caliburn, implement the concept of a “shell”, which blends together different modules or subsystems into a single UI at runtime.  Even after numerous attempts I still haven’t succeeded to implement this runtime weaving in LightSwitch.  However, you can still create a LS APP that provides a rather similar experience to the end-user, considering you can host a web browser in a LightSwitch (desktop) app (thanks Tim Leung for that article, you’re a genius!), and a SilverLight application (LS PcM) is hosted in a normal web page:

Above is my first succeeded attempt to create a LightSwitch Portal Module.  I was working on a proof-of-concept of two interacting LightSwitch applications (hence the “student”/”teacher” entities) when I read Tim Leung’s article.  I just had to try it right there right then.  If you click on the image and pay attention to the web page property, you’ll see that you could create and test your own LS PtM with two simple LS APPs, right from the Visual Studio debugger!

A LightSwitch Portal Module is a LS APP that provides a user a single entry point into a Business Network and the ability to “portal” to the process module of his choice.  

Business Network.

A Business Network is a collection of different modules that support a company in its business.  This network can be partially or completely private (not accessible outside the company domain for example). It can contain numerous External and LightSwitch Modules.  Business networks of allied companies could also partially overlap.

MyBizz network

In the picture above you can see a (simplified) example of such a network.  Two actually.  The network on the left is the network that will fulfill my startup’s needs, the network on the right is one that I created for demo purposes…  Let’s just say – to avoid legal matters – that “a certain real estate company” already saw this “demo that I just had lying around” and “might” become my first paying customer on April 2nd.  Both networks happen to be distributed over both a private (Windows 2008) and a public (Windows Azure) server, totaling 4 servers…

What the picture doesn’t show, is that both networks actually overlap.  It would be more obvious if I’d draw the dependencies between the different components, but that quickly turns the overview into a messy web…  The demo customer’s skinrepository pulls resources from my business (central) skin repository, my STS (see later: single-sign-on) is a trusted STS of the demo customer’s STS, and his MITS (My Issue Tracking System) reads and writes to my PITS (Public Issue Tracking System).  Our two Business Networks contain over 235 entities, hundreds of screens, about every extension I could think of writing (including the Achievements extension to encourage my sales force to write up decent specs for each customer requirement, for which they earn points, which could be materialize in a bonus plan, meanwhile making the work for the developer easier…  and a very early alpha version of the skinning extension), almost all of the free extensions I could get my hands on (thanks to all the community contributors!), and some commercial extensions.

MyBizz Portal

I’m still playing around with the portal application at the moment, but have come to a point where I am satisfied enough to “reveal it to the public”.

Getting started with MyBizz Portal…

Upon a “clean” install, an administrator user can start the application, and after logging in is greeted with the main – and only – screen of the application…

To explain what you are seeing here… I have a LS EM that contains the core data, one of the entities is called a “MyBizzModule”.  In my portal application, I connect to that data, and show it in a custom Silverlight Control.  Because there are no other screens, and no commands, I opted to use a blank shell extension.

Because there’s only one module configured (in other words: only one MyBizzModule record in the database), the only option this application offers us now is to click the lonely red box icon at the bottom…

When clicked, the module opens and displays it’s login screen to us… (You might have to enlarge the image to see that it’s actually a LightSwitch application being shown IN another LightSwitch application).

Single-Sign-On

After logging in, we can see the main screen of the module.  This LS PcM allows us to manage all the modules in a Business Network, only one is configured at the moment.


Name, Image and Portal site should need no explanation, but the fourth one is a very special one which will take more than an hour to explain in detail.

In my Business Network, I have a WCF service that fulfills the role of a Security Token Service.  The login screens used throughout the Business Network are actually all “hacked” custom implementations. Instead of authenticating with the current LightSwitch application, they request an encrypted token from the STS, and use that token as a key to log in – or, and only if automatic authentication fails, present the login screen to the user.

When I logged in to the portal application, the portal application kept the token in memory.

Now, if I check the “Include Security Token” checkbox, and portal to the module, the encrypted token will be passed in the query (I did the same thing with the “LightSwitch Deep Linking“) to the module.  The “hacked” login screen will pick up the token and try to use that token to log in automagically.  This functionality will be really important for the end-user, we do not want him to enter a username & password every time he/she portals to a different module, hence the “single-sign-on”…

Another major benefit is that one STS can “trust” another STS.  This means that I can log on to my Business Network, and navigate to a “public” module from an allied company’s Network.  That module will recognize that the token I’m trying to use was issued from my STS, and map my claims (permissions) accordingly.

Another thing that I’m trying to pass through, is information about the “default skin” that should be used.  This feature is in an EXTEMELY early alpha stage, so I wont go into it too deep.

Last property, the required claim, simply allows the administrator to indicate that only users with the given permission (claim) can view / use the module, allowing fine-tuning of users&groups at a much higher level than the classic screens & entities level that we LightSwitch developers have been doing so far…

Moving on

Enough explaining, let’s give that module some values & restart the application (changes in the configured modules still require a restart at this point… ).

You can see that the “Cosmopolitan.Blue” skin has been loaded (unfinished, based on a Silverlight theme and the LightSwitch Metro theme sources), and that I did not need to log on a second time to enter the module… (Well, kind of hard to post a screenshot of the latter.)

Let’s have some fun and add two sample modules, one portal to Twitter and one to MSDN.

Clicking the bird in the middle shows that the portal application is (obviously) not limited to LS PcM alone, any link that can be shown in a web browser will do…

Finally, just to show my custom SilverLight control – 3 icons really don’t do it justice, these screenshots below are from my Business Network as it is today, roughly 2 months before my company will actually be born…

Which results in this layout…

And for bonus points…

Basic questions

What does your application (or extension) do? What business problem does it solve?

From a technical point of view: it’s a webbrowser wrapper with an advanced URL management system.

From a LightSwitch point of view: it’s a LightSwitch application that manages my LightSwitch applications.

From a functional point of view: it’s an application that allows a user to portal anywhere he wants ( / is allowed to ) inside my LightSwitch Business Network…

From a personal point of view: it’s the last of the missing pieces of the puzzle, it will help me manage my startup (customers, sales force, expenses, keeping track of projects & LightSwitch applications, …) , and gave me the confidence that truly anything is possible with LightSwitch.

How many screens and entities does this application have?

The application has 1 screen and 1 entity.

Additional questions

Did LightSwitch save your business money? How?

Not yet, but I strongly believe it will save me loads once my company is born…   I can however say that without LightSwitch, the chances of me starting a company after my day job, and actually produce working software, would pretty much be zero.

Would this application still be built if you didn’t have LightSwitch? If yes, with what?

Most likely, it wouldn’t have been built.

How many users does this application support?

In theory, over 7,023,324,899; especially since the modules can be deployed on and load balanced over seperate servers.  The databases would be the only bottleneck.

How long did this application take to actually build using LightSwitch?

Less than a week.  Most time was spent trying to make a radial ItemsControl.  I have limited experience as a developer, and none as a designer…  Another two evenings were spent to write this article & take the screenshots.  The LightSwitch part took me 15 minutes.

(Developing both Business Networks took me 6+ months, ofcourse)

Does this application use any LightSwitch extensions? If so, which ones? Did you write any of these extensions yourself? If so, is it available to the public? Where?

The LS PcM in the Business Networks also use…
  • LightSwitch Achievements – homebrewn and part of a blog post series, so available to public soon.
  • LightSwitch STS – homebrewn and won’t be available to public anytime soon, however I’m porting the ability to inject a custom login screen to EME soon.
  • LightSwitch Skin Studio – homebrown and available to public later this year… Much, much later…
  • Many, many, many commercial and free extensions – a special thanks to the LightSwitch crew, Allesandro, Tim, Yann, Bala and Michael for contributing so much to the community! (So sorry in advance if I forgot anyone special!!)

How did LightSwitch make your developer life better? Was it faster to build compared to other options you considered?

LightSwitch gave me an incredible passion & energy to build applications that support the customer’s process, I wouldn’t find the energy to do this in any other technology that I know of at the time of writing…  It does all the tedious and boring tasks for you with a few clicks, and let’s you focus on what really makes your application stand out.

Additional additional questions

Can LightSwitch handle extremely large applications?  Is there a limit on how much functionality I can fit in one LSML?  Will an enterprise LightSwitch application load fast enough?

Yes, if you find any way to split your extremely large applications in many different modules, and bring them all together, there should be no limits for any LightSwitch developer.  The solution I choose (using a webbrowser control) fits my business’ needs perfectly, and because modules are only loaded when you actually access them, drastically reduces the load time of the application.

Can LightSwitch handle horizontal scaling scenarios?  Can I do a distributed installation of a LightSwitch application over several servers to support a massive amount of simultaneous users?

Yes, it does!

How can I reuse screens and entities between my customers when they have similar needs?  Is a VSIX extension really the only way?  And will I be able to partially update one functionality without fear of breaking other parts of the application?

A VSIX is one way, and sometimes the best way.  If you truly want to reuse screens & entities, distributing your application over multiple, reusable modules, adds a whole new dimension of benefits to the LightSwitch way of development.

LightSwitch can help me develop at lightning speed, but is that the only aspect of a smooth running company?  How can LightSwitch help me to align customers, developers, salesmen, …   Or help me keep track of versions, servers, feature requests, installations, …

LightSwitch helped me build several LS PcM to keep track of my business process in just a couple of days…

How are multiple developers going to work on the same LightSwitch application?  Merging the LSML file on a daily bases will be a hell…

Not if they work on one module each…

Where is the source?

– You wish 😉

(Although parts could be polished, then published on my blog, on demand).