| |
| Localization in ASP.NET 2.0 using a database and adapters, part 2
|
|
|
Location: Blogs Ferry 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. |
|
|
|
|
|
|
|
|
|