LightSwitch – Installing on Windows XP requires SP3

This might be relevant to those building Virtual PCs or those who are planning on testing using Windows XP. Contrary to the system requirements that are specified on the LightSwitch website, the minimum version of XP required is in fact SP3, and not SP2. The following error is returned if you attempt to install LightSwitch on XP SP2.

image  image
Illustration of what happens when installing under XP SP2.

Advertisements
Posted in LightSwitch | Leave a comment

Clearing Browser History now clears Flash Cookies in Version 10.3

After attending a security presentation this week, one thing I learnt is that clearing your internet browser history will now clear Flash cookies if you have the latest version of Flash installed. This was also reported through the IE blog last week.

http://blogs.msdn.com/b/ie/archive/2011/05/03/deleting-flash-cookies-made-easier.aspx

In previous versions of Flash, the only way of clearing cookies was to use the Adobe ‘Settings Manager’ via the following web site.

http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager07.html

The security risk this posed was that even after deleting your browser history, someone using your PC could partially trace your browsing history and the videos that you’ve viewed using Flash cookies or the ‘Settings Manager’ shown above. Websites were also using Flash cookies to restore ‘regular HTTP cookies’ which may have been intentionally deleted by the user.

This update appears to have been long overdue and is a very positive change in terms of improving browser privacy.

Posted in Uncategorised | Leave a comment

LightSwitch – Limiting Item Selections using a ComboBox

Overview of Article

One of the annoyances about the LightSwitch AutoCompleteBox is that there isn’t an option to limit selections to only those items which are shown in the list. Non existent values can be typed in, causing validation errors to occur when a screen is saved.

image

Fig 1 – Illustration of AutoCompleteBox failing to limit selections.

Fortunately, the Silverlight ComboBox control can limit items to the list and the following article describes how we can use this control on a LightSwitch screen.

In the following example, we’ll create a customer entry screen and allow the user to select from a list of available Countries.

 

Data

The example solution contains a Person table and a Country table. The table schemas and relationships are illustrated in the following images below.

image
Fig 2 – Illustration of Person table

image
Fig 3 – Illustration of Country table

image

Fig 4 – One to Many relationship between Country and Person 

 

Screens

The following section describes the creation of the screens in the project..

  1. First of all, create an ‘Editable Grid Screen’ on the Country table to enable some Countries to be added.
  2. Create a ‘New Data Screen’ on the Person table.
  3. By default, an ‘AutoCompleteBox’ is created on the Country field. Change this to ‘Custom Control’ using the drop down list to the left of the control. After doing so, bring up the properties of the control and click on the ‘Change…’ link next to the ‘Custom Control’ field. In the dialog that appears, select the ‘ComboBox’ control from within the System.Windows.Controls namespace.

    image  image
    Fig 5 – Changing the AutoCompleteBox to a ComboBox

  4. We now need to create a data source in order to populate our ComboBox with a list of available Countries. In order to do this, click on the ‘Add Data Item’ button, select the ‘Query’ radio button and select ‘Countries – Country (All)’. Retain the default name of ‘Countries’.

    image
    Fig 6 – Creating a data source for our ComboBox
     

  5. We now need to write some code to bind our ComboBox to the person entity. Click on ‘Write Code’ button and select the ‘_Activated’ event. Now write the following code:
  6. Private Sub CreateNewPerson_Activated()
        Dim comboControl As IContentItemProxy = Me.FindControl("Country")
        comboControl.SetBinding(System.Windows.Controls.ComboBox.ItemsSourceProperty, "Screen.Countries", Windows.Data.BindingMode.TwoWay)
        comboControl.SetBinding(System.Windows.Controls.ComboBox.SelectedItemProperty, "Screen.PersonProperty.Country", Windows.Data.BindingMode.TwoWay)
    End Sub
    

    Here’s the C# equivalent…

    private void CreateNewPerson_Activated()
    {
        IContentItemProxy comboControl = this.FindControl("Country");
        comboControl.SetBinding(System.Windows.Controls.ComboBox.ItemsSourceProperty, "Screen.Countries", System.Windows.Data.BindingMode.TwoWay);
        comboControl.SetBinding(System.Windows.Controls.ComboBox.SelectedItemProperty, "Screen.PersonProperty.Country", System.Windows.Data.BindingMode.TwoWay);
    }
    
  7. Now run our application and open the ‘Create Person’ screen. The list of Countries is now limited to those shown in the list.
    image
    Fig 7 – Illustration of final screen showing the ComboBox which can not be typed into.

Conclusion 

This article demonstrates how we can limit drop down choices by using a Silverlight ComboBox. It also illustrates the data binding syntax which is used when binding custom controls. The image below illustrates the relationship between the designer and the call to the SetBinding method. This is particularly relevant when creating a ‘details screen’ as the default entity will be ‘Person’ rather than ‘PersonProperty’.

  

image

Fig 8 – Illustration of DataBinding Code

 

Posted in LightSwitch | 22 Comments

LightSwitch – Add non existent records using AutoCompleteBox

Overview of Article

The LightSwitch AutoCompleteBox allows you select records using a dropdown list or to enter some text into the control. Typing into the AutoCompleteBox filters down the selectable records.

If a non existent record entered, it’s likely that a new record is required based upon the entered text. 

The following example uses a set of Customer and Category tables. A Customer belongs to a Category and the following sample demonstrates a ‘New Data Screen’ for creating a new Customer. The screen contains an AutoCompleteBox which allows a category to be selected. If a non existent category is typed in, the user will be prompted to save the new category prior to saving the customer record.

Data

The following screenshots illustrate the schema of our tables. A ‘zero or one’ to many relationship has been set up between the Category and Customer tables.

 

image

Fig 1 – Category table schema

image

Fig 2 – Customer table schema

image

Fig 3 – Relationship between the 2 tables

Screens

Here are the steps to create our ‘Customer’ screen.

  1. Create a new ‘Editable Grid Screen’ for entering in some Category details
  2. Create a ‘New Data Screen’ based upon the Customer table
  3. In order to programmatically access the AutoCompleteBox, we need to add a reference to System.Windows.Controls.Input in the client project. To do this, switch to ‘File Mode’ in solution explorer.
    image_thumb[24]
    Fig 4 Switch to File View in Solution Explorer

  4. Right click the  ‘Client’ folder and click ‘Add Reference’. Select System.Windows.Controls.Input
    image_thumb[25]
    Fig 4 Add a reference to System.Windows.Controls.Input

  5. We need to write some code to handle the LostFocus event of the AutoCompleteBox. However, this can only be done when the AutoCompleteBox becomes available. We therefore need to write an event handler for the ‘ControlAvailable’ event and to add the handler for the LostFocus event there. Click on the ‘Write Code’ button and click and select the ‘CreateNewCustomer_Created’ event. Add the following code:
    Private Sub CreateNewCustomer_Created()
        AddHandler Me.FindControl("Category").ControlAvailable, AddressOf CategoryFieldAvailable
    End Sub
    
    Private Sub CategoryFieldAvailable(sender As Object, e As ControlAvailableEventArgs)
        AddHandler CType(e.Control, System.Windows.Controls.Control).LostFocus, AddressOf CategoryFieldChanged
    End Sub
    
    Private Sub CategoryFieldChanged(sender As Object, e As System.Windows.RoutedEventArgs)
    
        'Add a reference to System.Windows.Controls.Input.dll in the Client project
        Dim txtComboText As String = CType(sender, System.Windows.Controls.AutoCompleteBox).Text
        Me.Details.Dispatcher.BeginInvoke(
            Sub()
                If txtComboText <> "" Then
                    Dim selectedCategory As Category = Me.DataWorkspace.ApplicationData.Categories.Where(Function(Category) Category.CategoryName = txtComboText).FirstOrDefault
                    If selectedCategory Is Nothing Then
                        'Category doesn't exists
                        If Me.ShowMessageBox("Do you want to add the category " & txtComboText & "?", "Add Category", MessageBoxOption.YesNo) = Windows.MessageBoxResult.Yes Then
                            selectedCategory = Me.DataWorkspace.ApplicationData.Categories.AddNew()
                            selectedCategory.CategoryName = txtComboText
                            Me.CustomerProperty.Category = selectedCategory
                        End If
                    End If
                End If
            End Sub)
    
    End Sub
    

    Here’s how the C# equivalent looks like:

    private void CreateNewCustomer_Created()
    {
        this.FindControl("Category").ControlAvailable += CategoryFieldAvailable;
    }
    
    private void CategoryFieldAvailable(object sender, ControlAvailableEventArgs e)
    {
        ((System.Windows.Controls.Control)e.Control).LostFocus += CategoryFieldChanged;
    }
    
    
    private void CategoryFieldChanged(object sender, System.Windows.RoutedEventArgs e)
    {
        //Add a reference to System.Windows.Controls.Input.dll in the Client project
        string txtComboText = ((System.Windows.Controls.AutoCompleteBox)sender).Text;
        this.Details.Dispatcher.BeginInvoke(() =>
        {
            if (!string.IsNullOrEmpty(txtComboText)) {
                Category selectedCategory = this.DataWorkspace.ApplicationData.Categories.Where(Category => Category.CategoryName == txtComboText).FirstOrDefault;
                if (selectedCategory == null) {
                    //Category doesn't exists
                    if (this.ShowMessageBox("Do you want to add the category " + txtComboText + "?", "Add Category", MessageBoxOption.YesNo) == System.Windows.MessageBoxResult.Yes) {
                        selectedCategory = this.DataWorkspace.ApplicationData.Categories.AddNew();
                        selectedCategory.CategoryName = txtComboText;
                        this.CustomerProperty.Category = selectedCategory;
                    }
                }
            }
        });
    
    }
    
    

    In the above code, we obtain the text that has been entered using the ‘Text’ property of the AutoCompleteBox. If the text is not empty, we attempt to look up the Category in the Category table. If the Category isn’t found, we use ‘ShowMessageBox’ to prompt the user to save the new Category. After the new Category is saved, we set the Category property on the Customer entity equal to the Category which has just been created.

  6. Now run the application. Here are some illustrations showing the application in action. We begin by having just a ‘High Risk’ Category in the database.

    image

    In the ‘Create New Customer’ form, we enter a Firstname, Surname and type ‘Low Risk’ into the Category AutoCompleteBox. When we leave the Category AutoCompleteBox, the following dialog appears.

    image

    If we click ‘Yes’, the Customer record is saved into the database. If we now return to the Category screen, we see that the ‘Low Risk’ category has also been added into the database.

    image

 

Conclusion

This article illustrates how records can be added using an AutoCompleteBox. The sample solution could benefit from some refinement but highlights various principles required in order to put together a working screen.

The example solution can be downloaded from the following link.

http://cid-7a042700ee409d7b.office.live.com/self.aspx/LightswitchFiles/CustomerCategory3.zip

 

Posted in LightSwitch | 35 Comments

LightSwitch – In What Order do Screen Events Fire?

Overview of Article

There are various screen events available in LightSwitch. At the moment, there isn’t very much documentation specifying the order in which these events fire.

The following post documents my findings in relation to the ordering of events.

Methodology

Having created a details screen based on a ‘Customer’ entity, this is a typical screen which is created by default. The name of the screen is ‘CustomerDetail’ and the name of the Customer entity is ‘Customer’.

image

Fig 1 Illustration of Details screen

The following screenshot shows the available events. There are 3 property/entity events and 7 screen events. ‘CustomerId’ is the name of the property that relates to the screen parameter.

image

Fig 2 Events that are available

In order to work out the order in which these events fire, I’ve written some code showing a message box on each event. Here are my findings:

Order of events when opening a screen

  1. New
  2. CustomerId_Changed
  3. CustomerDetail_InitializeDataWorkspace
  4. CustomerDetail_Created
  5. CustomerDetail_Activated
  6. Customer_Validate
  7. CustomerId_Validate
  8. Customer_Loaded

Order of Events when changing a field and clicking ‘Save’

  1. CustomerDetail_Saving
  2. Customer_Validate
  3. CustomerId_Validate
  4. Finalize

Order of Events when closing a screen with no changes

  1. CustomerDetail_Closing
  2. Finalize

Order of Events when closing a screen with unsaved changes and choosing to discard

  1. CustomerDetail_Closing
    image
      Dialog now appears – we choose ‘Discard’
  2. Finalize

Order of Events when closing a screen with unsaved changes and choosing to save

  1. CustomerDetail_Closing
    image
    Dialog now appears – we choose ‘Save’
  2. CustomerDetail_Saving
  3. Customer_Validate
  4. CustomerId_Validate
  5. Finalize

As a final note, the CustomerDetail_Activated will fire whenever you change focus to another screen and return to it. Hopefully, this post sheds a bit more light into the ordering of events.

Technorati Tags: ,
Posted in LightSwitch | 8 Comments

LightSwitch – Displaying Web Pages / HTML on a Screen

Overview of Article

Continuing with our earlier post on adding custom controls from the System.Windows.Controls namespace, the following article describes how to add a WebBrowser control onto a LightSwitch Screen.

This will allow us to display HTML or load web pages onto a LightSwitch Screen.

Screens

This example is not based upon any data. Therefore, create a new screen using the ‘New Data Screen’ template and select ‘Screen Data (None)’.
image

Fig 1 Create a screen based on no data

  1. In order for us to add a WebBrowser control onto the screen, we need to bind the control it to a notional piece of data. Therefore, click the ‘Add Data Item’ button and add a new local property of type string. Untick the ‘Is Required’ checkbox and name the control ‘prpWebPage’.
    image
    Fig 2 Add a local property called prpWebPage
  2. Drag the control onto the screen. Change the control from a TextBox into a Custom Control. On the properties pane, click the ‘change’ hyperlink and select ‘System.Windows.Controls.WebBrowser’.

    image
    Fig 3 Select System.Windows.Controls.WebBrowser

  3. In order to load a web page, we can use the ‘Navigate’ method on the WebBrowser control. However, we can only call this when the control is ready so we need to handle the ControlAvailable event. Click on the ‘Write Code’ button and select the ‘Activated’ event. Now write the following code:
    Private Sub WebPage_Activated()
        AddHandler Me.FindControl("prpWebPage").ControlAvailable, AddressOf webControlAvailable
    End Sub
    
    Private Sub webControlAvailable(sender As Object, e As ControlAvailableEventArgs)
        CType(e.Control, System.Windows.Controls.WebBrowser).Navigate(New Uri("http://news.bbc.co.uk"))
    End Sub
    

    Here’s the C# version….

    private void WebPage_Activated()
    {
        this.FindControl("prpWebPage").ControlAvailable += webControlAvailable;
    }
    
    private void webControlAvailable(object sender, ControlAvailableEventArgs e)
    {
        ((System.Windows.Controls.WebBrowser)e.Control).Navigate(new Uri("http://news.bbc.co.uk"));
    }
    

    Obviously, change the URL to the URL of your choice

  4. The properties of the control are now optionally modified to hide the label and to set the sizing to ‘stretch’. The alignment on the parent group can also be set to ‘top’ and ‘left’. If we now run the solution, here’s what appears.
    image
    Fig 4 Illustration of a loaded web page in LightSwitch

  5. If we want to display some HTML rather than load a web page, we can call the NavigateToString method on the WebBrowser Control. Here’s some sample code.
    Private Sub webControlAvailable(sender As Object, e As ControlAvailableEventArgs)
        Dim strHtml As String = "<h1>Hello World!</h1>"
        CType(e.Control, System.Windows.Controls.WebBrowser).NavigateToString(strHtml)
    End Sub
    

    Here’s the same in C#

    private void webControlAvailable(object sender, ControlAvailableEventArgs e)
    {
        string strHtml = "<h1>Hello World!</h1>";
        ((System.Windows.Controls.WebBrowser)e.Control).NavigateToString(strHtml);
    }
    
  6. Here’s what appears when we now run the application
    image
    Fig 5 Illustration of displaying custom HTML in the WebBroswer Control

 

Conclusion

This post illustrates how to load web pages and HTML content onto a LightSwitch screen.

There are many useful scenarios in which this can be used. For example, we can use this technique to display HTML data from a database. The technique could also be used to connect to a SQL Server reporting server in order to display reports inside LightSwitch.

 

Posted in LightSwitch | 69 Comments

LightSwitch – Creating a Masked Password TextBox Part 2

Overview of Article

Here’s an update to my previous post on creating a masked textbox.

The previous sample used the LostFocus event to save the password data into the entity. After a prompt from Yann Duran, the code has now been modified so that data binding syntax is used instead. Not only is this syntax much neater, we can also more easily get and retrieve data when building ‘detail’ type screens.

Screen Code Changes

  1. Follow the instructions from the previous post on creating a table and custom control of type System.Windows.Controls.PasswordBox
  2. Instead of writing the ‘LostFocus’ code referred to previously, write the following code instead:
    Private Sub CreateNewCustomer_InitializeDataWorkspace(ByVal saveChangesTo As Global.System.Collections.Generic.List(Of Global.Microsoft.LightSwitch.IDataService))
        ' Write your code here.
        Me.CustomerProperty = New Customer()
    
        Dim proxyPassword As IContentItemProxy = Me.FindControl("Password")
        proxyPassword.SetBinding(System.Windows.Controls.PasswordBox.PasswordProperty, "Value", Windows.Data.BindingMode.TwoWay)
    
    End Sub

    In the code above, the SetBinding method on the IContentItemProxy interface is called. The first parameter of this method accepts a System.Windows.DependencyProperty. The PasswordBox control includes a PasswordProperty that we can use for this purpose.

    Here’s the C# version:

    private void CreateNewCustomer_InitializeDataWorkspace(global::System.Collections.Generic.List<global::Microsoft.LightSwitch.IDataService> saveChangesTo)
    {
        // Write your code here.
        this.CustomerProperty = new Customer();
    
        IContentItemProxy proxyPassword = this.FindControl("Password");
        proxyPassword.SetBinding(System.Windows.Controls.PasswordBox.PasswordProperty, "Value", System.Windows.Data.BindingMode.TwoWay);
    }
  3. When we now run the project, the screen works as before. However as you can see, the code is now much simplified.

Checking the Entered Password

In this section, we’ll add a second PasswordBox and some validation code to enable us to check the entered password.

  1. Click on ‘Add Data Item’ and add a new local property of type string called ‘prpPassword2’
  2. Change the ‘Display Name’ of prpPassword2 to ‘Re-entered Password’
  3. Drag prpPassword2 onto the screen. Change the textbox control to a System.Windows.Controls.PasswordBox control.
  4. Extend the InitialiseWorkSpace event from above to bind the newly added PasswordBox to the prpPassword2 property:
    Private Sub CreateNewCustomer_InitializeDataWorkspace(ByVal saveChangesTo As Global.System.Collections.Generic.List(Of Global.Microsoft.LightSwitch.IDataService))
        ' Write your code here.
        Me.CustomerProperty = New Customer()
    
        Dim proxyPassword As IContentItemProxy = Me.FindControl("Password")
        proxyPassword.SetBinding(System.Windows.Controls.PasswordBox.PasswordProperty, "Value", Windows.Data.BindingMode.TwoWay)
    
        Dim proxyPassword2 As IContentItemProxy = Me.FindControl("prpPassword2")
        proxyPassword2.SetBinding(System.Windows.Controls.PasswordBox.PasswordProperty, "Value", Windows.Data.BindingMode.TwoWay)
    
    End Sub

    In C#…….

    private void CreateNewCustomer_InitializeDataWorkspace(global::System.Collections.Generic.List<global::Microsoft.LightSwitch.IDataService> saveChangesTo)
    {
        // Write your code here.
        this.CustomerProperty = new Customer();
    
        IContentItemProxy proxyPassword = this.FindControl("Password");
        proxyPassword.SetBinding(System.Windows.Controls.PasswordBox.PasswordProperty, "Value", System.Windows.Data.BindingMode.TwoWay);
    
        IContentItemProxy proxyPassword2 = this.FindControl("prpPassword2");
        proxyPassword2.SetBinding(System.Windows.Controls.PasswordBox.PasswordProperty, "Value", System.Windows.Data.BindingMode.TwoWay);
    
    }
  5. Click on the ‘Write Code’ button and select the ‘prpPassword2_Validate’ event. Now write the following code.
Private Sub prpPassword2_Validate(results As ScreenValidationResultsBuilder)

    If prpPassword2 <> Me.CustomerProperty.Password Then
        results.AddPropertyError("Reentered Password does not match Password")
    End If

End Sub

The C# version would be…

private void prpPassword2_Validate(ScreenValidationResultsBuilder results)
{
    if (prpPassword2 != this.CustomerProperty.Password) {
        results.AddPropertyError("Reentered Password does not match Password");
    }
}

Conclusion

When we now run the project, the screen checks to see whether or not we’ve entered our password correctly.

image

Fig 1 Error message that appears when incorrect password is re-entered

This post also highlights the syntax that you would use to perform 2 way data binding to controls in the System.Windows.Controls namespace.

Posted in LightSwitch | 8 Comments