Archive for ◊ May, 2010 ◊

Author:
Monday, May 31st, 2010

Any Silverlight application which has reasonable Business logic will always uses either Web Services or WCF services. Inevitable we end up in a need to communicate any error or exceptions that occur in server to the Silverlight client so that it takes necessary actions for the user. 

This need is so common; ironically there is no simple straight forward way. One option is to have an attribute as part of every DataContracts and use this attribute to bubble the error messages to Client. But this is a crude way because many times we want to keep DataContracts simple like string or int or bool. 

And if we throw an exception at the server side it manifests at the client as 500 Not Found. 

Lets see how we can work around this problem.

W.r.t Silverlight 4, it is possible that the service is a RIA enabled WCF service.

So I will discuss 2 possibilities 1. Silverlight Enabled WCF service 2. RIA DomainService.

 

 1.      Silverlight Enabled WCF Service. 

In this scenario we can use FaultContracts.

Let’s say I have a business method which returns an Entity type. But before the call for business method I have to check whether the user is Authenticated or not. If he is not authenticated I have to tell the client to load appropriate screens for the user to login. The attribute FaultContract is specified for a business method.

 

[OperationContract]

[FaultContract(typeof(MyException))]

public IEnumerable<MyData> GetMydata()

        {           

             MyException fault = null;

             IEnumerable<MyData>  result = null;

             IEnumerable<vw_narrowcastpage_template> list = null;

             if (HttpContext.Current.User.Identity.IsAuthenticated)

             {

                 try

                 {

//Your Business Logic

                 }

                 catch (Exception ex)

                 {

                     fault = new MyException (ex);

                 }

             }

             else

             {

                 fault = new MyException (1, “Un Authenticated”);

             } 

             if (fault != null)

             {

                 WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;

                 throw new FaultException< MyException >(fault, new FaultReason(fault.MyMessage));

             }

 

            return result;

        }

 

Now in the above code,

  1. MyException is nothing but a small class which encapsulates important information regarding the fault.
  2. Specify the attribute FaultContract over the method.
  3. In case of un authenticated call, create an instance of Fault of generic type MyException and set the necessary values for the attributes of MyException.
  4. Notice that in case of Fault, I set Response status code to 200, Ok. This is to prevent the exception details to be again manifested due to some limitations of web browser’s stack.
  5. Finally throw the Fault Exception. Specify the Fault reason as well.

 

At the client,

When the async call to the method completes, in the completed event handler check is the event argument has Error. If so check if it is of type FaultException<MyException>. You can do the necessary actions henceforth. For Exception message can be retrieved using fault.Detail.MyMessage as shown below. 

if (e.Error != null)

            {

              if (e.Error is FaultException<MyException>)

              {

                    FaultException< MyException > fault = e.Error as FaultException< MyException >;

                    MessageBox.Show(fault.Detail.MyMessage);

                }

            }  

2.      With WCF RIA services it is much simpler. 

Let’s say I want to authenticate a User using Forms authentication.

The business method will return Boolean value. But in case of authentication failure I also want to communicate to the Client the exact reason for failure viz. Invalid User Name, Wrong password, User Locked or Not Approved.

  

All you can do is use the DomainException call to specify the exception details as follows. 

protected override bool ValidateUser(string userName, string password)

        {

            if (base.ValidateUser(userName, password))

                return true;

            else

            {                

                MembershipUser objUser = Membership.GetUser(userName);

                string exceptionMessage = string.Empty;

                if (objUser == null)

                {

                    exceptionMessage = “Invalid User Name.”;

                }

                else if (objUser.IsLockedOut)

                {

                    exceptionMessage = “User is Locked.”;

                }

                else if (!objUser.IsApproved)

                {

                    exceptionMessage = “User is not approved.”;

                }

                else

                {

                    exceptionMessage = “Incorrect Password.”;

                }

                DomainException d = new DomainException(exceptionMessage);

                throw d;               

            }

        }

Category: Silverlight  | One Comment
Author:
Monday, May 31st, 2010

Recently I was tasked with creating test data for a new project that we started. Creating large volumes of test data with all constraints and checks repeatedly with variations requires a well though through test data creation plan.

There were multiple options to go about creating test data.

  1. Find a third party tool to create test data.
  2. If tool doesn’t support your requirement, create a custom script to meet the requirement.
  3. A least preferred option, manually create insert scripts. 

Third party tools: 

There are some good tools available which can create valid test data based on your DB design and table constraints. Some tools even provide the flexibility to an extent where you can predefine the type of data, for e.g. first name will be populated with valid first names; SSN will be populated with proper formatting etc. 

I found Red Gates’ SQL Data Generator tool very useful in creating test data. Below screenshot illustrates various data selection fields available with this tool.  

Sample Data field values

Sample Data field values

Test Data creation Script:

If tools don’t help you, then your next best option is to pull your fingers out and write yourself a light weight data generator. This below code creates a one random record and inserts into the given table.

 

declare @select varchar(max), @insert varchar(max), @column varchar(100), 
    @type varchar(100), @identity bit, @db nvarchar(100) 
set @db = N'Orders' 
set @select = 'select ' 
set @insert = 'insert into ' + @db + ' (' 
 
declare crD cursor fast_forward for 
select column_name, data_type,  
COLUMNPROPERTY( 
    OBJECT_ID( 
       TABLE_SCHEMA + '.' + TABLE_NAME),  
    COLUMN_NAME, 'IsIdentity') AS COLUMN_ID 
from Northwind.INFORMATION_SCHEMA.COLUMNS 
where table_name = @db 
open crD 
fetch crD into @column, @type, @identity 
while @@fetch_status = 0 
begin 
if @identity = 0 or @identity is null 
begin 
    set @insert = @insert + @column + ', '  
    set @select = @select  +  
        case @type 
            when 'int' then '1' 
            when 'varchar' then '''test''' 
            when 'nvarchar' then '''test''' 
            when 'smalldatetime' then 'getdate()' 
            when 'bit' then '0' 
            else 'NULL' 
        end + ', '  
end 
fetch crD into @column, @type, @identity 
end  
set @select = left(@select, len(@select) - 1) 
set @insert = left(@insert, len(@insert) - 1) + ')' 
exec(@insert + @select) 
close crD 
deallocate crD 

Manual test data creation:  This is the least preferred option because it is time consuming and error prone. But, hey, if you have time and patience to manually creation thousands of records, go for it.

Category: Databases  | One Comment
Author:
Monday, May 31st, 2010

ASP.NET Web programming uses the http protocol which is stateless i . e after each time the page is posted to the server the state of the controls is lost.to overcome this , ASP.NET includes several options that help you preserve data on both a per-page basis and an application-wide basis. These features are as follows:

1) View state

2) Control state

3) Hidden fields

4) Cookies

5) Query strings

6) Application state

7) Session state

8 ) Profile Properties

View state, control state, hidden fields, cookies, and query strings all involve storing data on the client in various ways. However, application state, session state, and profile properties all store data in memory on the server. Each option has distinct advantages and disadvantages, depending on the scenario.

References:

http://msdn.microsoft.com/en-us/library/75x4ha6s.aspx

Author:
Monday, May 31st, 2010

There is a lot of debate on pair programming, its advantages, benefits and pitfalls.
I tried it my team on one of the critical project, I used this practice since I was going on vacation and there was no time for formal knowledge transfer and there were many issues that need to be addressed.
With this constraints peer programming seem to be an ideal candidate. I was fascinated by the result of it. The code written was almost bug free, every line of code was code reviewed then and there and comments updated.
There were so many creative ideas which flow in when you are discussing about the feature and also implementing it right away if it’s feasible.
It helped the other person to get the confidence and control over the project.
Another aspect of it was the quality time spent on the project increased by almost 30% and we were able to keep up the concentration level for the entire period.

Also remember that this will only work if there is good coordination and understanding between the team members else this leads to chaos.

Category: Agile/Scrum  | 2 Comments
Author:
Wednesday, May 26th, 2010

If you’re not aware of the Optional or Named Parameters feature introduced in C# 4.0, take a look at this video before reading this article:

http://msdn.microsoft.com/en-us/vcsharp/ee460905.aspx

The Good:

1) This features will certainly help you reduce the number of overloads for your methods.

2) The calls to the methods will be more reader friendly.
Eg. SetUserName(lastName: “Hello”, firstName: “World”); // the user will know which value goes into which parameter without having to look up the method signature.

3) Calls to a lot of COM APIs will now be simpler

The Bad:

1) When you compile a code that calls a method using named parameters, the parameter name used in the call is stored at callsite (i.e. in the assembly where the method is being called). If the method is actually defined in a different assembly (say a library dll that your other projects use), then this can have unindented side effects. Lets say you change one of the parameter names in your method and compiled your library dll and deployed it without compiling the other projects that use it. If the order and type of your parameters hasn’t changed you could still get by, cos the caller simply calls the methods as they did in earlier versions of C#. The named parameter call is only for the benefit of the reader. However, if the type or order of the parameters have changed the you are in trouble. You’ll have to recompile all the projects that use your library to reflect this change.

2) Another, and more serious side effect would be when you are using optional parameters. The values of optional parameters are also stored on the callsite. Hence if you change the default value of any parameter in your library dll and deploy it without recompiling the projects that use it, then your method will continue to get the old default values! This could lead to some bugs.

The Learning:

Although this new feature is pretty useful, developers should be aware of these side effects. Think of parameter names and the default values as a part of your public interface, just like the name of your method. That will make you think hard before changing parameter names or default values.

Author:
Tuesday, May 25th, 2010

Deleting the indexes (Primarykey and foriegnkey) from MySql InnoDB

When we try to delete the foreign key index from the innodb table

(ALTER TABLE `<DBNAME>`.`<TABLENAME>` DROP INDEX `<INDEXNAME>`;)

it will through below error

“Error on rename of ‘.\<DBNAME>\#sql-1410_4′ to ‘.\<DBNAME>\<TABLENAME>’ (errno: 150)”

It’s because we are trying to delete the index before deleting the foreign key. So first we need to drop foreign key and then index.

EX:

ALTER TABLE <TABLENAME> DROP FOREIGN KEY `<INDEXNAME>`;
ALTER TABLE <TABLENAME> DROP INDEX `<INDEXNAME>`;

Similarly when we try to delete primay key

(ALTER TABLE `<DBNAME>`.`<TABLENAME>` DROP INDEX `PRIMARY`;)

It will through the below error

“Incorrect table definition; there can be only one auto column and it must be defined as a key”

Before deleting primary key we need to delete auto increment for the field

EX:

ALTER TABLE <TABLENAME> CHANGE `<FIELDNAME>` `<FIELDNAME>` INT(11) NOT NULL;
ALTER TABLE <TABLENAME> DROP INDEX `PRIMARY`;

Author:
Tuesday, May 25th, 2010

Data warehouse architecture is primarily based on the business processes of a business enterprise taking into consideration the data consolidation across the business enterprise with adequate security, data modeling and organization, extent of query requirements, meta data management and application, warehouse staging area planning for optimum bandwidth utilization and full technology implementation.

The Data Warehouse Architecture includes many facets. Some of these are listed as follows:

Process Architecture

Describes the number of stages and how data is processed to convert raw / transactional data into information for end user usage.

The data staging process includes three main areas of concerns or sub- processes for planning data warehouse architecture namely €œExtract€, €œTransform€ and €œLoad€.

These interrelated sub-processes are sometimes referred to as an €œETL€ process.

1) Extract- Since data for the data warehouse can come from different sources and may be of different types, the plan to extract the data along with appropriate compression and encryption techniques is an important requirement for consideration.

2) Transform- Transformation of data with appropriate conversion, aggregation and cleaning besides de-normalization and surrogate key management is also an important process to be planned for building a data warehouse.

3) Load- Steps to be considered to load data with optimization by considering the multiple areas where the data is targeted to be loaded and retrieved is also an important part of the data warehouse architecture plan.

Data Model Architecture

In Data Model Architecture (also known as Dimensional Data Model), there are 3 main data modeling styles for enterprise warehouses:

  1. 3rd Normal Form – Top Down Architecture, Top Down Implementation
  2. Federated Star Schemas – Bottom Up Architecture, Bottom Up Implementation
  3. Data Vault – Top Down Architecture, Bottom Up Implementation

Technology Architecture

Scalability and flexibility is required in all facets. The extent of these features is largely depending upon organizational size, business requirements, nature of business etc.

Technology or Technical architecture primary evolved from derivations from the process architecture, meta data management requirements based on business rules and security levels implementations and technology tool specific evaluation.

Besides these, the Technology architecture also looks into the various technology implementation standards in database management, database connectivity protocols (ODBC, JDBC, OLE DB etc), Middleware (based on ORB, RMI, COM/DOM etc.), Network protocols (DNS, LDAP etc) and other related technologies.

Information Architecture

Information Architecture is the process of translating the information from one form to another in a step by step sequence so as to manage the storage, retrieval, modification and deletion of the data in the data warehouse.

Resource Architecture

Resource architecture is related to software architecture in that many resources come from software resources. Resources are important because they help determine performance. Workload is the other part of the equation. If you have enough resources to complete the workload in the right amount of time, then performance will be high. If there are not enough resources for the workload, then performance will be low.

Various Architectures

Please notice that with the different architectures there is one that stands out: Data Model Architecture. What is happening in the integration industry at large is: the ability to integrate information across the enterprise is becoming dependent on the quality of the data model architecture below.

The ability to be compliant, consistent and repeatable depends on how the data model is built under the covers.

There are 3 main data modeling styles for enterprise warehouses:

  1. 3rd Normal Form – Top Down Architecture, Top Down Implementation
  2. Federated Star Schemas – Bottom Up Architecture, Bottom Up Implementation
  3. Data Vault – Top Down Architecture, Bottom Up Implementation

The point to Data Warehousing Architecture is it is not JUST a data warehouse anymore. It is now a full-scale data integration platform, including right-time (real-time) data, and batch or strategic data sets in a single, auditable (and integrated) data store.

Author:
Tuesday, May 25th, 2010

StringTable resources

Application that maintains (a large number of) strings in resources can be translated into new languages with minimum effort. Storing localized version of Label, Button, and other control Captions into a string table resource offers several advantages over placing all the strings directly into the exe file:

  1. Character strings contained in a string table resource do not consume memory until specifically loaded by an application.
  2. If using string table resources to create multilingual applications, adding a new language is trivial since Stringtables are easily edited. What’s more if the string table is stored in a resource-only DLL, you do not even have to recompile your application.

As with any other type of resources, string tables are compiled into a “.res” file that is attached to your application’s exe file at build time.

Creating a string table resource

Creating a string table resource to support a two (multi) language application:

  1. Create a .RC text file containing your string resources in the applications build directory. Name the file “StringTableLocalization.rc” – you can name it whatever you like, but it must have the “.rc” extension.

StringTableLocalization.rc

STRINGTABLE
{
1000, “English”
1001, “Display selected”
1002, “Yes”
1003, “No”
1004, “Maybe”

2000, “Hrvatski”
2001, “PrikaÃ…¾i odabrano”
2002, “Da”
2003, “Ne”
2004, “MoÃ…¾da”
}

  1. Compile the RC file into a RES file with the BRCC32 resource compiler.

Note: the “StringTableLocalization.rc” CAN contain any additional number of resources of a different type (icons, images, data, etc.)

The string table starts with the key word stringtable. Enclosed in the curly braces are the strings. Each string is listed by its index identifier, followed by the actual string data in quotes. If you need to use a non-standard character, insert the character as a backslash character followed by the octal number of the character you wish to insert. The only exception is when you want to embed a backslash character, you will need to use two backslashes. For example:
1, “A two\012line string”
2, “c:\\Borland\\Delphi”

Using string tables

For the moment take a look at our string table. It is “broken” (only visually) into two regions: “English” and “Hrvatski” (“Croatian”). The Index numbers that you use are not important to the resource compiler. In order to load a particular string from the stringtable you’ll use the LoadString function. One of the parameters in a call to LoadString is the index of a string in a string table.

Linking to an applicaiton
As with any .RES file, you can link the resource file with your application simply by adding the next statement to your application’s code (inside the implementation section of a unit):

{$R StringTableLocalization.RES}

Once the .res file is linked to your program, you can load the resource from any module, even if you specified the $R directive in a different unit.

LoadString
Function to load a string from a stringtable:

function GetString(const Index: integer) : string;
var
  buffer : array[0..255] of char;
  ls : integer;
begin
  Result := '';
  ls := LoadString(hInstance, 
                   Index, 
                   buffer, 
                   sizeof(buffer));
  if ls <> 0 then Result := buffer;

end;

 

 

Once the application is started, the code gets all the languages defined in our string table. By “design” all the language specific strings start at 1 + (1000 * N) position (where N >= 1). The actual name of the language is located at the index for which the following is true: (1000 * N) DIV 1000 = 0.

Note: this “design” is specific to this sample application.

The application gets all the languages and presents them as items of a TRadioGroup component. Once a particular item is selected the strings defined for the selected language are loaded and used by the application.

 

Note: the sample application includes one “special” custom class TResourceLocalizer that actually loads the strings from the resource.

Adding additional languages to this application is a piece of cake – just edit the “StringTableLocalization.rc” by adding any new languages you want. Make sure the new language name starts with an index identifier of 3000 and all other language specific strings follow after it.
For example, to add the German language localized strings edit the RC file as follows:

StringTableLocalization.rc

STRINGTABLE
{
1000, “English”
1001, “Display selected”
1002, “Yes”
1003, “No”
1004, “Maybe”
2000, “Hrvatski”
2001, “PrikaÃ…¾i odabrano”
2002, “Da”
2003, “Ne”
2004, “MoÃ…¾da”
3000, “German”
3001, “Anzeige wählte”
3002, “Ja”
3003, “Nein”
3004, “Möglicherweise”
}

Now, recompile it using the BRCC32 resource compiler, start the application and select the German language in the radio group:

 

That’s it, easy and simple. If you place all the stringtable resources into a separate DLL, you do not even have to recompile your application – only the DLL.

Note:

  • When you compile the rc-file to res-file (using standard Borland bcc), the current codepage in Windows must be a same as strings in rc-file. For example, you can’t compile the rc-file with Hebrew strings on English computer. Only when default codepage will be a Hebrew, bcc will compile the correct res-file. Unfortunatelly to add the LANGUAGE tag to rc-file will not solve a problem.
  • Some controls require additionally to change the Font.Charset property when language toggled.
Category: Delphi  | 5 Comments
Author:
Wednesday, May 05th, 2010

Ever wanted to have a button in your webpage that could show text as well as an image; and also have an overall background image? Something like this:

CustomButton

I’ve created a simple custom control that would achieve the desired goal.

Here’s the code for the custom button itself (CustomImageButton.cs):

using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication2
{
[ToolboxData(
"<{0}:CustomImageButton runat=\"server\"></{0}:CustomImageButton>")]
public class CustomImageButton : LinkButton
{
public string ImageUrl { get; set; }
/// <summary>
/// This image will override any background mentioned in CSS. Use this in case you want to use ASP.net (non-CSS) style URLs (like ~/images/add.png)
/// </summary>
public string BackgroundImageUrl { get; set; }
public override void RenderBeginTag(HtmlTextWriter writer)
{
if (!string.IsNullOrEmpty(this.BackgroundImageUrl))
{
base.Style.Add(“background”, “url(‘” + base.ResolveUrl(this.BackgroundImageUrl) + “‘) left center no-repeat”);
}
base.Style.Add(“text-decoration”, “none”);
base.Style.Add(“text-align”, “center”);
base.RenderBeginTag(writer);
}
protected override void RenderContents(HtmlTextWriter writer)
{
writer.Write(“<span style=’vertical-align:top;’>”);
base.RenderContents(writer);
writer.Write(“</span>”);
writer.Write(“<img border=’0′ style=’margin-top:2px;margin-left:3px’ src=’” + base.ResolveUrl(this.ImageUrl) + “‘ />”);
}
}
}

using System.Web.UI;

using System.Web.UI.WebControls;

namespace WebApplication2

{

[ToolboxData(

"<{0}:CustomImageButton runat=\"server\"></{0}:CustomImageButton>")]

public class CustomImageButton : LinkButton

{

public string ImageUrl { get; set; }

/// <summary>

/// This image will override any background mentioned in CSS. Use this in case you want to use ASP.net (non-CSS) style URLs (like ~/images/add.png)

/// </summary>

public string BackgroundImageUrl { get; set; }

public override void RenderBeginTag(HtmlTextWriter writer)

{

if (!string.IsNullOrEmpty(this.BackgroundImageUrl))

{

base.Style.Add(“background”, “url(‘” + base.ResolveUrl(this.BackgroundImageUrl) + “‘) left center no-repeat”);

}

base.Style.Add(“text-decoration”, “none”);

base.Style.Add(“text-align”, “center”);

base.RenderBeginTag(writer);

}

protected override void RenderContents(HtmlTextWriter writer)

{

writer.Write(“<span style=’vertical-align:top;’>”);

base.RenderContents(writer);

writer.Write(“</span>”);

writer.Write(“<img border=’0′ style=’margin-top:2px;margin-left:3px’ src=’” + base.ResolveUrl(this.ImageUrl) + “‘ />”);

}

}

}

As you can see, this class derives from LinkButton, so all the button related functionality is taken care. What we do is a little html tweak to get the image and background image into the html that’s rendered.

Here’s a sample usage of this custom button:

<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Default.aspx.cs” Inherits=”WebApplication2.Default” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<%@ Register assembly=”WebApplication2″ namespace=”WebApplication2″ tagprefix=”cc1″ %>

<html xmlns=”http://www.w3.org/1999/xhtml” >

<head runat=”server”>

<title></title>

</head>

<body>

<form id=”form1″ runat=”server”>

<div>

<asp:Label ID=”Label1″ runat=”server” Text=”Label”></asp:Label>

<br />

<cc1:CustomImageButton ID=”button1″ runat=”server” Width=”130″ ForeColor=”White”

BackgroundImageUrl=”Images/BlueButton.png”

ImageUrl=”Images/add.png”

Text=”Show Time” onclick=”button1_Click”

>

</cc1:CustomImageButton>

</div>

</form>

</body>

</html>

And here’s the code behind for this sample page:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication2
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void button1_Click(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToString();
}
}
}
That’s it. A simple custom control with lots of potential!
Author:
Monday, May 03rd, 2010

Recently we had a requirement to have ImageCheckbox instead of the traditional checkboxes provided by ASP.NET  where in it was required to be able to configure the images representing the different states of Checkbox such as checked and enabled,unchecked and enabled,checked and disabled,unchecked and disabled .

So,we built an ImageCheckbox custom control that would display images instead of normal checkboxes for the checked and unchecked states.Different images can also be provided for enabled and disabled states of checkbox.

Following demonstrates how to use the Custom control in the ASPX page.

<%@ Register TagPrefix=”custom” Namespace=”CustomControls” Assembly=”CustomControls” %>

<custom:ImageCheckBox id=”chkUserEnabled” runat=”server” Enabled=”false”

ImageChecked=”../img/common/checked_enabled.gif”

ImageUnchecked=”../img/common/unchecked_enabled.gif”

DisabledImageChecked=”../img/common/checked_disabled.gif”

DisabledImageUnchecked=”../img/common/unchecked_disabled.gif” ShowCheckBox=”false”/>

Following is the source code of how to achieve the functionality.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CustomControls
{
public class ImageCheckBox : CheckBox
{
// Methods
public ImageCheckBox()
{
base.Init += new EventHandler(this.ImageCheckBox_Init);
}
private void ImageCheckBox_Init(object sender, EventArgs e)
{
if (!this.Page.ClientScript.IsClientScriptBlockRegistered(“ImageCheckBox”))
{
string script = “function createImageCheckbox(c, iC, iU){\r\n    var cO=document.getElementById(c);var iO = document.getElementById(c+ ‘_Image’);if (cO.checked) { cO.checked=false; iO.src = iU;} else {cO.checked=true; iO.src = iC;}}\r\nfunction toggleImageCheckbox(c,iC, iU){var cO=document.getElementById(c);var iO = document.getElementById(c+ ‘_Image’);\r\nif (cO.checked) {iO.src = iC;} else {iO.src = iU;}}”;
this.Page.ClientScript.RegisterClientScriptBlock(typeof(ImageCheckBox), “ImageCheckBox”, script, true);
}
}
protected override void Render(HtmlTextWriter output)
{
string str = “”;
string str2 = “createImageCheckbox(‘” + this.ClientID + “‘,’” + this.ImageChecked + “‘,’” + this.ImageUnchecked + “‘);”;
string str3 = “toggleImageCheckbox(‘” + this.ClientID + “‘,’” + this.ImageChecked + “‘,’” + this.ImageUnchecked + “‘);”;
if (this.AutoPostBack)
{
str = @”setTimeout(‘__doPostBack(\’” + this.ClientID + @”\’,\’\')’, 0);”;
}
else
{
base.Attributes.Add(“onclick”, str3);
}
Image image = new Image();
image.ID = this.ClientID + “_Image”;
if (!this.ShowCheckBox)
{
base.Style.Add(“display”, “none”);
}
if (this.Enabled)
{
image.Attributes.Add(“onclick”, “javascript:” + str2 + str);
if (this.Checked)
{
image.ImageUrl = this.ImageChecked;
}
else
{
image.ImageUrl = this.ImageUnchecked;
}
}
else
{
//if disabled
if (this.Checked)
{
image.ImageUrl = this.DisabledImageChecked;
}
else
{
image.ImageUrl = this.DisabledImageUnchecked;
}
}
image.RenderControl(output);
base.Render(output);
}
// Properties
[Bindable(true), DefaultValue(0), Description("Specifies Image for the Checked Image"), Category("Appearance")]
public string ImageChecked
{
get
{
string str = (string)this.ViewState["ImageChecked"];
if (str == null)
{
return “images/checked.gif”;
}
return str;
}
set
{
this.ViewState["ImageChecked"] = value;
}
}
[Category("Appearance"), Description("Specifies Image for the Unchecked Image"), Bindable(true), DefaultValue(0)]
public string ImageUnchecked
{
get
{
string str = (string)this.ViewState["ImageUnchecked"];
if (str == null)
{
return “images/unchecked.gif”;
}
return str;
}
set
{
this.ViewState["ImageUnchecked"] = value;
}
}
[Bindable(true), DefaultValue(0), Description("Specifies Image for the Disabled Checked Image"), Category("Appearance")]
public string DisabledImageChecked
{
get
{
string str = (string)this.ViewState["DisabledImageChecked"];
if (str == null)
{
return “images/checked.gif”;
}
return str;
}
set
{
this.ViewState["DisabledImageChecked"] = value;
}
}
[Category("Appearance"), Description("Specifies Image for the Disabled Unchecked Image"), Bindable(true), DefaultValue(0)]
public string DisabledImageUnchecked
{
get
{
string str = (string)this.ViewState["DisabledImageUnchecked"];
if (str == null)
{
return “images/unchecked.gif”;
}
return str;
}
set
{
this.ViewState["DisabledImageUnchecked"] = value;
}
}
[Bindable(true), Category("Appearance"), DefaultValue(0), Description("Show or hide the checkbox")]
public bool ShowCheckBox
{
get
{
if (this.ViewState["ShowCheckBox"] == null)
{
return false;
}
return (bool)this.ViewState["ShowCheckBox"];
}
set
{
this.ViewState["ShowCheckBox"] = value;
}
}
}
}

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Text;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

namespace CustomControls

{

public class ImageCheckBox : CheckBox

{

// Methods

public ImageCheckBox()

{

base.Init += new EventHandler(this.ImageCheckBox_Init);

}

private void ImageCheckBox_Init(object sender, EventArgs e)

{

if (!this.Page.ClientScript.IsClientScriptBlockRegistered(“ImageCheckBox”))

{

string script = “function createImageCheckbox(c, iC, iU){\r\n    var cO=document.getElementById(c);var iO = document.getElementById(c+ ‘_Image’);if (cO.checked) { cO.checked=false; iO.src = iU;} else {cO.checked=true; iO.src = iC;}}\r\nfunction toggleImageCheckbox(c,iC, iU){var cO=document.getElementById(c);var iO = document.getElementById(c+ ‘_Image’);\r\nif (cO.checked) {iO.src = iC;} else {iO.src = iU;}}”;

this.Page.ClientScript.RegisterClientScriptBlock(typeof(ImageCheckBox), “ImageCheckBox”, script, true);

}

}

protected override void Render(HtmlTextWriter output)

{

string str = “”;

string str2 = “createImageCheckbox(‘” + this.ClientID + “‘,’” + this.ImageChecked + “‘,’” + this.ImageUnchecked + “‘);”;

string str3 = “toggleImageCheckbox(‘” + this.ClientID + “‘,’” + this.ImageChecked + “‘,’” + this.ImageUnchecked + “‘);”;

if (this.AutoPostBack)

{

str = @”setTimeout(‘__doPostBack(\’” + this.ClientID + @”\’,\’\')’, 0);”;

}

else

{

base.Attributes.Add(“onclick”, str3);

}

Image image = new Image();

image.ID = this.ClientID + “_Image”;

if (!this.ShowCheckBox)

{

base.Style.Add(“display”, “none”);

}

if (this.Enabled)

{

image.Attributes.Add(“onclick”, “javascript:” + str2 + str);

if (this.Checked)

{

image.ImageUrl = this.ImageChecked;

}

else

{

image.ImageUrl = this.ImageUnchecked;

}

}

else

{

//if disabled

if (this.Checked)

{

image.ImageUrl = this.DisabledImageChecked;

}

else

{

image.ImageUrl = this.DisabledImageUnchecked;

}

}

image.RenderControl(output);

base.Render(output);

}

// Properties

[Bindable(true), DefaultValue(0), Description("Specifies Image for the Checked Image"), Category("Appearance")]

public string ImageChecked

{

get

{

string str = (string)this.ViewState["ImageChecked"];

if (str == null)

{

return “images/checked.gif”;

}

return str;

}

set

{

this.ViewState["ImageChecked"] = value;

}

}

[Category("Appearance"), Description("Specifies Image for the Unchecked Image"), Bindable(true), DefaultValue(0)]

public string ImageUnchecked

{

get

{

string str = (string)this.ViewState["ImageUnchecked"];

if (str == null)

{

return “images/unchecked.gif”;

}

return str;

}

set

{

this.ViewState["ImageUnchecked"] = value;

}

}

[Bindable(true), DefaultValue(0), Description("Specifies Image for the Disabled Checked Image"), Category("Appearance")]

public string DisabledImageChecked

{

get

{

string str = (string)this.ViewState["DisabledImageChecked"];

if (str == null)

{

return “images/checked.gif”;

}

return str;

}

set

{

this.ViewState["DisabledImageChecked"] = value;

}

}

[Category("Appearance"), Description("Specifies Image for the Disabled Unchecked Image"), Bindable(true), DefaultValue(0)]

public string DisabledImageUnchecked

{

get

{

string str = (string)this.ViewState["DisabledImageUnchecked"];

if (str == null)

{

return “images/unchecked.gif”;

}

return str;

}

set

{

this.ViewState["DisabledImageUnchecked"] = value;

}

}

[Bindable(true), Category("Appearance"), DefaultValue(0), Description("Show or hide the checkbox")]

public bool ShowCheckBox

{

get

{

if (this.ViewState["ShowCheckBox"] == null)

{

return false;

}

return (bool)this.ViewState["ShowCheckBox"];

}

set

{

this.ViewState["ShowCheckBox"] = value;

}

}

}

}

Category: .Net, General  | One Comment