Get the Most Out of Windows Forms Controls

Create Rich User Interfaces by Injecting Windows Forms Controls into Your ASP.NET Web Pages

ControlFreak

LANGUAGES: VB.NET | C#

ASP.NET VERSIONS: 1.x

 

Get the Most Out of Windows Forms Controls

Create Rich User Interfaces by Injecting Windows Forms Controls into Your ASP.NET Web Pages

 

By Steve C. Orr

 

Developers love Web applications because they are easier to deploy than Windows applications. But developers love Windows applications because functionally rich user interfaces can be created rapidly. Wouldn t it be nice to have the best of both worlds? In this article I ll show you how you can have your cake and eat it too by supercharging your ASP.NET Web pages with Windows Forms controls.

 

Why Use Windows Forms Controls?

There are many examples of things that can be done easily with Windows Forms controls that would be difficult or impossible with Web controls alone. For example, there is no Web control that provides the rich functionality of the Windows Forms ComboBox control. So what s to stop a developer from using the ComboBox control on their Web forms? Not much, as will be demonstrated shortly. The custom ComboBox control defined in this article can even fetch its own data from a Web service.

 

How about interactive images that can constantly redraw and keep themselves up do date? The Bar Graph custom Windows control detailed later in this article will demonstrate a mesmerizing animated bar chart that can redraw itself based on user input without having to call back to the server.

 

Browser and .NET Framework Detection

Every user will need two things to successfully consume Windows Forms controls in a Web page: Internet Explorer and the .NET Framework. These requirements shouldn t be hard to meet these days, but there will sometimes be a minority of users who don t meet the requirements. Luckily, as a developer, you can help them find their way. A few lines of code are all it takes to verify the user has Internet Explorer and the .NET Framework installed; if they don t, you can redirect them to an alternate page or guide them toward a solution:

 

Dim msg As String

If Request.Browser.Browser.ToUpper().IndexOf("IE") >= 0 Then

 If Request.Browser.ClrVersion.Major > 0 Then

   Msg ="Your browser is good and powerful."

 Else

   msg ="Get the .NET Framework from www.WindowsUpdate.com"

 End If

Else

 Response.Write("This page requires Internet Explorer.")

End If

Response.Write(msg)

 

The Request.Browser property contains information about the user s Web browser. In this example, searching for the string IE confirms the user is running Internet Explorer.

 

The Request.Browser.ClrVersion property contains detailed version information for the most up-to-date version of the .NET Framework that s installed on the user s machine. The Major property will be zero if the user doesn t have any version of the .NET Framework installed. The GetClrVersions method (not shown) will return an array of all the versions of the .NET Framework that are installed on the user s machine (in case you need such detailed information). In the vast majority of cases, that level of detail shouldn t be necessary, but it s nice to know it s there.

 

The Basics

To embed a custom Windows control in a Web page, you ll need an HTML snippet such as this:

 

classid="http:MyCustom.dll#MyNamespace.MyClassName">

     

     You have an unsupported browser.

 

A special technique is used to overload the ClassID attribute so all the necessary information can be specified to launch the .NET component. The ClassID must start with http: , which must be followed by the name of the DLL containing the .NET component. This DLL must reside in the Web application s root directory. After the DLL name there must be a pound sign (#), followed by the full name of the component (namespace included).

 

tags can be used to declaratively set properties of the control. In the previous example, the BackColor property of the control is set to yellow. Client-side script can also be used to call properties and methods of the custom .NET Windows control, as will be demonstrated later in the article.

 

The unsupported browser text will only appear in cases where the message is true.

 

A Basic ComboBox

Using the technique just described, it s not possible to refer to any components that reside in the GAC, and, therefore, it s impossible to refer directly to a standard Windows control. It is possible to use standard Windows controls in your Web pages, but they must be encapsulated within a custom assembly that can be referred to with the precise HTML syntax previously listed. It s not difficult.

 

For example, compile this simple class into a new Windows Control Library using Visual Studio:

 

Public Class MyComboBox

   Inherits System.Windows.Forms.ComboBox

End Class

 

Add the resulting control to a Web page using the earlier HTML snippet syntax and you re good to go. Don t forget to place the control s resulting DLL in the Web application s root directory, or else it won t be downloaded to the user s computer.

 

An Enhanced ComboBox

A ComboBox isn t very useful unless you can get data into and out of it. The above ComboBox control will be enhanced to retrieve its own data from a Web service.

 

After setting a reference to a local Web service that returns a DataSet, this improved ComboBox control calls the Web service back on its home server and fills itself with the resulting data (see Figure 1).

 

Public Class ComboBox

 Inherits System.Windows.Forms.ComboBox

 Public Sub New()

   MyBase.New()

   'Fetch data from a web service and fill the ComboBox

   Dim ws As New MyWebService.MyDataSource

   For Each dr As DataRow In ws.GetDataSet.Tables(0).Rows

      Items.Add(dr(0).ToString)

   Next

 End Sub

End Class

Figure 1: Intended to be hosted within a Web page, this customized Windows ComboBox control retrieves its own data from a Web service.

 

This control inherits from the standard Windows Forms ComboBox control, thereby getting all its functionality. It then extends the standard functionality by calling a Web service from within the constructor. Finally, it loops through the records and adds them to the Items collection of the ComboBox. Figure 2 shows it in action.

 


Figure 2: Don t be discouraged by the fact that there s no ComboBox Web control in ASP.NET. The Windows Forms ComboBox control can be used in Web applications.

 

To retrieve the value the user selects in the ComboBox, an OnSubmit attribute is added to the HTML Form tag. Using a line of JavaScript, the ComboBox value is placed into an HTML HiddenTextBox control just before the page is submitted back to the server:

 

onsubmit="document.forms[0].HiddenTextBox1.value =

 document.forms[0].ComboBox1.Text;"

 

Because that HiddenTextBox is marked with the runat= Server attribute, the value can be easily retrieved from server-side code:

 

Response.Write("You chose " + HiddenTextBox1.Value)

 

An Animated Bar Graph Control

The bar graph shown in Figure 3 is another example of a custom Windows Forms control that doesn t need to post back to the server. In fact, there is no server-side code needed at all for this page, as you can see by the plain HTML page listed in Figure 4.

 


Figure 3: It would be difficult if not impossible to implement such a rich, animated bar graph as this with HTML and JavaScript alone. Windows Forms controls are simply better at many tasks than Web controls.

 

 BarTest

 

 

   classid="http:ControlFreak.dll#ControlFreak.BarGraph"

   name="WinWebBarGraph1" VIEWASTEXT>

 

 

   

September:

      name="txtSep">

October:

      name="txtOct">

November:

      name="txtNov">

December:

      name="txtDec">

 

 

Figure 4: Windows controls can be embedded in plain HTML pages, with no server-side required. In this example, client-side JavaScript is used to call methods of the Windows control that are hosted within the browser.

 

Just after the beginning tag you can see the tag, with syntax matching the description at the beginning of this article. The Backcolor property is set to light blue via a tag. After that, a few textboxes are followed by a few buttons. Finally there is a block of JavaScript that sets initial values for the bar graph control and tells the control to begin its colorful animation cycle.

 

The final graphbutton_onclick JavaScript function operates similarly when one of the buttons is clicked, setting the bar graph values to match the user s input. The bar graph control is capable of two different kinds of animation, as well as a static (non-animated) layout. There is an HTML button on the form matching each animation style. All three buttons call this client-side JavaScript function, which clears the old bar values, adds new bars with sizes that match the user-entered values, and sets the animation style according to the user s command.

 

Internally, the BarGraph control contains a collection of Bar objects. The Bar class is nothing very fancy; basically, it s just a container to hold a few values. The Bar class is defined in Figure 5.

 

Public Class cBar

   Public Sub New(ByVal Text As String, _

       ByVal Value As Double)

       _text = Text

       _Value = Value

   End Sub

   Dim _text As String = String.Empty

   Public Property Text() As String

       Get

           Return _text

       End Get

       Set(ByVal Value As String)

           _text = Value

       End Set

   End Property

    Dim _Value As Double = 0

   Public Property Value() As Double

       Get

           Return _Value

       End Get

       Set(ByVal Val As Double)

           _Value = Val

       End Set

   End Property

End Class

Figure 5: A bar object is instantiated for each bar in the BarGraph control.

 

What s more interesting is the code for the actual BarGraph control. The basic drawing method for this control is listed in Figure 6. This function is for drawing the static (non-animated) version of the BarGraph control.

 

Public Sub DrawBars()

 Timer1.Enabled = False

 'initialize a drawing surface

 Dim objBitmap As Bitmap = New Bitmap(Me.Width, Me.Height)

 Dim objGraphics As Graphics = _

    Graphics.FromImage(objBitmap)

 objGraphics.FillRectangle(New SolidBrush(Me.BackColor), _

     0, 0, Me.Width, Me.Height)

 'loop through and draw each bar

 Dim iCount As Integer = 0

 For Each Bar As cBar In _Bars

     'determine the bar dimensions

     Dim Width As Single = _

         Convert.ToSingle(Me.Width / _Bars.Count - 20)

     Dim BarHeightPercent As Integer = _

         Convert.ToInt32(Bar.Value / _Bars.MaxValue * 100)

     Dim BarHeight As Single = _

         Convert.ToSingle(BarHeightPercent _

         / 100 * Me.Height - 20)

     Dim rect As New RectangleF(iCount * Width + 20 _

         * iCount + 10, (Me.Height - 10) - BarHeight, _

         Width, BarHeight - 10)

     'specify the bar colors

     Dim Color1 As Color = Color.Green

     Dim Color2 As Color = Color.Blue

     'draw the bar

      objGraphics.FillRectangle(New _

       Drawing2D.LinearGradientBrush(rect, Color1, Color2, _

       Drawing2D.LinearGradientMode.ForwardDiagonal), rect)

     'Draw the text

     Dim drawFont As New Font("Arial Narrow", 10)

     Dim drawPoint As New PointF(rect.X, rect.Y + _

        rect.Height + 1)

     Dim drawBrush As New SolidBrush(Color.Black)

     objGraphics.DrawString(Bar.Text, drawFont, _

        drawBrush, drawPoint)

     'Draw the value

     drawPoint = New PointF(rect.X, rect.Y - 14)

     objGraphics.DrawString(Bar.Value.ToString, _

         drawFont, drawBrush, drawPoint)

     iCount += 1

 Next

 Me.BackgroundImage = objBitmap

 _DisplayStyle = DisplayStyleEnum.NonAnimated

End Sub

Figure 6: The DrawBars method of the BarGraph control loops through each bar and draws them along with their associated text.

 

First, the internal timer is disabled because it s used only for the animation functions. Then the drawing surface is initialized and is filled with the specified background color. The code then loops through each Bar object in the Bars collection. The bar dimensions are then calculated and the two bar colors are chosen before each rectangular bar is drawn with a gradient brush. The bar text is drawn just below the bar, and the bar value is drawn just above the bar.

 

Finally, the completed in-memory image is assigned to be the background image of the control, which causes it to appear. Keep in mind that all this code is being executed by the .NET Framework on the user s machine and the output is displayed in the user s browser.

 

A similar function is shown in Figure 7. This function is called each time the encapsulated timer ticks, rapidly redrawing the bars with random colors and gradient modes.

 

Public Sub DrawBarsAnimatedRandom()

 Dim rdm As Random = New Random

 'initialize a drawing surface

 Dim objBitmap As Bitmap = New Bitmap(Me.Width, Me.Height)

 Dim objGraphics As Graphics = _

   Graphics.FromImage(objBitmap)

   objGraphics.FillRectangle(New SolidBrush(Me.BackColor), _

   0, 0, Me.Width, Me.Height)

 'loop through and draw each bar

 Dim iCount As Integer = 0

 For Each Bar As cBar In _Bars

   'determine the bar dimensions

   Dim Width As Single = Convert.ToSingle(Me.Width / _

     _Bars.Count - 20)

   Dim BarHeightPercent As Integer = _

     Convert.ToInt32(Bar.Value / _Bars.MaxValue * 100)

   Dim BarHeight As Single = _

     Convert.ToSingle(BarHeightPercent / 100 _

     * Me.Height - 20)

   Dim rect As New RectangleF(iCount * Width + 20 _

     * iCount + 10, (Me.Height - 10) - BarHeight, _

     Width, BarHeight - 10)

   'determine the bar's colors randomly

   Dim Color1 As Color = Color.FromArgb(rdm.Next(0, 255), _

     rdm.Next(0, 255), rdm.Next(0, 255))

   Dim Color2 As Color = Color.FromArgb(rdm.Next(0, 255), _

     rdm.Next(0, 255), rdm.Next(0, 255))

   'random gradient style

   Dim ldb As Drawing2D.LinearGradientMode

   Select Case rdm.Next(0, 3)

     Case 0

       ldb =Drawing2D.LinearGradientMode.BackwardDiagonal

     Case 1

       ldb = Drawing2D.LinearGradientMode.ForwardDiagonal

     Case 2

       ldb = Drawing2D.LinearGradientMode.Horizontal

     Case 3

       ldb = Drawing2D.LinearGradientMode.Vertical

   End Select

   'draw the bar

   objGraphics.FillRectangle(New _

       Drawing2D.LinearGradientBrush(rect, _

       Color1, Color2, ldb), rect)

   'Draw the text

   Dim drawFont As New Font("Arial Narrow", 10)

   Dim drawPoint As New PointF(rect.X, rect.Y + _

       rect.Height + 1)

   Dim drawBrush As New SolidBrush(Color.Black)

   objGraphics.DrawString(Bar.Text, drawFont, _

       drawBrush, drawPoint)

   'Draw the value

   drawPoint = New PointF(rect.X, rect.Y - 14)

   objGraphics.DrawString(Bar.Value.ToString, _

       drawFont, drawBrush, drawPoint)

   iCount += 1

 Next

 Me.BackgroundImage = objBitmap

 _DisplayStyle = DisplayStyleEnum.AnimatedRandom

 Timer1.Enabled = True

End Sub

Figure 7: The System.Random class is used extensively in this alternate version of the DrawBars method to create an alluring animation of random, pulsating colors.

 

The general structure of this method is essentially the same as the DrawBars method. It starts by initializing a drawing surface and filling it with the specified background color. Looping through each bar, the same calculations are used to determine the bar dimensions. Then things start to diverge a bit. A random gradient mode is chosen; the gradient colors are chosen randomly, as well. Then, as in the DrawBars function, the text values are drawn and the function finishes by assigning the image to be the background image of the control. A client-side timer is enabled, ensuring that this function will be called again shortly so that the next frame of the animation can be drawn.

 

The full source code for the BarGraph control contains another function named DrawBarsAnimatedSmooth (the full source code is available; see end of article for download details). This function is similar, but uses slightly different randomization algorithms for the drawing to create an alternate (but equally alluring) animation.

 

Limitations and Security Issues

Windows Forms controls are better than ActiveX controls from a security standpoint. Every Web-based ActiveX control comes with a security warning that users must accept or deny no matter what the control does. The control might be entirely harmless or it might maliciously reformat their hard drive. It s an all-or-nothing scenario, and if an uneducated user makes the wrong choice, there is no limit to the potential negative outcomes. Today, ActiveX controls are one of the primary sources of Spyware and Adware infections.

 

The .NET Framework provides a much more robust security system, improving upon Java s Sandbox methodology. To make decisions about whether the control is harmless or potentially dangerous it examines the kinds of functions that the control wants to use, evidence about the user, and application context. Potentially dangerous functions are blocked from execution, although educated users can make exceptions with the .NET Framework Wizard located under Control Panel | Administrative Tools.

 

The controls in this article contain no potentially dangerous function calls; therefore, they are automatically downloaded and run on the user s computer without any kind of warning or dialog box needing to appear at all.

 

What kinds of functions are considered potentially dangerous? Internet-based applications have the most restrictions, while intranet applications have somewhat more lenient boundaries. For example, all network calls are blocked for Internet applications except calls back to the originating application. The ComboBox control listed earlier in this article calls back to the same server from which the containing Web page is hosted. Calls to a different server would fail unless the user (or a custom installation program) explicitly grants the assembly the necessary permissions. This security is based on the URL, so http://localhost is considered different than http://192.168.0.1 even if both those URLs ultimately point to the same server. If you tinker with the ComboBox control from this article, make sure the browser s URL root matches the URL root of the Web service it is calling.

 

Access to the user s hard drive is also heavily restricted. Although isolated storage is available for temporary files, reading from other locations is strictly prohibited unless the user explicitly chooses a file through the permitted OpenFileDialog class.

 

Reflection and Serialization are also entirely prohibited. No XSL transformations are permitted, and ADO.NET access is limited. Calls to unmanaged code are prohibited, such as Windows API functions.

 

Another issue is that communication between client-side script and Windows controls is currently one-way only. That is, JavaScript functions within the page can call methods of the hosted Windows control, but the Windows control cannot raise events back to the page. This (hopefully temporarily) broken functionality is related to the current mix of patches for Windows, Internet Explorer, and the .NET Framework. Although this limitation is annoying, you should be familiar with such one-way communication because it is essentially a metaphor for HTTP communication. That is, Web browsers can make requests to Web servers, but Web servers cannot call directly to a Web browser without the Web browser initiating the conversation.

 

Unfortunately, all of these limitations rule out a lot of potentially useful applications, but most of these limitations are there for good reason so users can sleep more soundly at night (and so Microsoft won t catch so much heat about security problems!).

 

Despite the limitations, clearly there are many good uses for Windows Forms controls in Web applications, just a few of which have been demonstrated in this article.

 

C# and VB.NET sample code accompanying this article is available for download.

 

Steve C. Orr is an MCSD and a Microsoft MVP in ASP.NET. He s been developing software solutions for leading companies in the Seattle area for more than a decade. When he s not busy designing software systems or writing about them, he can often be found loitering at local user groups and habitually lurking in the ASP.NET newsgroup. Find out more about him at http://SteveOrr.net or e-mail him at mailto:[email protected].

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish