Dec
14
Written by:
Michael Washington
12/14/2013 10:06 AM
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
Open the project in Visual Studio, click on the .vsix project and Run the project.
A testing instance of Visual Studio will open.
Create or open a LightSwitch HTML Client project.
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.
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.
Create two tables that have a relationship defined.
Right-click on the Screens folder and select Add Screen.
Select the Ls Collapsible Screen Template.
Select the primary data source and the related data source.
The code will be generated.
The screen will be created.
The dynamic JavaScript will also be created.
Run the project…
The Add button will allow you to add records to the primary data source.
Popups are used to allow you to add and edit records.
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.
A Popup is used to allow the related table records to be edited.
The nested collapsible list can be fully edited.
Exploring The Code
The image above shows the general structure of the code used for the screen template.
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
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);
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;
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);
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:
Then examine the .lsml file to see what is created. In the case of our nested list we see the following binding:
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
We can use the Jewel Lambert theme from here:
http://jewellambert.com/lightswitch-html-client-theme-with-rounded-corners/
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...
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
|
I would gladly pay for help and support for great functionality
By Jason on
12/26/2013 9:59 AM
|
@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
|
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
|
@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
|