Inloggen
 
 
 
 
    
Localization in ASP.NET 2.0 using a database and adapters, part 2
Location: BlogsFerry Onderwater - Developer    
Posted by: Ferry Onderwater 30-4-2007 20:07
In a previous blog we made a page localized without changing any existing code by using a database and controladapters. Now we will take a next step and localize a control which is a little more complex than a label, a dropdownlist.
The following code enhances the code from the blog I wrote a few days ago about controladapters and using them for localization.
Now it can localize a more 'difficult' control, a dropdownlist.
Why is this more difficult? In the label-control we just write text in the render-method. A dropdownlist however contains multiple 'options' in the HTML-select. We don't want to translate the whole control but only the text-attributes from the options.

In the previous code we inherited from System.Web.UI.Adapters.ControlAdapter. This class, however, doesn't give us all the necessary methods. So we are going to inherit from System.Web.UI.WebControls.Adapters.WebControlAdapter.
One of the differences is the RenderContents-method.

Let's code:

Code:
Imports System
Imports System.Data
Imports System.Configuration
Imports System.IO
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Namespace Arcencus
    Public Class DropDownListAdapter
        Inherits System.Web.UI.WebControls.Adapters.WebControlAdapter

        Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
            RenderBeginTag(writer)
            RenderContents(writer)
            RenderEndTag(writer)
        End Sub

        Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter)
            If TypeOf Control Is DropDownList Then
                Dim ddl As DropDownList = CType(Control, DropDownList)
                For Each li As ListItem In ddl.Items
                    writer.WriteBeginTag("option")
                    If li.Selected Then writer.WriteAttribute("selected", "selected")
                    writer.WriteAttribute("value", li.Value)

                    'Add style if necessary
                    writer.WriteAttribute("style", li.Attributes("style"))

                    writer.Write(">")
                    HttpUtility.HtmlEncode(GetTerm(li.Text, li.Value, HttpContext.Current.Session("Culture")), writer)
                    writer.WriteEndTag("option")
                    writer.WriteLine()

                Next
            Else
                MyBase.Render(writer)
            End If
        End Sub

        Private Function GetTerm(ByVal Text As String, ByVal Value As String, ByVal Culture As String) As String
            Dim sconn As New SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("GlobalizationConnectionString").ConnectionString)
            Dim scomm As New SqlClient.SqlCommand("SELECT TOP 1 Text FROM Terms WHERE Value = @Value AND Culture = @Culture", sconn)
            With scomm.Parameters
                .AddWithValue("@Value", Value)
                .AddWithValue("@Culture", Culture)
            End With
            Dim _result As String
            sconn.Open()
            _result = scomm.ExecuteScalar
            sconn.Close()
            Return IIf(String.IsNullOrEmpty(_result), Text, _result)
        End Function
    End Class
End Namespace


You see the function to get the translated text has slightly changed. It takes both the text ánd the value as a parameter. When no result is found it returns the original text.

In the render-method we call three other methods. The first and the last are of no concern for us now so we'll just call them. In the 'middle' method, RenderContents, we use 'the control'. By casting the control as a dropdownlist we can loop through all it's items.
But instead of calling the base render-method we will render it ourself.
The code is quite self-explaining, we write the 'option' tag with some properties, write the translated text and end the tag.

But, If we run this code and change the selected item in the dropdownlist an exception is thrown:

Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.

We can solve this by following the instructions in the error but since we are trying to implement localization without changing the original code (see first blog) our only option would be to set 'enableEventValidation=false' in web.config. But by doing that alle event validation in the whole app will be disabled.

So we are solving this the official way, we register the necessary objects. This is done by adding two pieces of (almost similar) code:

Code:
Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter)
    If TypeOf Control Is DropDownList Then
        Dim ddl As DropDownList = CType(Control, DropDownList)
        For Each li As ListItem In ddl.Items
            writer.WriteBeginTag("option")
            If li.Selected Then writer.WriteAttribute("selected", "selected")
            writer.WriteAttribute("value", li.Value)

            'Add style if necessary
            writer.WriteAttribute("style", li.Attributes("style"))

            writer.Write(">")
            HttpUtility.HtmlEncode(GetTerm(li.Text, li.Value, HttpContext.Current.Session("Culture")), writer)
            writer.WriteEndTag("option")
            writer.WriteLine()
            If Me.Page IsNot Nothing Then
                Page.ClientScript.RegisterForEventValidation(ddl.UniqueID, li.Value)
            End If
        Next
        If Me.Page IsNot Nothing Then
            Page.ClientScript.RegisterForEventValidation(ddl.UniqueID)
        End If
    Else
        MyBase.Render(writer)
    End If
End Sub


The code we have added registers the dropdownlist ánd the options for event validation.

And voila, we have a 'self-localizing' dropdownlist.

Have fun!

Ferry

Complete project for downloading
Copyright ©2007 Ferry Onderwater
Permalink |  Trackback

Comments (1)  
Betr: Localization in ASP.NET 2.0 using a database and adapters, part 2    By Ferry on 14-5-2007 16:15
You will run into some problems when trying to use this code in an Ajax-enabled site. One solution is to replace all the adapters with one adapter for the Page-control and within the Page control looping throught the child-controls and translate whatever you want.

  
 
Weblogs
    
Archief
    
Zoeken
    
 
 
 
 
Copyright 2006-2009 by Arcencus
Privacy Statement | Terms Of Use