You are here:   Blog
Register   |  Login

 

Dec 14

Written by: Michael Washington
12/14/2013 10:06 AM  RssIcon

image

Visual Studio LightSwitch HTML Client provides a unique opportunity for creators of JavaScript libraries to securely distribute and even sell their JavaScript code. With LightSwitch you can create HTML screen templates that will generate code that responds to data that the end-user developer has specified. Instead of selling the JavaScript library that cannot be secured, because JavaScript source is always viewable when an application is running, a JavaScript library developer is able to distribute a Visual Studio plug-in that dynamically creates code. This code is secure because it is a normal Visual Studio extension.

In this article we will explore creating a complex LightSwitch screen template.

However, note, this is not a professional grade extension, and has the following limitations:

  • It will only work with intrinsic LightSwitch data sources (tables created inside LightSwitch)

 

Getting Started

To get a good idea of how the LightSwitch HTML Screen Templates work, start with the following article: Creating A LightSwitch HTML Screen Extension. After that, read: Fundamentals of Visual Studio LightSwitch HTML Screen Template Creation.

The following is required in order to create LightSwitch extensions and run the sample code:

Visual Studio 2013 Professional (or higher)
Visual Studio 2013 SDK
LightSwitch Extensibility Toolkit for Visual Studio 2013

 

Walk-Thru

image

Open the project in Visual Studio, click on the .vsix project and Run the project.

image

A testing instance of Visual Studio will open.

Create or open a LightSwitch HTML Client project.

image

If you have not already enabled the extension for the project, go into Properties and select Extensions and check the box next to the extension to enable it.

image

Add tables to the project.

Note: The sample screen template will only work with LightSwitch tables created in the project. it will not work with external data or WCF RIA Services.

image

Create two tables that have a relationship defined.

image

Right-click on the Screens folder and select Add Screen.

image

Select the Ls Collapsible Screen Template.

Select the primary data source and the related data source.

image

The code will be generated.

image

The screen will be created.

image

The dynamic JavaScript will also be created.

image

Run the project…

image

The Add button will allow you to add records to the primary data source.

image

Popups are used to allow you to add and edit records.

 

image

Records to the associated table can be added by clicking the Add button under a record from the primary table after you have expanded it.

image

A Popup is used to allow the related table records to be edited.

image

The nested collapsible list can be fully edited.

 

Exploring The Code

image

The image above shows the general structure of the code used for the screen template.

image

When creating a screen template, you will want to first create a normal screen. We start with the code from the article: JQuery Mobile Tree Using Collapsible Sections and Dynamic Views in LightSwitch. Also note that a screen template must be contained to one screen so we use Popups to allow entities to be edited.

Data Sources

The first part of your template will need to interrogate the data sources that the end-user developer specified. The following code is used to get the name of the table to use in later code and in JavaScript:

 

        // Get the ScreenCollectionProperty that was selected by the end user
        ScreenCollectionProperty collectionProperty =
            (ScreenCollectionProperty)(host.PrimaryDataSourceProperty);
        // Cast the collectionProperty that was selected by the end user to a IDataType
        IDataType primaryDataType =
            host.FindGlobalModelItem<ISequenceType>(collectionProperty.PropertyType).ElementType as IDataType;
        // Cast the collectionProperty that was selected by the end user to a IEntityType
        IEntityType collectionDataType =
            host.FindGlobalModelItem<ISequenceType>(collectionProperty.PropertyType).ElementType as IEntityType;
        // Get the entity set of the entity type
        IEntitySetDefinition primaryEntitySet = collectionDataType.Module.GlobalItems
            .OfType<IEntityContainerDefinition>()
            .SelectMany(entityContainer => entityContainer.EntitySets)
            .Single(entitySet => entitySet.EntityType == collectionDataType);
        // Get the name of the "table"
        string PrimaryTableName = primaryEntitySet.Name;

 

Buttons

image

To create the Add button, the following code is used:

 

        ScreenMethod method = host.AddScreenMethod("AddMainData");
        CallExpression callExpression = host.CreateCallExpression(method.Id);
        ChainExpression chainExpression = host.CreateChainExpression(callExpression);
        ScreenExpressionTree expressionTree = new ScreenExpressionTree() { Body = chainExpression };
        // Create contentItem
        ContentItem addMainDataContentItem = host.AddContentItem(
            tabContentItem,
            "AddMainData",
            ContentItemKind.Command);
        host.SetDisplayName(addMainDataContentItem, "Add");
        // Set Tap property to expression tree
        host.SetControlPropertyExpressionTree(
            addMainDataContentItem,
            "Microsoft.LightSwitch.MobileWeb:RootControl",
            "Tap",
            expressionTree);

 

image

Notice that at this point, everything but the JavaScript invoked by the button is added to the screen.

The JavaScript for the button is then added using the following code:

 

        sb.Append("{0}myapp.{1}.AddMainData_execute = function (screen) {{");
        sb.Append("{0}    // Create A New Record");
        sb.Append("{0}    screen.{4} = new myapp.{4}();");
        sb.Append("{0}    screen.showPopup('{4}Popup');");
        sb.Append("{0}}};");
        // Call AddScreenCodeBehind to render JavaScript
        host.AddScreenCodeBehind(String.Format(sb.ToString(),
            Environment.NewLine,
            host.ScreenName,
            PrimaryTableName,
            RelatedTableName,
            primaryDataType.Name,
            relatedDataType.Name
            ));

 

Popups For Editing

Using Popups is a two part process. First you need to add the entity that the Popup will be bound to, to the View Model, then you create the Popup and custom JavaScript to open the Popup.

This is the code used to add entities to the View Model of the screen:

 

        // Add a singular instance of the Primary collection to the View Model
        var PrimarySingular = host.AddScreenProperty(primaryDataType, primaryDataType.Name);
        // Add a singular instance of the Related collection to the View Model
        var RelatedSingular = host.AddScreenProperty(relatedDataType, relatedDataType.Name);
        relatedDataTypeName = RelatedSingular.Name;

 

image

This adds a singular entity for the primary and related data sources.

The following code is used to create a Popup and bind the entity for the primary data source to it:

 

        var PrimaryPopup =
            host.AddContentItem(host.ScreenDialogPagesContentItem, 
            String.Format("{0}Popup", primaryDataType.Name), ContentItemKind.Group);
        // Add a control to display the data
        ContentItem PrimaryPopupContentItem =
            host.AddContentItem(PrimaryPopup, PrimarySingular.Name, PrimarySingular);
        PrimaryPopupContentItem.View = "Microsoft.LightSwitch.MobileWeb:RowsLayout";
        // Call ExpandContentItem to create elements to represent fields in the Entities
        // disableNavigationPropertyGeneration - indicates if navigation to an associated table is shown
        // disableGeneratedPropertyGeneration - indicates if automatic fields (like the audit fields) are shown
        host.ExpandContentItem(PrimaryPopupContentItem, disableNavigationPropertyGeneration: false,
            disableGeneratedPropertyGeneration: false);

 

 

image

 

The process to add or edit a record is as follows, the generated JavaScript opens the Popup:

 

myapp.EmployeesLsCollapsibleScreen.AddMainData_execute = function (screen) {
    // Create A New Record
    screen.Employee = new myapp.Employee();
    screen.showPopup('EmployeePopup');
};
myapp.EmployeesLsCollapsibleScreen.EditMainData_execute = function (screen) {
    // Show the Popup
    screen.Employee = screen.Employees.selectedItem;
    screen.showPopup('EmployeePopup');
};

 

The user makes changes in the Popup and the following generated JavaScript saves any changes:

 

function SaveMainChanges_EmployeesLsCollapsibleScreen() {
    // Save changes
    myapp.applyChanges().then(function () {
        // Close Popup
        _screen.closePopup();
        // Reload
        _screen.Employees.load();
    }, function fail(e) {
        // Show the error.
        msls.showMessageBox(e.message, { title: 'Error' }).then(function () {
            // Cancel Changes
            myapp.cancelChanges();
            // Close Popup
            _screen.closePopup();
            // Reload
            _screen.Employees.load();
        });
    });
}

 

Binding For Custom Controls

As described in the the article Fundamentals of Visual Studio LightSwitch HTML Screen Template Creation, you want to first create a normal screen:

image

Then examine the .lsml file to see what is created. In the case of our nested list we see the following binding:

image

The following code in the screen template is used to programmatically create the Container Control (Rows Layout), the Custom Control, and the binding:

 

    // Child RowsLayout
    ContentItem ChildRowsLayoutItem = host.AddContentItem(ParentRowsLayoutItem,
        "ChildRowsLayout", ContentItemKind.Group);
    ChildRowsLayoutItem.View = "Microsoft.LightSwitch.MobileWeb:RowsLayout";
    // Add the Custom Control to display the nested collection                
    IEntityPropertyDefinition IdProperty =
        collectionDataType.Properties.Where(p => p.Name.ToLower() == "id").FirstOrDefault();
    // Entity of Primary data source must have a Id property to proceed
    if (IdProperty != null)
    {
        // Expression used to access Id property of the element in the Primary data source
        ChainExpression nameExpression =
            host.CreateChainExpression(
            host.CreateMemberExpression(String.Format(@"{0}/Properties[Id]", collectionDataType.Name))
            );
        // Add the CustomControl 
        ContentItem namePropertyControl = host.AddContentItem(ChildRowsLayoutItem,
                                                                        "NestedElements",
                                                                        ContentItemKind.Value,
                                                                        nameExpression,
                                                                        IdProperty.PropertyType);
        namePropertyControl.View = "Microsoft.LightSwitch.MobileWeb:ValueCustomControl";
    }

 

Adding A Theme

image

We can use the Jewel Lambert theme from here:

http://jewellambert.com/lightswitch-html-client-theme-with-rounded-corners/

image

To add styling to our collapsible list.

 

Special Thanks

This article would not be possible without extensive assistance of LightSwitch team member Justin Anderson. However, any mistakes are my own.

Links

LightSwitchHelpWebsite:

Creating A LightSwitch HTML Screen Extension

Fundamentals of Visual Studio LightSwitch HTML Screen Template Creation

Additional:

Creating a LightSwitch Screen Template

LightSwitch Extensibility Toolkit for Visual Studio 2013

LightSwitch Screen Template Extension Sample for Visual Studio 2013

Microsoft Visual Studio 2013 SDK (Download)

LightSwitch Extensibility Toolkit for Visual Studio 2013 (Download)

How to: Create a LightSwitch Extension Project

How to: Debug or Test a LightSwitch Extension

How to: Set VSIX Package Properties

How to: Distribute a LightSwitch Extension

Download

The LightSwitch project is available at http://lightswitchhelpwebsite.com/Downloads.aspx

(you must have Visual Studio 2013 Professional (or higher), Visual Studio 2013 SDK, and LightSwitch Extensibility Toolkit for Visual Studio 2013 installed to run the code)

5 comment(s) so far...


Gravatar

Re: Creating Advanced LightSwitch HTML Screen Templates

I really think the LightSwitch HTML screen templates are a big deal. You can’t sell JavaScript code because anyone can basically “view source” in their web browsers and take it. In my opinion the component venders sell “help and support”. This however leaves out the smaller guys who can’t provide such expensive services. However, it is the smaller guys and gals who provide the important fuel that is needed for any technology to have a healthy ecosystem.

LightSwitch HTML screen templates, in my opinion, allow you to package, distribute, and even sell your application of a JavaScript library against the LightSwitch developer’s defined data. A LightSwitch developer’s data definition they have defined in the application, is always the description of the “unique thing” of the “problem domain” (the need they are trying to fulfill by creating the computer application). This workflow for creating such applications, defining the data first, remains consistent from the very first edition of LightSwitch.

What I find utterly amazing is that there is no other tool anywhere that I know of that allows a small time 3rd party developer, such as myself, to create a program that can be plugged into a powerful tool such as Visual Studio that then allows an end-user developer to create complex JavaScript applications. This is really happening, LightSwitch is “the-only-game-in-town” that can deliver this functionality!

This was my motivation for basically putting my free-time on hold for 3 weeks to devote to this project. I really think history is being made here and I wanted to be a small part of it.

By Michael Washington on   12/14/2013 12:54 PM
Gravatar

Re: Creating Advanced LightSwitch HTML Screen Templates

I would gladly pay for help and support for great functionality

By Jason on   12/26/2013 9:59 AM
Gravatar

Re: Creating Advanced LightSwitch HTML Screen Templates

@Jason - You may wish to make a post on the Official LightSwitch forums at: http://social.msdn.microsoft.com/Forums/vstudio/en-US/home?forum=lightswitch

By Michael Washington on   12/26/2013 10:00 AM
Gravatar

Re: Creating Advanced LightSwitch HTML Screen Templates

its brilliant! Thanks Michael - have you thought about showing the count of detail items in the header summary?

By pp8357 on   3/10/2014 6:05 PM
Gravatar

Re: Creating Advanced LightSwitch HTML Screen Templates

@pp8357 - Thanks. That can be done but I don't want to make the template any more complex :)

By Michael Washington on   3/11/2014 4:02 AM

Your name:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
CAPTCHA image
Enter the code shown above in the box below
Add Comment   Cancel 
Microsoft Visual Studio is a registered trademark of Microsoft Corporation / LightSwitch is a registered trademark of Microsoft Corporation