May
21
Written by:
Michael Washington
5/21/2011 6:19 AM
Note: There is a third method covered at this link.
It is easy to create a LightSwitch application using your own custom user interface (UI), composed entirely of Silverlight Custom Controls. The article This Is How LightSwitch Does MVVM, covers the basics of how you bind Silverlight Custom Controls to LightSwitch Properties and Collections. This article demonstrates two ways to raise LightSwitch Methods (in a normal Silverlight MVVM applications these would usually be Commands), from a Silverlight Custom Control.
We first start with the project from the article: LightSwitch Procedural Operations: “Do This, Then Do That”.
In that project, we built an application that allowed us to select a Book, two Sites, and Transfer books between them. First we press the “Get Existing Inventory” button to see the available inventory at the two sites. After entering the amount to transfer, pressing the “Transfer Inventory” button makes the transfer.
Using A Silverlight Custom Control
The first step is to add a Silverlight Class Library to the LightSwitch solution.
We can open the Silverlight project up in Expression Blend and design the UI. In this example, we are using Alan Beasley’s buttons from one of his projects.
Both of the methods to call LightSwitch from a Silverlight control, require references to:
- Microsoft.LightSwitch – ..\ClientGenerated\Bin\Debug\Microsoft.LightSwitch.dll
- Microsoft.LightSwitch.Client – ..\ClientGenerated\Bin\Debug\Microsoft.LightSwitch.Client.dll
The Sheel Method
Sheel Shah, from the LightSwitch team showed me this method. We just double-click on the button in the designer, and enter the following code:
using System.Windows.Controls;
using Microsoft.LightSwitch.Presentation;
namespace SilverlightUI
{
public partial class InventoryUI : UserControl
{
public InventoryUI()
{
InitializeComponent();
}
private void TransfeerInventoryButton_Click
(object sender, System.Windows.RoutedEventArgs e)
{
// Get a reference to the LightSwitch DataContext
var objDataContext = (IContentItem)this.DataContext;
// Get a reference to the LightSwitch Screen
var Screen =
(Microsoft.LightSwitch.Client.IScreenObject)objDataContext.Screen;
// Call the Method on the LightSwitch screen
Screen.Details.Dispatcher.BeginInvoke(() =>
{
Screen.Details.Methods["TransfeerInventory"]
.CreateInvocation(null).Execute();
});
}
}
}
That’s it. The advantage is that it really cannot get any simpler. The only disadvantage of this, is that code can break (if the method signature changes), and it wont show up at compile-time.
The Karol Method
Karol Zadora-Przylecki, from the LightSwitch team showed me this method.
First we switch to File View (you have to click on the LightSwitch project in the Visual Studio Solution Explorer first to see that button).
We create a class file in the Common project with the following code:
using System;
namespace LightSwitchApplication.UserCode
{
public interface IInventoryManagement
{
void TransfeerInventory();
void GetExistingInventory();
}
}
We go to the LightSwitch screen that we plan to use our Silverlight Custom Control on, and click Write Code.
We enter code to inherit from the Interface we just created.
We use this code for the implementation:
// Interface
void UserCode.IInventoryManagement.TransfeerInventory()
{
TransfeerInventory_Execute();
}
void UserCode.IInventoryManagement.GetExistingInventory()
{
GetExistingInventory_Execute();
}
We add a reference to the Common project in our Silverlight project.
We are then able to use the following code for the button event:
private void GetInventoryButton_Click
(object sender, System.Windows.RoutedEventArgs e)
{
// Get a reference to the LightSwitch DataContext
var objDataContext = (IContentItem)this.DataContext;
// Get a reference to the LightSwitch Screen
var Screen =
(Microsoft.LightSwitch.Client.IScreenObject)objDataContext.Screen;
// Cast the LightSwitch Screen to our custom Interface
// (that we put in the "common" project)
var InventoryManagement =
(LightSwitchApplication.UserCode.IInventoryManagement)Screen;
// Call the Method on the LightSwitch screen
Screen.Details.Dispatcher.BeginInvoke(() =>
{
InventoryManagement.GetExistingInventory();
});
}
See the article at this link for the steps on adding a Silverlight Custom Control to your LightSwitch screen.
When we run the project, we can call any Method (Command) on our LightSwitch screen.
It is suggested that you also read: This Is How LightSwitch Does MVVM, to fully understand how all of this is simply part of the MVVM pattern.
Note: There is a third method covered at this link.
Download
You can download the code at this link.
18 comment(s) so far...
This is awesome. Thanks Michael, Karol, Alan, and Sheel!
So many doors are open with LS now.
By Garth Henderson on
5/21/2011 8:13 AM
|
@Garth Henderson - Yes this does "open doors". We can create a custom Shell (that will remove the normal LightSwitch menu), and then create a UI composed entirely of our custom Silverlight design.
The final result would look the same as a normal Silverlight application (because actually is IS a Silverlight application), but the time savings would be massive.
By Michael Washington on
5/21/2011 9:34 AM
|
Very good job. Rachida
By Rachida Dukes on
5/21/2011 11:26 AM
|
@Rachida Dukes - Thank you!
By Michael Washington on
5/21/2011 11:36 AM
|
Great article - I like the idea about the 'Custom Shell' which could turn out to be very powerful.
By Tim Leung on
5/21/2011 12:42 PM
|
I tried the ideas on this page. I have a custom control containing a textbox that executes its KeyDown method when the user presses the Enter button. But for some reason my custom control does not remember the value entered in the textbox. But if I enter another value and press Enter, a second time, the first value I entered before seems to be remembered. Here's my code:
private void TextBox_KeyDown(object sender, KeyEventArgs e) { // When user presses Enter, call the OpenTransactionList method on the Home (parent of the custom control) screen. if (e.Key == Key.Enter) { // Get a reference to the LightSwitch DataContext var objDataContext = (IContentItem)this.DataContext;
// Get a reference to the LightSwitch Screen var Screen = (Microsoft.LightSwitch.Client.IScreenObject)objDataContext.Screen; // Call the Method on the LightSwitch screen Screen.Details.Dispatcher.BeginInvoke(() => { Screen.Details.Methods["OpenTransactionList"].CreateInvocation(null).Execute(); }); } }
By Ray Cacciatore on
9/30/2011 8:00 PM
|
@Ray Cacciatore - Please post programming questions to the forums. You will also want to post the xaml code
By Michael Washington on
9/30/2011 8:02 PM
|
Is there a way to get a returning value from Light Switch from a Silverlight Control?
eg, In my screen code
// Interface void UserCode.IInventoryManagement.TransfeerInventory() { //TransfeerInventory_Execute(); return "Hello" }
Then on my Silverlight Control some like the following...
var objDataContext = (IContentItem)this.DataContext; var Screen = (Microsoft.LightSwitch.Client.IScreenObject)objDataContext.Screen;
string myVar = "Empty";
var SilverlightBridge = (LightSwitchApplication.UserCode.ISilverLightBridge)Screen;
Screen.Details.Dispatcher.BeginInvoke(() => { myVar = SilverlightBridge.GetVehicleID();
});
MessageBox.Show(myVar) ;
The issue I have is that myVar isn't being set. Would you have a recommendation?
Thanks Michael - your Lightswitch work is some of the best out there.
By Matt on
1/9/2012 8:36 AM
|
@Matt - Can you please post your question to the forums? The comments section in the blog is bad for tracking and resolving your issue.
By Michael Washington on
1/9/2012 8:37 AM
|
I can't find these two dlls Microsoft.LightSwitch, Microsoft.LightSwitch.Client in the ClientGenerated folder when I upgraded to Visual Studio 2012. I tried adding the ones in the Client\bin\debug folder but they dont work as well. Is there another way to call lightswitch from silverlight?
By pimlong on
7/4/2012 7:05 AM
|
@pinlong - I just upgraded the project to 2012 and it works fine. The .dlls are at: ..\LightSwitchBookInventory\ClientGenerated\Bin\Debug\..
By Michael Washington on
7/4/2012 7:07 AM
|
I also tried creating a new lightswitch project for visual studio 2012 and the ClientGenerated folder is completely missing. What should I do? Thanks for the quick reply.
By pimlong on
7/4/2012 9:57 PM
|
Hey Michael, thanks for this post. I’m getting an error on my IExecutable class calling my screen:
I’m calling a screen on the ExecutaAsyn method like this: public void ExecuteAsync() { Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(() => { Application.Current.ShowCustomersListDetail();
}); }
But on execution when I click the button I get this error: ” Operation is not valid due to the current state of the object.”
Any help is much appreciated!
By Juan on
9/1/2012 4:37 AM
|
@Juan - I can only suggest that you download my example code and compare it to your own.
By Michael Washington on
9/1/2012 4:39 AM
|
Hi Michael,
I follow your example in this article but it is not working. Not sure what I am doing wrong. For some reason, you are not allow to reference Microsoft.LightSwitch, Microsoft.LightSwitch.Client or Microsoft.LightSwitch.Client.Presentation from within Silverlight control. Just curious, how did your example code work for you? Also, because you can't reference the above assemblies, your code will error out on any reference to the IContentItem or DataContext, since these are in the above assemblies. I am sure I am missing something.
By Creo Abraham on
6/13/2013 1:57 PM
|
@Creo Abraham - I can only suggest that you download my example code and compare it to your own.
By Michael Washington on
6/13/2013 1:58 PM
|
Hi Michael,
The Karol Method In Visual studio 2012 there is no longer a Common project. So I added the Interface to DesktopClient/Shared folder
I then added a reference to DesktopClient.Client in my Silverlight Project All compiles but when I run the project I get a Webpage Error
Error: Unhandled Error in Silverlight Application Code: 2028 Category: ParserError Message: The name already exists in the tree: DesktopClient.Client. File: Line: 0 Position: 0
When I add the line.
Dim CBOMaintenanceScreen = CType(Screen, LightSwitchApplication.UserCode.ICBOMaintenance)
Any Ideas would be much appreciated. Regards, Dean
By Dean on
8/7/2013 4:13 AM
|
Dean - I am sorry but I do not have any examples for VS 2012. You will want to ask any questions on the official Microsoft LightSwitch Forums at: http://social.msdn.microsoft.com/Forums/vstudio/en-US/home?forum=lightswitch
By Michael Washington on
8/7/2013 4:39 AM
|