LightSwitch 2013 – Modern UI Menus!

Tired of the old list menu that comes with LightSwitch?  Follow this tutorial and stand out from the crowd!  My apologies in advance for what seems like a long post… but trust me…it WILL be worth it!

Oh, I’ve also changed up a bit and included some images, let me know if it works or step by step is better…

FinishedExample

Step 1 – Project Setup

Go to http://metroui.org.ua
Find the download button, and download the latest package of Metro UI CSS.
Extract the zip somewhere, remember the location!

Go to our repository on GitHub to download this project
Extract the zip

Open up Visual Studio 2013
Create a new project, name it: LightSwitchWithTiles
Once the project is created and Visual Studio settles down select the HTMLClient project
Create the following new folders under your Content folder

Fonts
MetroUICss

Right click on the Fonts folder, select add, add existing item
Navigate to your Metro-UI-CSS-master folder
Select all the files under the docs/fonts folder and click the add button

Back in Visual Studio
Right click on the MetroUICss folder you created, select add, add existing item
Navigate to your Metro-UI-CSS-master folder
We are only interested in Tiles, so we’ll include a subset of the full CSS
Select the following files under the Less folder and press the add button

colors.less
icons.less
icons-content.less
layout.less
mixins.less
tiles.less
transform.less
typography.less
variables.less

Add a new file under your MetroUICss folder

 LightSwitchWithTiles.less

Add the following into your LightSwitchWithTiles.less

/*
 * Metro Bootstrap v 1.0.0
 *
 * Copyright 2012-2013 Sergey Pimenov
 * Licensed under the MIT License (MIT)
 * http://opensource.org/licenses/mit-license.php
 */
// Core variables
 @import "variables.less";
// Our Tiles
 .metro {
 @import "colors.less";
 @import "mixins.less";
 @import "transform.less";
 @import "typography.less";
 @import "layout.less";
 @import "tiles.less";
 @import "icons.less";
 @import "icons-content.less";
}

Save the file, CSS will get generated

In your Content folder, add the following to the user-customization.css file

/* Allows MetroUICss to play nice with LightSwitch */
.metro-container *
 {
 -webkit-box-sizing: border-box;
 -moz-box-sizing: border-box;
 -ms-box-sizing: border-box;
 -o-box-sizing: border-box;
 box-sizing: border-box;
 }
/* End of ITG Add */

Under your scripts folder create a new folder

 itgHelpers

Add the itgMetroHelper.js from the LightSwitchWithTiles zip

Open the default.htm file
Add the LightSwitchWithTiles.css file to your css section before the user-customization.css file
Add the itgMetroHelper.js to your scripts section
Add update the document ready that LightSwitch generates with the following

var start = getUrlParameterByName("start")
 msls._run(start)

Ok cool… core project has been setup. Now let’s work with the database side.

Step 2 – Core Database

For this demo we’ll be using a couple of tables to house our menu definitions.
We won’t get too elaborate to keep this demo manageable.
For a production application you will want to expand on this structure, adding choice lists, validation, etc.

Create a table just to hold a definition for a menu as shown below

CoreDatabase1

Now let’s create the table for our tiles as shown below

CoreDatabase2

Click on the Type property
In the properties window, click on Choice List, add the following

CoreDatabase3

Click on the Size property and do the same

CoreDatabase4

Click on the add relationship and define as shown below

CoreDatabase5

Great! Last database work is to create a query for MenuTiles.
Still on the MenuTiles table, click on query, change the name to TilesForMenu
Configure the query as shown below

CoreDatabase6

We’ll have LightSwitch do most of our work getting tiles with this query.

Ok… Database done… Yay!!

Step 3 – Menu Management

Since our application menus are database driven, we’ll need a way to manage/create them.
Note that our naming convention is a bit opposite than what LightSwitch recommends for screens. We prefix all screens with our database table name first, then the screen type. This allows us to keep all the screens together for a particular area and gets so important on large projects.

Create a new screen
Screen Name: MenusBrowse
Screen Data: Menus
Clean up the Display Name in properties to show Menus
Adjust your properties per your preferences, we set the list to be 400 max width
Add a new button to the Command Bar
Select Existing Method
In the showTab dropdown select addAndEditNew
Screen Name: MenuAddEdit
Screen Data: Menu Details only
Click Ok
Adjust your screen to your liking, here is ours

MenuMgt1

Go back to the MenusBrowse screen
For this new Add Menu button, change its Icon to Add

Click on the List for the Menus
In the properties window click on the Item Tap
Choose an existing method, viewSelected
Screen Namez: MenuView
Screen Data: Menu Details and Menu MenuTiles
This screen is really busy, yet a critical one so be patient.
Here is how we have designed it for this demo project

MenuMgt2

Here is the easiest way to create the above.
Delete both the tabs LightSwitch creates, should end up with a screen shown below.

MenuMgt3

Now add a tab back in, Make the tab a Column Layout
Then add two more groups under the tab, both Row Layouts

MenuMgt4

Change the Max width of Group1 to 300
Drag the MenuTiles query and drop it under the first row layout
Adjust your list to your liking, we went with Order and Name to be shown in a column layout

MenuMgt5

Now Click on and drag the Selected Item part of the MenuTiles query and drop it under the second row
Remove the Created/Modified and Menu fields
Adjust the screen to your liking, as you see we used additional Column Layouts

MenuMgt6

Now for some buttons
Under the main Group (Tab), Command Bar, Add

Choose existing method, Under MenuTiles, addAndEditNew
Screen Name: MenuTileAddEdit
Screen Data: MenuTile Details
Remove the Menu field from the screen
Adjust the layout to your liking or follow ours

MenuMgt7

Back to the MenuView screen

Change the Display Name of your Add button to just Add Tile
Change the Icon to Add

Add another button, existing method, Under MenuTiles, editSelected
Change the Display Name to Edit Tile
Change the Icon to Edit, uncheck Is Visible

Add another button, Write my own, name it DeleteMenuTile
Change the Display Name to Delete Tile
Change the Icon to Remove, uncheck Is Visible

Add another button, existing method, Under Menu, edit
Change the Icon to Edit

Add another button, Write my own, name it DeleteMenu
Change the Name to Delete Menu
Change the Icon to Remove

Now we need to add some code for the following

MenuView
DeleteMenu
DeleteMenuTile
MenuTiles_ItemTap

I won’t go into details but review the following and add into your appropriate methods

// Optional
 // Put our Menu Name as the screen header
 myapp.MenuView.MenuTiles_postRender = function (element, contentItem) {
// Bind so that changes will be reflected
 contentItem.dataBind("screen.Menu.Name", function (newValue) {
 contentItem.screen.details.displayName = newValue + " Menu";
 });
};
// When a tile in the list is tapped, hide/show appropriate buttons
 myapp.MenuView.MenuTiles_ItemTap_execute = function (screen) {
// Tile selected, show edit/delete tile buttons
 screen.findContentItem("DeleteMenuTile").isVisible = true;
 screen.findContentItem("EditMenuTile").isVisible = true;
// Yet hide the buttons to edit/delete the menu itself
 screen.findContentItem("EditMenu").isVisible = false;
 screen.findContentItem("DeleteMenu").isVisible = false;
};
// Delete the selected tile
 myapp.MenuView.DeleteMenuTile_execute = function (screen) {
// Grab the selected, delete and apply
 screen.MenuTiles.selectedItem.deleteEntity();
 myapp.applyChanges();
// Since we won't have a tile selected anymore, hide the tile buttons
 screen.findContentItem("DeleteMenuTile").isVisible = false;
 screen.findContentItem("EditMenuTile").isVisible = false;
// Now show again the menu specific buttons
 screen.findContentItem("EditMenu").isVisible = true;
 screen.findContentItem("DeleteMenu").isVisible = true;
};
// Delete the entire menu and associated tiles
 myapp.MenuView.DeleteMenu_execute = function (screen) {
// Delete and commit, returning us to the browse screen
 screen.Menu.deleteEntity();
 myapp.commitChanges();
};

Of course you would add appropriate confirmations and validations to all the screens. Especially your delete actions. But for this demo we’ve tried to make it robust enough to show the power yet try to remain somewhat brief.

Go ahead and build your app to make sure we’re good from this point.

Step 4 – Build Menu Screens

Let’s create some screens to test our new menu infrastructure.

Create a new Browse Screen
Screen Name: Start
Screen Data: none

Add Data Item, select our query TilesForMenu

MenuScreens1

Click on the Query Parameter MenuName
In the properties window click in the Parameter Binding field
Click on Add Property

In the screen definition window, add a custom control under the group tab
Data for the new control, leave as default: Screen
Change the name of the control to ModernUIContent
Set the Label Position to be None
The rest of the properties can stay default
Click on the Edit Render Code link for this control
For intellisense, add the itgMetroHelper.js to the top of this file
Add one line of code as follows:

createModernTileMenu(element, contentItem, "Start");

Create two more screens just for testing. Neither will use data.

Screen 1 Name: Profile
Screen 1 Data: None

Screen 2 Name: AdminMenu
Screen 2 Data: None

Open up Screen 2 and follow the procedure above to make it a tile menu screen. Use “Admin” as the name passed to our createModernTileMenu.

Right click on your Start screen and set it to be your Home Screen.

Build the app and run.

Hmmm… nothing?

Good… as you see we have a little chicken before the egg scenario here. So how do we get to our menu administration without a menu. Well thanks to a post by Jewel Lambert we’re already setup to do this. That little modification we did to the default.htm file at the beginning will be our friend.

To get to our menu administration you’ll add a parameter to your url as so

 http://localhost:port/HTMLClient?start=MenusBrowse

Now normally before pushing to production you would put a bunch of permission checking on the screens before going live so that only security administrators can access. But for this demo we won’t go into that detail.

Btw, if this trick did not work, check to make sure you have all the CSS and JavaScript references in your default.htm file. Also make sure you do a build after you add those references in.

You should now be able to get to your Menus screen

Go ahead and create (add) your first menu
Name: Start
Screen: Start
Click on the new menu list item to get to the view

Add a tile
Order: 1
Type: Simple
Name: Profile
Size: Default
Color: bg-lighterBlue
OnClick: myapp.showScreen(‘Profile’)
Status: Profile
Icon: icon-user

Add a tile
Order: 2
Type: Simple
Name: Admin
Size: Double
Color: bg-teal
OnClick: myapp.showScreen(‘AdminMenu’)
Status: Admin
Icon: icon-power

Back to the Menus screen

Add a new menu
Name: Admin
Screen: AdminMenu

Click on it so we can add a tile

Add a tile
Order: 1
Type: Simple
Name: Menus
Size: Default
Color: bg-yellow
OnClick: myapp.showScreen(‘Menus’)
Status: Menus
Icon: icon-list

Now… we should be good to go to our normal main screen. If you click on the app icon this will refresh and get you there or type the address in.

http://localhost:port/HTMLClient

If your icons do not show. Go check the CSS file. I’ve seen where the LESS compiler in Visual Studio uses full drive path vs URI in its location of the icons. Do a search for ../fonts and see what path its trying to use.

You can also just use the precompiled CSS in our project.

Check out more colors at http://metroui.org.ua/global.html
Icons at http://metroui.org.ua/icons.html

Stuff
So… explain the data fields?

Menus – This is just a bucket so we can get our tiles
MenuTiles – This is the meat of the system so let’s go over the fields

Order – this is the display order for tile layout
Type – this will be the type of tile, currently for this demo only simple is implemented
Name – internal identifier for the tile
Size – half, default, double, triple, quadro
Color – background color of the tile, class based
OnClick – javascript function to execute, ie: myapp.showScreen(‘SomeScreen’)
Status – text to display on the bottom line of the tile
StatusFgColor – class based
StatusBgColor – class based
Icon – class based
IconFgColor – class based
IconBgColor – class based
Badge – number to display on the lower right of the tile
BadgeFgColor – class based
BadgeBgColor – class based

Red means required
If no Order is set, tiles will be ordered by its Name

I’d like to thank Jewel Lambert for the wealth of knowledge she brings to the LightSwitch community.
I’d also like to thank Sergey Pimenov for his great work on MetroUICSS… nicely done!

Tagged

19 thoughts on “LightSwitch 2013 – Modern UI Menus!

  1. Johnathan Lightfoot says:

    Hi,
    Looks like a terrific tutorial. I am unable to find the mixins.less file though that referred to. Has the name of the file change or is it no longer needed?

  2. Hi, I think your site might be having browser compatibility issues.
    When I look at your blog site in Safari, it looks fine but when opening in Internet Explorer,
    it has some overlapping. I just wanted to give you a
    quick heads up! Other then that, awesome blog!

  3. Do you mind if I quote a couple of your posts as long as I provide credit and sources back to
    your weblog? My blog is in the very same niche as yours and my users would definitely
    benefit from some of the information you present here.
    Please let me know if this ok with you. Thanks a lot!

  4. Mike says:

    Yes. Thank you for sharing and contributing your time and efforts on this. I just installed win8.1, ms sql 2014, vs2013 ult this week – and I’d like to do all of your tutorials, starting with this one. I had a quick question:regarding Lightswitch and this tutorial: will I be able to do everything from this single box – in other words, can the database just be ms sql 2014 or will I need to do against Azure? Thanks

  5. Simon says:

    Hi, the tutorial look very promising and your result awesome already.
    However, I trying to redo the steps here, to understand it fully and am already running into some issue. Hope you can help out:

    1. I Downloaded the Metro CSS package, but mixins.less and transform.less are missing in there, which we were supposed to add to the project.

    2.”Add the following into your LightSwitchWithTiles.less

    Save the file, CSS will get generated”
    If I save that file, no css is generated (even wondering why VS should generate a CSS just because I’m saving another file(?))

    Best regards
    Simon

  6. Brilliant thx. This is exactly what I’ve been waiting for because it helps bridge the gap between the Windows Modern UI & the Browser. Now if only we could get the same performance and hardware access as native apps ;-)

  7. Fantastic!

    One thing: is it not possible to have one screen ONLY that shows the tiles for a particular menu (instead of Start, Admin Menu etc) so that you don’t have to build several similar ‘menuTile’ screens?

    I would guess then that you could pass some type of parameter value to the ‘Start’ screen which states which menu name to pass to the query?

    Must admit I’ve been trying to think of a way to do this but haven’t come up with the answer (if there is one!)

    Example:
    myapp.Start.ModernUIContent_render = function (element, contentItem)
    {
    Instead of:
    createModernTileMenu(element, contentItem, “Start”);

    How about:
    createModernTileMenu(element, contentItem, [a particular variable value])

    };

    Passing this value to the screen and reading it I can’t seem to do, any thoughts?

    I guess if this was possible you would have done this. If not would you be kind enough to explain why?

    Thanks

    ( a relative newcomer to HTML client so if I’ve completely missed the point, please make allowances :-) )

    • dwm9100b says:

      I originally had a single screen for all my menus. But… the visualization was inconsistent with the rest of the app. In other words… the menus were TOO responsive compared to how navigation happened in the rest of the app.

      • Understood! Still, I’d like to try it out; would it be possible to pass some guidance on how you approached this please? Presumably a small code-change/addition?

  8. very cool. Thanks for sharing. Love your blog !

  9. Johann Quintero says:

    This is very nice!!! Thanks for sharing… one Question: Can I use this with VS2012?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 146 other followers

%d bloggers like this: