Feb
4
Written by:
Michael Washington
2/4/2012 10:48 AM
Visual Studio LightSwitch allows you to create Business Type extensions. A Business Type “enables 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.
First note that the following are required in order to create LightSwitch extensions:
Create The Project
First, we create an extension project in Visual Studio.
We add a New Item to the .Lspkg project.
We add a Business Type to the project.
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>
The textbox will now be a red box.
Run The Project
We click on the .Vsix project…
We then Start Debugging. This will open another instance of Visual Studio.
We create or open a LightSwitch project and go into Properties.
We click on the Extensions tab and enable the extension.
When we add fields to an Entity (table) we now have the option to select CustomerCode as the type.
When laying out a Screen we now have the option to select the Customers Code control.
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
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
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
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>
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: