Oct
8
Written by:
Michael Washington
10/8/2011 9:39 AM

It is important to know that you should only use the methods described here as a last resort. The methods described here should not be your first choice for implementing a custom Silverlight Control in LightSwitch. 99% of the time these other methods will work:
Videos:
- Part One - Creating and Binding a Silverlight Control in LightSwitch
- Part Two - The 3 methods of integrating a Silverlight Control in LightSwitch
The Problem
The Silverlight RichTextBox is notorious for being difficult to use with MVVM (LightSwitch uses MVVM). The problem is, that unlike most controls, it does not implement a Dependency Property to bind to.
Practically any control you run across will have a Dependency Property for you to bind to. Even when you make your own Silverlight control and put it in LightSwitch, you will usually have a control like a TextBox that has a Dependency Property for you to bind to. So to make this clear, we only need to go through the steps outlined below when we encounter the odd control that does not have a Dependency Property for you to easily bind to, or it has resources in the App.xaml.
The LightSwitch Application

To test out the RichTextBox, we create a simple table called Document.

We clear the Maximum Length property for the DocumentText field to allow unlimited text.
The XAML text created by RichTextBox is very verbose and requires a lot of room.

We make a simple List and Details screen that allows us to enter text.
The Silverlight Text Editor Sample

The first step is to download the Silverlight Text Editor Sample. The sample contains a Rich Text Box, but also implements a toolbar and other features such as copy and paste, and printing.

We unzip the project and add it as an Existing Project.

We point to the SilverlightTextEditor.csproj file.

The project will show up in the Solution Explorer.

We also add references to:
- Microsoft.LightSwitch
- Microsoft.LightSwitch.Base.Client
- Microsoft.LightSwitch.Client
Insert Control Into LightSwitch

On the LightSwitch screen, we select the Document Text Box and change it to a Custom Control.

In the Properties we click Change.

We click the Add Reference Button.

We create a Project reference to the SilverlightTextEditor project.

We will now be able to select the Custom Control.
We Click OK.

If we try to run the project at this point, the screen will just freeze up. We need to program the binding to make the control work, but the reason the screen is freezing up is that there are resources that the control is looking for in the app.xaml that it cannot get to.
Fixing Resource Issues

Currently the control is set to load “resources” such as templates and styling, from the app.xaml file.
The problem is, that when the control is running in LightSwitch, the app.xaml cannot load. We need to remove the references.
There are various methods to do this, however, the easiest is to use Microsoft Expression Blend.

We open MainPage.xaml in Expression Blend.

We delete al the resources in App.xaml.

If any resources are to be broken, we Reset to default values.
We also take this time to remove any buttons (and their associated code behind) that insert objects into the Rich Text Box. We would need additional code to actually save these objects to the database, and that is out of the scope of this article.
Code To Update The Rich Text Box
Normally we would bind LightSwitch to the control, and we would be done. However, the Rich Text Box does not expose a dependency property. We now have to alter the code behind of the control to manually update the control from LightSwitch, and to update LightSwitch when there are changes in the control.

First we create a DependancyProperty that will notify the control when LightSwitch is trying to bind to it. The main purpose for this is that we can wire-up an event, contentItem_PropertyChanged that will be raised whenever the LightSwitch property that the control is bound to changes.
This is the contentItem_PropertyChanged method that will get the value from LightSwitch and update the Rich Text Box:
private void contentItem_PropertyChanged(object sender,
System.ComponentModel.PropertyChangedEventArgs e)
{
// Get the DataContext
IContentItem contentItem = (IContentItem)sender;
// Make sure the contentItem is not null
if (contentItem.Value != null)
{
// Make sure we do not already have the value set
// from rtb_ContentChanged to prevent endless looping
if (contentItem.StringValue != rtb.Xaml)
{
// Check to see if the contentItem is an empty string
if (contentItem.StringValue != "")
{
// Set the value on the RichTextControl
rtb.Xaml = contentItem.StringValue;
xamlTb.Text = contentItem.StringValue;
}
else
{
// The RichText Control will throw an error
// if you attempt to set it to an empty string
// Create and set the minimal default text
StringBuilder SB = new StringBuilder();
SB.Append("<Section xml:space='preserve' HasTrailingParagraphBreakOnPaste='False' ");
SB.Append("xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>");
SB.Append("<Paragraph FontSize='20' FontFamily='Calibri' Foreground='#FF000000' ");
SB.Append("FontWeight='Normal' FontStyle='Normal' FontStretch='Normal' ");
SB.Append("TextAlignment='Left'><Run Text='' /></Paragraph></Section>");
rtb.Xaml = SB.ToString();
}
}
}
}
The Rich Text Box also has an event that is raised when text changes. This is the method that will fire and update LightSwitch:
private void rtb_ContentChanged(object sender, ContentChangedEventArgs e)
{
// Get the DataContext
IContentItem contentItem = (IContentItem)this.DataContext;
// Make sure we do not already have the value set
// from contentItem_PropertyChanged to prevent endless looping
if (contentItem.StringValue != rtb.Xaml)
{
// Set the value of the RichTextControl
// to the value in LightSwitch
contentItem.Value = rtb.Xaml;
}
}

We also override the code for the Add Button on the LightSwitch screen with code that will properly create a blank document:
partial void DocumentListAddAndEditNew_Execute()
{
// The RichText Control will throw an error
// if you attempt to set it to an empty string
// Create and set the minimal default text
StringBuilder SB = new StringBuilder();
SB.Append("<Section xml:space='preserve' HasTrailingParagraphBreakOnPaste='False' ");
SB.Append("xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'>");
SB.Append("<Paragraph FontSize='20' FontFamily='Calibri' Foreground='#FF000000' ");
SB.Append("FontWeight='Normal' FontStyle='Normal' FontStretch='Normal' ");
SB.Append("TextAlignment='Left'><Run Text='' /></Paragraph></Section>");
var NewDocument = Documents.AddNew();
NewDocument.DocumentTitle = "New Document";
NewDocument.DocumentText = SB.ToString();
}

(the program running with the Metro Theme)
Special Thanks
A special thanks to Sheel Shah and Karol Zadora-Przylecki for their assistance.
Download Code
The LightSwitch project is available at http://lightswitchhelpwebsite.com/Downloads.aspx
22 comment(s) so far...
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
Thanks for another awesome tutorial Michael.
PS : The code runs without referring Microsoft.LightSwitch.Base.Client.
By Bala on
10/8/2011 12:10 PM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
@Bala - Thanks for pointing that out. I just automatically add those references :)
By Michael Washington on
10/8/2011 12:15 PM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
Follow up from prior post referencing build error: 'FontStyle' is an ambigouous reference between 'System.Windows.FontStyle' and Microsoft.LightSwitch.Presentation.FontStyle'
The error is MainPage.xamal.cs in the btnItalic_Click event.
private void btnItalic_Click(object sender, RoutedEventArgs e) { if (rtb != null && rtb.Selection.Text.Length > 0) { if (rtb.Selection.GetPropertyValue(Run.FontStyleProperty) is FontStyle && ((FontStyle)rtb.Selection.GetPropertyValue(Run.FontStyleProperty)) == FontStyles.Normal) rtb.Selection.ApplyPropertyValue(Run.FontStyleProperty, FontStyles.Italic); else rtb.Selection.ApplyPropertyValue(Run.FontStyleProperty, FontStyles.Normal); } ReturnFocus(); }
with the two "FontStyle' references in the statement if (rtb.Selection.GetPropertyValue(Run.FontStyleProperty) is FontStyle && ((FontStyle) . . .
I have both these using statements in the .cs file using System.Text; using Microsoft.LightSwitch.Presentation;
Commenting out either of them obviously throws many other errors.
Would appreciate some advice as to how to resolve this. Thank you very much.
Ken
By Kenneth James on
10/10/2011 10:23 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
@Kenneth James - Open up References in the SilverlightTextEditor project and see if you have Yellow triangles on the three LightSwitch assemblies. If you do then that is the problem. Fix the references by locating them on your machine. My code is pointing to the default locations but you may have installed LightSwitch in another directory.
By Michael Washington on
10/10/2011 10:31 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
Just a note that on a 64 bit OS, the LS assemblies are loaded into: C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\LightSwitch\1.0\Client\
By Garth Henderson on
10/27/2011 7:19 PM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
@Garth Henderson - Thank you Garth that is very helpful.
By Michael Washington on
10/27/2011 7:26 PM
|
SilverLight/LightSwitch rich text control that copies/pastes styled text from the clipboard?
Many thanks for posting this tutorial!
In trying the demo code, I see that the SilverLight RichTextBox neither accepts styled text pasted from the clipboard nor copies styled text to the clipboard, making the control of limited practical use. Is there a LightSwitch-compatible rich text control that does support styled text to/from the clipboard?
By Keith Gillette on
11/9/2011 5:41 PM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
@Keith Gillette - see: http://lightswitchhelpwebsite.com/Blog/tabid/61/EntryId/48/Using-the-Telerik-Rich-Text-Editor-In-Visual-Studio-LightSwitch.aspx
By Michael Washington on
11/9/2011 8:23 PM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
Michael, I downloaded MS expression Blend 2, SP1 and installed it. I right click on mainpage.xml and select open with Expression Blend just like the tutorial above mentions. I get an error saying Invalid XAML and a bunch of erros in the results pane. for example, richtextbox is not supported in a Silveright project line 20, column 38 and so on.
I also have silverlight 4 & 5 SDK, I can build the silverlighttexteditor fine under VS2010. Is there something else I am missing in order for MS Expression Blend to work?
Thanks
By dbdmora on
3/22/2012 11:48 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
nevermind Michael, I had to get the latest Blend 4, thanks
By dbdmora on
3/22/2012 11:48 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
is it possible to save rich text into database ? Thanks
By werner on
5/4/2012 5:49 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
@werner - Yes this example does that.
By Michael Washington on
5/4/2012 5:49 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
function rtb_ContentChanged is never called. Do you know where could be a problem ?
By werner on
5/4/2012 6:31 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
I got it. I should create event in InitializeComponent() this.rtb.ContentChanged += new ContentChangedEventHandler(rtb_ContentChanged);
Thanks !
By werner on
5/4/2012 6:31 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
Hi, Michael I've tried running the sample on VS2012 RC, upgrading thhe project to SL5 and changing the references to the new LS dlls. When I run it I get:
No matching constructor found on type 'SilverlightTextEditor.Strings'. [Line:17 Position:30]
There were 3 warnings during build of which:
Message 2 The type 'local:Strings' was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built. C:\code\RichTextBox\SilverlightTextEditor\SilverlightTextEditor\SilverlightTextEditor\MainPage.xaml 17 10 SilverlightTextEditor
seems related. Can you help?
By emtopping on
7/28/2012 4:24 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
@emtopping - This project was created using Silverlight 4. You should be able to run it without upgrading it. Unfortunately I wont have time to update the code to Silverlight 5.
By Michael Washington on
7/28/2012 5:13 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
Ok, I'll try it as sl4. Sorry about the double post.
By emtopping on
7/28/2012 6:36 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
Well it looks like I can't target SL4 if I include the reference to LightSwitch from VS 2012 RC as that requires SL% (not surprisingly) Warning 3 The primary reference "Microsoft.LightSwitch" could not be resolved because it has an indirect dependency on the .NET Framework assembly "mscorlib, Version=5.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" which has a higher version "5.0.5.0" than the version "2.0.5.0" in the current target framework. SilverlightTextEditor
By emtopping on
7/28/2012 6:42 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
@emtopping - It looks like you will have to update the source code. I regret that I wont have time to update this.
By Michael Washington on
7/28/2012 7:00 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
I understand , Michael thanks for taking the time to reply.
By emtopping on
7/29/2012 6:32 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
Hi, all that needed to chaange to get it running was to make this internal class public
C:\code\RichTextBox\SilverlightTextEditor\SilverlightTextEditor\SilverlightTextEditor\Strings.Designer.cs(32): internal Strings() {
hope it helps someone.
By emtopping on
7/30/2012 8:11 AM
|
Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch
@emtopping - Thank you for following-up.
By Michael Washington on
7/30/2012 9:30 AM
|