The easiest way to create business applications for the Desktop and the Cloud
More videos »
LightSwitch provides built-in functionality quickly add or edit data in a grid or list. Unfortunately this modal dialog is not customizable. In more complex data entry scenarios, the built-in dialogs may not fulfill your customer's needs. There are a couple of options in this situation.
This article will describe how to provide a customized dialog for adding or editing records in a grid.
Create a new LightSwitch application. Add a Customer table with the following fields:
Create a new Editable Grid screen for Customers.
On the Editable Grid screen, right click on the top-most item and select "Add Group".
On the group, select the dropdown next to "Rows Layout" and change this to "Modal Window". Select the "Add" button underneath the modal window and choose Selected Item. This will display the currently selected customer in the modal window. This view can now be customized as necessary.
By default, a modal window group will display a button on the screen. This button can be used to launch the window. In our scenario, we don't want this default button display - instead, we'd like to launch the modal window whenever the user clicks the Add or Edit button in a list or grid. Select the modal window and in the properties grid set the "Show Button" property to false. We can also change the name of the group to CustomerEditDialog.
We can now override the grid's add and edit buttons to instead launch our modal window. Open the Command Bar for the data grid, right click on the "Add…" button and select "Override Code".
Add the following code for the Execute and CanExecute methods. This code will add a new record to the collection and open the modal window.
Private Sub gridAddAndEditNew_CanExecute(ByRef result As Boolean)
result = Me.Customers.CanAddNew()
End Sub
Private Sub gridAddAndEditNew_Execute()
Dim newCustomer As Customer = Me.Customers.AddNew()
Me.Customers.SelectedItem = newCustomer
Me.OpenModalWindow("CustomerEditDialog")
Similarly, right click on the "Edit…" button in the screen editor and select "Override Code" Add the following code.
Private Sub gridEditSelected_CanExecute(ByRef result As Boolean)
result = Me.Customers.CanEdit AndAlso Me.Customers.SelectedItem IsNot Nothing
Private Sub gridEditSelected_Execute()
Run the application and click on the Add or Edit buttons in the Editable Customer Grid. This should launch our custom dialog.
Unfortunately, the dialog we've created is quite limited in functionality. It does not include the Ok and Cancel buttons of the built-in dialog. It also does not update its title based on whether it is editing or creating a customer.
In the screen designer, right click on the Modal Window and select "Add Button...". Choose "New Method" and name the method EditDialogOk. In the property sheet, change the Display Name of the button to just Ok.
Add a similar button called EditDialogCancel. Again, change the display name of the modal window to just Cancel.
Double click on the Ok button to add some code. We will add some code to close the modal dialog when either Ok or Cancel is pressed.
Private Sub EditDialogOk_Execute()
Me.CloseModalWindow("CustomerEditDialog")
Private Sub EditDialogCancel_Execute()
This code simply closes the dialog when the user presses Cancel. This is not ideal. When Cancel is pressed, we'd like new records removed and changes to existing records reverted. This is possible, but requires a fair bit of code. The following helper class will provide this functionality.
Public Class DialogHelper
Private _screen As Microsoft.LightSwitch.Client.IScreenObject
Private _collection As Microsoft.LightSwitch.Client.IVisualCollection
Private _dialogName As String
Private _isEditing As Boolean = False
Private _entity As IEntityObject
Public Sub New
ByVal dialogName As String)
_screen = visualCollection.Screen
_collection = visualCollection
_dialogName = dialogName
Public Sub InitializeUI()
'This code may not work in Beta 2. Fixed in final release.
AddHandler _screen.FindControl(_dialogName).ControlAvailable,
Sub(sender As Object, e As ControlAvailableEventArgs)
Dim childWindow As System.Windows.Controls.ChildWindow = e.Control
AddHandler childWindow.Closed, Sub(s1 As Object, e1 As EventArgs)
If _entity IsNot Nothing Then
DirectCast(_entity.Details, IEditableObject).CancelEdit()
End If
Public Function CanEditSelected() As Boolean
Return _collection.CanEdit() AndAlso (Not _collection.SelectedItem Is Nothing)
End Function
Public Function CanAdd() As Boolean
Return _collection.CanAddNew()
Public Sub AddEntity()
_isEditing = False
_collection.AddNew()
_screen.FindControl(_dialogName).DisplayName = "Add " + _collection.Details.GetModel.ElementType.Name
BaseOpenDialog()
Public Sub EditSelectedEntity()
_isEditing = True
_screen.FindControl(_dialogName).DisplayName = "Edit " + _collection.Details.GetModel.ElementType.Name
Private Sub BaseOpenDialog()
_entity = _collection.SelectedItem()
If _entity IsNot Nothing Then Dispatchers.Main.Invoke(Sub()
DirectCast(_entity.Details, IEditableObject).EndEdit()
DirectCast(_entity.Details, IEditableObject).BeginEdit()
End Sub)
_screen.OpenModalWindow(_dialogName)
Public Sub DialogOk()
_screen.CloseModalWindow(_dialogName)
Public Sub DialogCancel()
Dispatchers.Main.Invoke(Sub()
If _isEditing = False Then
_entity.Delete()
End SubEnd Class
First, we'll need to add the class to our project. Right click on the application in the solution explorer and select "View Application Code (Client)". Paste the code from above beneath the Application class. This will also require importing the Microsoft.LightSwitch.Threading namespace.
Imports Microsoft.LightSwitch.Threading
Namespace LightSwitchApplication
Public Class Application
End Class
'Code from above
End Namespace
This helper library requires a reference to an additional library. Select the application in Solution Explorer and switch to File View. Right click on the Client application and select "Add Reference". Select the "System.Windows.Controls" component and press Ok.
On our existing grid screen for Customer, we'll need to initialize and use this helper class. The code for many of our existing methods is replaced by calls to the helper class. The final code for our screen is shown below.
Public Class EditableCustomersGrid
Private customersDialogHelper As DialogHelper
Private Sub EditableCustomersGridOld_InitializeDataWorkspace( saveChangesTo As System.Collections.Generic.List(Of Microsoft.LightSwitch.IDataService))
customersDialogHelper = New DialogHelper(Me.Customers, "CustomerEditDialog")
Private Sub EditableCustomersGridOld_Created()
customersDialogHelper.InitializeUI()
result = customersDialogHelper.CanAdd()
customersDialogHelper.AddEntity()
result = customersDialogHelper.CanEditSelected()
customersDialogHelper.EditSelectedEntity()
customersDialogHelper.DialogOk()
customersDialogHelper.DialogCancel()
Run the application again. Click on the "Add" button for the grid. This will open our modal dialog with the title appropriately updated. If we click on the "Cancel" button, the newly added record will be removed. Similarly, if a record is being edited and "Cancel" is clicked, the changes will be reverted.
While a little involved, this technique can be applied to any of your other screens. If you have more than one list on a screen, multiple custom dialogs can be added. The DialogHelper class utilizes some of the more advanced API options available within LightSwitch. We’re also planning on wrapping this sample into a screen template that will automatically generate the modal window and code that is needed.
- Sheel
vsls team hi
for real this thinks is so much harder for any one
in the time all in microsoft history create business application as a easy way to create business application ands now become harder to add a button
thinks again
ayman fouad fb.com/submarin64x
merci beaucoup !!!!!
c'est simple et bien expliqué
Thanks a lot
Sometimes you want to initialize the entity so I added this overload:
Public Sub AddEntity(initialEntity As Object)
_collection.SelectedItem = initialEntity
_screen.FindControl(_dialogName).DisplayName = "Add " +
_collection.Details.GetModel.ElementType.Name
In the caller I just do:
Private Sub StudentsByFacilityId1AddAndEditNew_Execute()
Dim newStudent As New Student
newStudent.Facility = ppvFacility
GenericDialogHelper.AddEntity(newStudent)
public class DialogHelper
{
private Microsoft.LightSwitch.Client.IScreenObject _screen;
private Microsoft.LightSwitch.Client.IVisualCollection _collection;
private string _dialogName;
private bool _isEditing = false;
private IEntityObject _entity;
public DialogHelper(Microsoft.LightSwitch.Client.IVisualCollection visualCollection, string dialogName)
_screen = visualCollection.Screen;
_collection = visualCollection;
_dialogName = dialogName;
}
public void InitializeUI()
//This code may not work in Beta 2. Fixed in final release.
_screen.FindControl(_dialogName).ControlAvailable += (object sender, ControlAvailableEventArgs e) =>
System.Windows.Controls.ChildWindow childWindow = (ChildWindow)e.Control;
childWindow.HasCloseButton = false;
childWindow.Closed += (object s1, EventArgs e1) =>
if (_entity != null) {
((IEditableObject)_entity.Details).CancelEdit();
};
public bool CanEditSelected()
return _collection.CanEdit && ((_collection.SelectedItem != null));
public bool CanAdd()
return _collection.CanAddNew;
public void AddEntity()
_isEditing = false;
_collection.AddNew();
_screen.FindControl(_dialogName).DisplayName = "Add " + _collection.Details.GetModel().ElementType.Name;
BaseOpenDialog();
public void EditSelectedEntity()
_isEditing = true;
_screen.FindControl(_dialogName).DisplayName = "Edit " + _collection.Details.GetModel().ElementType.Name;
private void BaseOpenDialog()
_entity = (IEntityObject)_collection.SelectedItem;
Dispatchers.Main.Invoke(() =>
((IEditableObject)_entity.Details).EndEdit();
((IEditableObject)_entity.Details).BeginEdit();
});
_screen.OpenModalWindow(_dialogName);
public void DialogOk()
if (_entity != null && _entity.Details.ValidationResults.Errors!=null) {
Dispatchers.Main.Invoke(() => { ((IEditableObject)_entity.Details).EndEdit(); });
_screen.CloseModalWindow(_dialogName);
public void DialogCancel()
Dispatchers.Main.Invoke(() => { ((IEditableObject)_entity.Details).CancelEdit(); });
if (_isEditing == false) {
_entity.Delete();
VSLS2011 is ease
Me.Customers.SelectedItem.Delete();
Me.CloseModalWindow("CustomerEditDialog");
Thanks Sheel for this great DialogHelper class. I have a little feedback with a problem I'm facing.
When the the "Add Entity" dialog is open and the user presses the escape key, the new entity created will remain as it is. The DialogCancel() sub works so I tried to add the lines around "_entity.Delete()" to the InitializeUI() sub.
Unfortunately I get the error "It is not valid to call Execute() on a different Dispatcher than the ExecutableObject's Logic Dispatcher". I believe is something to do with a different thread and I can't figure out a solution.
I just found a post by Yann that solves my problem. Here's the link
"Improved Modal Window Helper Class (based on Sheel's Article 'Creating a Custom Add Or Edit Dialog')"
social.msdn.microsoft.com/.../138464dd-f38e-48b6-a610-28279418b238
perfect code ,,, tks
Would appreciate if the code would be in C#
Will also appreciate code in C# please
Thank you for this great example.
Is there a way to disable the Enter key because the Enter key triggers the close event by default !!!
I'm having a problem when I click the OK button on the modal dialog. If I enter no info in the dialog and I press OK, none of the validation errors appear, it just closes and the record in the datagrid stays in the datagrid with the empty fields. I'd like the dialog to stay opened and show the validation errors, even when the user clicks ok.
Anyone found the work around for Ray and Markus's problem mentioned above?
Anyone knows how to provide specific screens for adding/editing records? Because the built-in modal dialog don´t let me add new child records at the same time I’m adding the main record. I created a screen that let me do that but I don´t know how to pass the parent Id to the child so I don´t have to complete it manually