You are here:   Blog
Register   |  Login

Oct 8

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

image

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

image

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

 

image

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.

 

image

We make a simple List and Details screen that allows us to enter text.

 

The Silverlight Text Editor Sample

image

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.

 

image

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

 

image

We point to the SilverlightTextEditor.csproj file.

 

image

The project will show up in the Solution Explorer.

 

image

We also add references to:

  • Microsoft.LightSwitch
  • Microsoft.LightSwitch.Base.Client
  • Microsoft.LightSwitch.Client

 

Insert Control Into LightSwitch

image

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

 

image

In the Properties we click Change.

 

image

We click the Add Reference Button.

 

image

We create a Project reference to the SilverlightTextEditor project.

 

image

We will now be able to select the Custom Control.

We Click OK.

 

image

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

image

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.

 

image

We open MainPage.xaml in Expression Blend.

 

image

We delete al the resources in App.xaml.

 

image

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.

 

image

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;
            }
        }

 

image

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();
        }

 

image

(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

24 comment(s) so far...


Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

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
Gravatar

Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch

How do i run it on silverlight 5.0?
Thanks!

By Trung Nguyên on   7/30/2013 8:18 PM
Gravatar

Re: Silverlight RichTextBox: Integrating A Control That Does Not Have a Dependency Property In LightSwitch

@Trung Nguyên - Sorry I have no samples.

By Michael Washington on   7/30/2013 9:19 PM

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