You are here:   Blog
Register   |  Login

LightSwitch News

Why I Love Office 365
9/29/2014 12:07 PM

 

Feb 4

Written by: Michael Washington
2/4/2012 10:48 AM  RssIcon

image

Visual Studio LightSwitch allows you to create Business Type extensions. A Business Typeenables you to present data in a way that is most appropriate for your application without changing the data type in which the data is stored in the underlying database”. In this article we will create a Business Type for a Customer Code. The underlying type will be a String, but the Business Type will be a custom type that requires the first character to not be a number and for it to be at least 10 characters long. It will also have its own custom control for display and editing.

Microsoft has an article, Walkthrough: Creating a Business Type Extension, that covers the basics of creating Business Type Extensions for LightSwitch, however, that article goes very deep into all the possible options and configurations. You may find this article an easier introduction.

image

First note that the following are required in order to create LightSwitch extensions:

Create The Project

image

First, we create an extension project in Visual Studio.

image

We add a New Item to the .Lspkg project.

image

We add a Business Type to the project.

image

A number of files are created in the various projects in the solution, including a CustomerCodeControl.xaml file in the Presentation/Controls folder in the .Client project.

Change the code in the CustomerCodeControl.xaml file to the following code:

 

<UserControl x:Class="CustomerCodeExtension.Presentation.Controls.CustomerCodeControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <TextBox Text="{Binding StringValue, Mode=TwoWay}" Background="#FFDFA9A9" 
                 ToolTipService.ToolTip="{Binding Description}" Foreground="#FFF1F18E" 
                 FontWeight="Bold" />
    </Grid>
</UserControl>

 

image

The textbox will now be a red box.

Run The Project

image

We click on the .Vsix project…

image

We then Start Debugging. This will open another instance of Visual Studio.

image

We create or open a LightSwitch project and go into Properties.

image

We click on the Extensions tab and enable the extension.

image

When we add fields to an Entity (table) we now have the option to select CustomerCode as the type.

image

When laying out a Screen we now have the option to select the Customers Code control.

image

When we run the application, the Customers Code control will display.

Adding Validation

At this point the CustomerCode type is simply a normal String type. We want to add validation that requires the first character to not be a number, and for the entire Customer Code to be at least 10 characters.

To implement validation, we need to complete the following steps:

  • Create constants – we will create a class to define constants that will be consumed by the remaining code.
  • Create the validation rule – this is where we will place our validation logic.
  • Define a validation attribute – this informs LightSwitch that we have a validation rule.
  • Create a ValidatorFactory – this is boilerplate code that allows LightSwitch to implement our validation rule.
  • Add a validation indicator – code that we add to the custom control to display validation errors.

 

Create Constants

image

First, we create a new file called CustomerCodeExtensionModule.cs in the Common project and use the following code:

 

using System;
namespace CustomerCodeExtension
{
    internal static class CustomerCodeExtensionModule
    {
        private const string Name = "CustomerCodeExtension";
        private const string ModulePrefix = Name + ":";
        private const string AttributePrefix = ModulePrefix + "@";
        internal static class PositiveInteger
        {
            private const string Name = "CustomerCode";
            public const string GlobalName = ModulePrefix + Name;
            internal static class ValidationAttribute
            {
                private const string Name = "CustomerCodeValidation";
                public const string GlobalName = AttributePrefix + Name;
            }
        }
    }
}

 

Create The Validation Rule

image

Next, we create a new file called CustomerCodeValidation.cs in the Common project and use the following code:

 

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Model;
using Microsoft.LightSwitch.Runtime.Rules;
using System.Text.RegularExpressions;
namespace CustomerCodeExtension
{
    public class CustomerCodeValidation : IAttachedPropertyValidation
    {
        public CustomerCodeValidation(IEnumerable<IAttribute> attributes)
        {
            _attributes = attributes;
        }
        private IEnumerable<IAttribute> _attributes;
        public void Validate(object value, IPropertyValidationResultsBuilder results)
        {
            if (null != value)
            {
                string strValue = (string)value;
                // Ensure string is not empty
                if (strValue.Trim().Length < 10)
                {
                    results.AddPropertyError("Customer number must be at least 10 characters.");
                }
                else
                {
                    // validation rule: first character must not be a number.
                    if (IsNumber(strValue.Substring(0, 1)))
                    {
                        results.AddPropertyError("First character must not be a number.");
                    }
                }
            }
        }
        bool IsNumber(string text)
        {
            Regex regex = new Regex(@"^[-+]?[0-9]*\.?[0-9]+$");
            return regex.IsMatch(text);
        }
    }
}

 

Add The Validation Attribute

image

Now, we open the CustomerCode.lsml file and change it to the following code:

 

<?xml version="1.0" encoding="utf-8" ?>
<ModelFragment
  xmlns="http://schemas.microsoft.com/LightSwitch/2010/xaml/model"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  
  <SemanticType Name="CustomerCode"
    UnderlyingType=":String">
    <SemanticType.Attributes>
      <DisplayName Value="CustomerCode" />
        <Attribute Class="@CustomerCodeValidation">
        </Attribute>
    </SemanticType.Attributes>
  </SemanticType>
    <AttributeClass Name="CustomerCodeValidation">
        <AttributeClass.Attributes>
            <Validator />
            <SupportedType Type="CustomerCode?" />
        </AttributeClass.Attributes>
    </AttributeClass>
    
  <DefaultViewMapping
    ContentItemKind="Value"
    DataType="CustomerCode"
    View="CustomerCodeControl"/>
</ModelFragment>

 

Add The ValidatorFactory Code

We add the following code to the CustomerCodeValidation.cs file:

 

[Export(typeof(IValidationCodeFactory))]
    [ValidationCodeFactory(CustomerCodeExtensionModule.PositiveInteger.ValidationAttribute.GlobalName)]
    public class CustomerCodeValidatorFactory : IValidationCodeFactory
    {
        public IAttachedValidation Create(IStructuralItem modelItem, IEnumerable<IAttribute> attributes)
        {
            // Enusre that the type model item is the proper type 
            if (!IsValid(modelItem))
            {
                throw new InvalidOperationException("Unsupported data type.");
            }
            return new CustomerCodeValidation(attributes);
        }
        public bool IsValid(IStructuralItem modelItem)
        {
            INullableType nullableType = modelItem as INullableType;
            // Get underlying type if it is an INullableType.
            modelItem = null != nullableType ? nullableType.UnderlyingType : modelItem;
            // Ensure that type is the proper type
            while (modelItem is ISemanticType)
            {
                if (String.Equals(((ISemanticType)modelItem).Id, 
                    CustomerCodeExtensionModule.PositiveInteger.GlobalName, StringComparison.Ordinal))
                {
                    return true;
                }
                modelItem = ((ISemanticType)modelItem).UnderlyingType;
            }
            // If the conditions aren't met, LightSwitch will not display the validation rule for
            //   this model item.
            return false;
        }
    }

 

Add The Validation Indicator

Finally we change the code in the CustomerCodeControl.xaml file to the following:

<UserControl x:Class="CustomerCodeExtension.Presentation.Controls.CustomerCodeControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:slu="clr-namespace:Microsoft.LightSwitch.Utilities.SilverlightUtilities;assembly=Microsoft.LightSwitch.Client"
    >
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <TextBox Text="{Binding StringValue, Mode=TwoWay}" Background="#FFDFA9A9" 
                 ToolTipService.ToolTip="{Binding Description}" Foreground="#FFF1F18E" FontWeight="Bold" />
        <slu:ValidatableContentControl ValidationDataSource="{Binding StringValue}" Grid.ColumnSpan="2"/>
    </Grid>
</UserControl>

 

image

When we run an application that implements the extension, we see the custom validation.

 

Download Code

The LightSwitch project is available at http://lightswitchhelpwebsite.com/Downloads.aspx

Also See:

Microsoft Tutorials:


Your name:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
CAPTCHA image
Enter the code shown above in the box below
Add Comment   Cancel 

Microsoft Visual Studio is a registered trademark of Microsoft Corporation / LightSwitch is a registered trademark of Microsoft Corporation