Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Creating an HTML Text Area Server Side Control

0.00/5 (No votes)
29 Jan 2003 2  
Using VB.NET and Java Script to Create ASP.NET Rich Edit Server Side Control.

Sample Image - text_area_control.jpg

Introduction

This article demonstrate that how can you create a Rich Editor, which supports HTML formatting, Server Side Control in VB .NET. This is my very first control I wrote in .NET. The purpose to write this article is to validate the technique I used and to know about any other better idea on writing controls in .NET. So let's begin.

Understanding JavaScript Editor

First of all, I am going to demonstrate that how we can create an Editor using HTML and JavaScript. Later we will convert the same to .NET server side control.

The core technique of creating the Editor is the use of execCommand method (Java Script). Let's see a simple example.

<HTML>
    <Head>
        <Title>Simple Demo of HTML Area </Title>
    <Script Language="JavaScript">
        function doBold()
        {
            frameEdit.document.execCommand('bold', false, null);
        }
        function doItalic()
        {
            frameEdit.document.execCommand('italic', false, null);
        }
    </Script>
    </Head>
    <Body onLoad="frameEdit.document.designMode='on';">
        <form id="frmEdit">
            <IFRAME id="frameEdit" style="width:600px; height:300px" align=center>
</IFRAME>
            <br>
            <P align=center>
                <Input type="Button" value="Bold" onClick="doBold()">
                <Input type="Button" value="Italic" onClick="doItalic()">
            </P>
                
            
        </form>
    </Body>
</HTML>

Just copy and paste above code to some editor and save as HTML. Run in browser, you will see that IFrame is behaving like a TextArea HTML control. OK, type something there, select and click on Bold Button. You will see that the text you typed is converted to Bold, and same with the Italic. It means it worked. Let's analyze the code we have written above.

We are starting from Body tag. The Script portion inside Head tag will be discussed later. On loading of body, we said that browser should start the design mode of our Inline Frame (IFrame, named frameEdit). This property will convert the IFrame to an Editable textbox. Ok, then on the Click events of the buttons, we invoked the JavaScript functions, doBold and doItalic. The functions were defined in the Head portion of our HTML document. There is only one statement in each function (doBold and doItalic). That is, the execCommand method of frameEdit's document property. The execCommand has three parameters, the Command, UserInterface, and the UserValue. Let's see them in some detail

Parameters of execCommand Method

Let's take a look at parameters of execCommand. As I told you before, this method is the heart of our HTML Area. Just understand the parameters of this method, and the rest is really more than easy.

Command (First Parameter)

The First parameter of execCommand is UserCommand. It is a string value which defines the work to do. In our above example, we passed bold and italic respectively. There are a number of commands which could be passed to this function. A complete list of these commands can be found in MSDN. Just look for Command Identifiers or execCommand in Index of your MSDN library. I am writing some commands here which were used in my HTML area.

  • BackColor To set the Back Color of the Text
  • Bold To set the Text to Bold
  • Copy To Copy some text to ClipBoard. (Copy will be made in HTML Format)
  • CreateLink Select some text and execute this command. This will make your text a Hyper Link
  • Cut Cuts text.
  • FontName To Change the Font of the Selected Text
  • FontSize To Change the Size of the Font.
  • ForeColor To Change the Fore Color of the Text.
  • Indent Increase the Indent of the Text/Paragraph.
  • InsertImage To Insert Image in your Editor area.
  • Italic To set the Text to Italic
  • JustifyCenter Center Justifies the Text
  • JustifyLeft Left Justifies the Text
  • JustifyRight Right Justifies the Text
  • Outdent Decrease the Indent.
  • Redo Redo your last action (inverse of Undo)
  • SaveAs Opens the Dialogue Box to save your work.
  • StrikeThrough Set the Text to Strike Through.
  • Subscript Moves the Selected text to slightly down than a normal text.
  • Supercript Moves the Selected text to slightly up than a normal text.
  • UnderLine To create Underlined text
  • Undo Undo the last action.
  • Unlink Removes hyperlink, if any

There are many more commands which could be used to format your HTML document. You can experience for more commands from MSDN. But for the moment, this is enough.

User Interface (Second Parameter)

The Second parameter asks you that either the execCommand should show some user interface for the Command you have just passed in first parameter or not? It is either true or false. If you set it to true, then Explorer will provide appropriate user interface for that command, if no, then you manually have to pass the values (if any required) to the function in it's third parameter (third parameter, Value is discussed later). In the above example, we just passed false for this parameter because, no User Interface was required for Bold or Italic Commands. Now let's see a simple example which will use this parameter to show any user interface.

<HTML>
    <Head>
        <Title>Simple Demo of HTML Area </Title>
    <Script Language="JavaScript">
        function doLink1()
        {
              //This method will show the User Interface
          frameEdit.document.execCommand('createlink', true, null);
        }
        function doLink2()
        {
         //This method will not show any user interface
         //But we are providing the value of third parameter manually
         frameEdit.document.execCommand('createlink', false, 'http://msdn.microsoft.com');
        }
    </Script>
    </Head>
    <Body onLoad="frameEdit.document.designMode='on';">
        <form id="frmEdit">
            <IFRAME id="frameEdit" style="width:600px; height:300px" align=center>
            </IFRAME>
            <br>
            <P align=center>
                <Input type="Button" value="Link 1 User Interface" onClick="doLink1()">            
<Input type="Button" value="Link 2 No User Interface" onClick="doLink2()">
            </P>            
       </form>
    </Body>
</HTML>

When you will run this example, you will see something like this

This interface was provided to you when you passed true as second parameter of execCommand. This is the Explorer's own user interface. Note that not all commands support user interfaces, only those which needs it. Like, if you pass true for user interface with bold command, then no user interface will be provided. Actually, this parameter will be ignored because doing bold, italic or underlined do not require any user interface.

When you will click on the second button (Link 2 No User Interface) then no user interface will be provided but still the Link will be created. If you see at the code, then you will note one thing that we have passed third parameter to the link location. Let's discuss the third parameter.

Value (Third Parameter)

Value parameter is passed to send some value to execCommand method in only those cases if the execCommand needs some value and user interface parameter was set to false. As in our above example, we used second button (Link 2 No User Interface). If you see the code working behind this button, then you will see that we passed command createlink, same as first buttons command, User Interface to false, and value to the URL of the MSDN site. Since we said the execCommand is to create some link, it must be aware of the location or URL which should be used to create link. Now we had two options, either prompt from user or hard code it (manual). So, if we want to manually set the value, then we can pass false for the user interface and some value (URL) as the value parameter.

So, that was all about the execCommand method. If you have understand what I said above then there should be no hurdle to make your own HTML Area using HTML and JavaScript. Just create buttons and execute the appropriate commands against each button. I have attached the HTML version of my TextArea too with this article. Now let's move to our real task, the HTML Text area Server Side Control.

Moving to Server Side Control for ASP .NET

Now let's see that how can we create the Server Side control for our text area. The Server Side controls of ASP .NET are very easy to build and require no permission or attention of user to be downloaded. Since the Server Side controls of .NET generates equivalent HTML code which is sent to the requested user’s browser.

To create our Server Side Control, just start your VS .NET and select new project and from project type, select Web Control Library from the Project templates of Visual Basic. In the name portion of project, set the name to RTFBox. When new project will be created, it will have one module with some code which is needed for the Server Side Control. For the moment, delete all the code and only leave the following.

Imports System.ComponentModel
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Xml
Imports System.Drawing
Imports System.Windows.Forms.Design
Imports System
Imports System.IO
Imports System.Web

Imports System.Drawing.Design


Namespace HangamaHouse
    Public Class RTFBox
     Inherits System.Web.UI.WebControls.WebControl
     
    End Class
End Namespace

OK, Now Create Some private methods which will return us the HTML code of our control. Your methods will be look like this.

Private Function GenerateCSSCode() As String
   Dim mCSS As String
   mCSS = vbCrLf
   mCSS = "<STYLE> " & vbCrLf
   mCSS += ".EditControl { " & vbCrLf
   mCSS += "width:" & Me.mWidth & "px; " & vbCrLf
   mCSS += "height:300px; } " & vbCrLf
   mCSS += ".tblTable { " & vbCrLf
   mCSS += "width : " & Me.mWidth & "px; " & vbCrLf
   mCSS += "height: 30px; " & vbCrLf
   mCSS += "border:0; " & vbCrLf
   mCSS += "cellspacing:0; " & vbCrLf
   mCSS += "cellpadding:0; " & vbCrLf
   mCSS += "background-color: #D6D3CE ; " & vbCrLf
   mCSS += " } " & vbCrLf
   mCSS += ".butClass { " & vbCrLf
   mCSS += "width:22; " & vbCrLf
   mCSS += "height:22; " & vbCrLf
   mCSS += "border: 0px solid; " & vbCrLf
   mCSS += "border-color: #D6D3CE ; " & vbCrLf
   mCSS += "background-color: #D6D3CE ; " & vbCrLf
   mCSS += " } " & vbCrLf
   mCSS += ".tdClass { " & vbCrLf
   mCSS += "padding-left: 0px; " & vbCrLf
   mCSS += "padding-top:0px; " & vbCrLf
   mCSS += "background-color: #D6D3CE ; " & vbCrLf
   mCSS += "</STYLE>" & vbCrLf
   Return (mCSS & vbCrLf)
End Function

This function will return us the Style Sheet for our text area. In the same way, we will create other functions which will return us the HTML code of creating toolbars and IFrame, Java Script which will handle the formatting of HTML in IFrame (using execCommand) and others. I am not writing the complete code here, just telling that how design the project. You can see the sample attached with this article.

When you finish writing all functions which returns the strings to send to client in order to create an HTML document looking like the picture at the top, there is the time to write code which will be responsible for sending code to client.

If you are writing a Server Side control which may send some output to User's browser, then in that control normally you write code in Overrides function Render. But in our case, we also have to send the JavaScript to the client browser, so first we will register our JavaScript to the browser and then we will send our normal HTML using the Render overridden function. So, to register your script you will probably write the code in OnPreRender Orverrides functions. Your code may look like this

Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
  'Register Style Sheet for our HTML area
  Page.RegisterClientScriptBlock("myStyleSheetScript", Me.GenerateCSSCode())
  'Register main Function which will deal with execCommand
  Page.RegisterClientScriptBlock("myCommandScript", Me.GenerateCommandScript())
  'Register Script which will handle with the code when button(s) is down
  Page.RegisterClientScriptBlock("mySelUpDownScript", Me.GenerateSelDown_UpScript())
  'Register Script which will handle with the code when mouse is away from the button(s)       
  Page.RegisterClientScriptBlock("myselOFFScript", Me.GenerateSelOFFScript())
  'Register Script which will handle with the code when mouse is on from the button(s)              
  Page.RegisterClientScriptBlock("myselONScript", Me.GenerateSelONScript())
End Sub

RegisterClientScriptBlock method of Page object takes two arguments, as in the above code. One the unique key of the script, and other is the script itself. Key is used to check that either the script is already registered or not, if it is registered already, then it is not sent to the client. The good way is that we first check either the script is registered or not. This method will also send all the script to the client browser. Note that we have to completely describe our script including <Script> tag.

When our script is sent to client, then we need to send actual HTML code which will produce interface of our HTML area. This code will be sent using OnRender overrides function.

        
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)            
writer.Write(Me.GenerateHTMLAreaBody)
       'Convert the Simple IFrame to Editable TextBox
        writer.RenderBeginTag("Script")
        writer.Write("RTFEdit_" & Me.UniqueID & ".document.designMode='on';")
        'writer.Write("RTFEdit_" & Me.UniqueID & ".document.body.innerText = '" & _
                      Text & "'")
        writer.RenderEndTag()
        'End Converting IFrame to Editable Textbox
End Sub

As we saw in our first example that we need to say to our browser that it should on the design Mode of IFrame. So, we the code for this work is sent to client here. RenderBeginTag method of HtmlTextWrite class takes responsibility to write some tag to the client output stream. We just passed the name of the tag, script in this case. Then we used the write method to write the contents of the tag, and then we called RenderEndTag. RenderEndTag will automatically close the last opened tag (script in this case). Note that we sent this code as the last output of our control. Because, when this code will be sent to client, it will look for the object we mentioned here. If we send this code before sending HTML of out document, then the client browser will generate error by saying something like object not found etc.

Don't confuse for Me.UniqueID, this will be discussed in the last section Managing View State.

Up to here our server side control is complete. Just compile it and it will create a DLL of the same name as your project name was. Now is the time to use our control in any ASP .NET page. Let's see the output of this control and then we will be back to our control to discuss some more things about this control.

Create Test Page for out Control

Open the note pad and write the following code there.

 <%@ Page Language="VB" %>
<%@ Register TagPrefix="mArea" Assembly="RTFBox" namespace="HangamaHouse" %>
<html><Head>
  <Title>Testing HTML Area Server Side Control</Title>
  </Head>
  <Bod>
  <Form id="Form1" Runat="server">
  <h1 align=center>HTML Text Area Demo</h1>
  <mArea:RTFBox Runat="server" />
  </Form>
  </Body>
  </html>

Save this code naming it test.aspx and save to some folder. Copy your compiled DLL file of Server Side Control in the folder named Bin. Note that the Bin Folder should be inside the folder of that where you saved your test.aspx. Make this folder a virtual folder. And type the URL in the browser. You will see the following output there.

Hey, the text you are seeing in the HTML area is written by me manually. Don't confuse if you do not see this in your browser. (Ok ok, I know you are very intelligent. just kidding). Anyway, we have seen our Server Side Control in work. Now let's move back to discuss something more which was used in out HTML Area Sever Control.

Color Management of Server Side Control

This control has the properties which can be used to set the color of HTML Area according to the colors of your site. As you can see in the picture at the start of this article and in the picture just above. Actually, the Colors are set in the Style Sheet we generated using GenerateCSSCode function (private function, user created). I simply created a property which is used to set or get the color of different portions of the HTML area, like Table Background. The type of the Color property is Color. But we know that HTML does not understand the Color object type. So, Microsoft was intelligent and he provided a method to convert Color Object to HTML Color string and vice versa. Well, I used ColorTranslator.FromHtml("#D6D3CE") to Convert HTML Color #D6D3CE to the equivalent color for Color object and in the same way, ColorTranslator.ToHtml(Color.Red) to convert Color Object value to HTML equivalent color string.

Managing View State of HTML Area Control

The final topic of this article is to demonstrate the View State handling for our Server Side Control. View state keeps the value of the form objects even when they are posted to the server. The major problem in implementing view state for our control is that MSDN clearly defines that only specific HTML controls can have view state which includes CheckBox, CheckBoxList, DropDownList, HTMLInputCheckBox, HTMLInputFile, HTMLInputHidden, HTMLInputImage, HTMLInputRadioButton, HTMLInputText, HTMLInputSelect, HTMLInputTextArea, ImageButton, ListBox, RadioButtonList and TextBox. IFrame is not included in these elements and it can not support View State. So what I did, that I got a hidden field and moved all text from IFrame to that hidden field. Then I implemented View state on that hidden field. It worked. So, let's see first that how I did that.

When User interface for HTML Area Server Side control is written to client, then with IFrame I also sent the code for a hidden field. That looks like this in the HTML generation code.

' Code before this for HTML Interface
 mStr += " <IFrame name=RTFEdit_" & Me.UniqueID & " ID=RTFEdit_" & _
      Me.UniqueID & " class=""EditControl"" ></IFrame>" & vbCrLf
 mStr += " <Input type=""hidden"" name=" & Me.UniqueID & " ID=" & _
      Me.UniqueID & " value='" & Text & "' >" & vbCrLf
'Code after this for HTML Interface

Note that the Value property of input type=hidden is Text. Text is the public property we created above and will be discussed soon. When this code is sent to the client, it will generate an IFrame and a Hidden field. I also transferred text from IFrame to this hidden field. The code for this is in the GeneratePostBackScript function. You should also note that the name of this hidden field is the Me.UniqueID. UniqueID is the property of every server control which returns the Unique ID for that control. If you hard code some name here, then it may conflict with other instance of the same control on the client. UniqueID makes it possible to have different IDs of each control on the client side. And it is also used for the View State Management. Now let's discuss something about the View State.

To implement the View State, we must have to implement the IPostBackDataHandler Interface. To implement the View State, I just implemented this Interface and also wrote some code for two functions of this Interface. But first of all, let we create a property named Text which should return us the Text (HTML) of our Control.

Public Property Text() As String
   Get                
      Return CType(Me.ViewState("Text"), String)
   End Get
   Set(ByVal Value As String)
      Value = Replace(Value, "\", "&#92")       
      '\ is a Special Character, Replace with \\
      Value = Replace(Value, "'", "&#146")       
      ' ' is cause of Error, replace with \' 
      Value = Replace(Value, vbCrLf, " ")
      Me.ViewState("Text") = Value
   End Set
End Property

Text Property retuns some String from the View State's collection. And when we need to set the value, it also set that in the ViewState collection. But before setting it to view state collection, it format's the value passed to it. It converts \ to equivalent HTML code &#92 since we are using JavaScript and in JavaScript \ indicates that we are going to write some special character. In the same way, single quote (') and new line (carriage return) is also converted to fit into JavaScript.

Now come to the implementation of IPostBackDataHandler interface. Here is the code.

Public Event TextChanged As EventHandler

Public Function LoadPostData(ByVal postDataKey As String, 
                             ByVal postCollection As 
                             System.Collections.Specialized.NameValueCollection) 
                             As Boolean 
                             Implements System.Web.UI.IPostBackDataHandler.LoadPostData
 Dim currentValue As String = Text
 Dim postedValue As String = postCollection(postDataKey)
 If currentValue Is Nothing Or Not postedValue.Equals(currentValue) Then
     Text = postedValue                
     Return True
 End If
     Return False
End Function
Public Sub RaisePostDataChangedEvent() 
   Implements System.Web.UI.IPostBackDataHandler.RaisePostDataChangedEvent
   OnTextChanged(EventArgs.Empty)
End Sub
Protected Overridable Sub OnTextChanged(ByVal e As EventArgs)
   RaiseEvent TextChanged(Me, e)
End Sub

We first declared an Event. Then we implemented the Interface's Functions/Methods. First Function is LoadPostData which is responsible for, as the name says, loading Posted data. It has two arguments, key and a data collection. We received the value from that collection to a variable postedValue and then checked if that is not equal to our previous value or nothing (null), then pass it to our Text property. Else wise just return false and exit.

The Second Method RaisePostDataChangedEvent, is used to raise events for our custom control, if we want to. We simply called the OnTextChanged overrideable method and in that method, we raised our event. We didn't raise our event in the RaisePostDataChangedEvent method, but in OnTextChanged method, so that if someone would like to override this method, so he can.

This was all about the creation of HTML area as a Server Side Control. There are some functions to be provided in it like the Special Characters. If you feel that some improvement should be made in this control, then let me know. If in any case, you are facing some problem in understanding code or else, then you can write me at theangrycoder@yahoo.com. Your comments and suggestions will be welcomed.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here