<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Chad Scharf&#039;s Weblog &#187; The Client Side</title>
	<atom:link href="http://www.chadscharf.com/index.php/categories/the-client-side/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.chadscharf.com</link>
	<description>It&#039;s always time to upgrade!</description>
	<lastBuildDate>Fri, 28 Oct 2011 22:14:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Creating a Page method (ScriptMethod) within an ASCX user control using AJAX, JSON, base classes and reflection</title>
		<link>http://www.chadscharf.com/index.php/2009/11/creating-a-page-method-scriptmethod-within-an-ascx-user-control-using-ajax-json-base-classes-and-reflection/</link>
		<comments>http://www.chadscharf.com/index.php/2009/11/creating-a-page-method-scriptmethod-within-an-ascx-user-control-using-ajax-json-base-classes-and-reflection/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 05:46:59 +0000</pubDate>
		<dc:creator>Chad</dc:creator>
				<category><![CDATA[ajax]]></category>
		<category><![CDATA[ASP.NET Development]]></category>
		<category><![CDATA[The Client Side]]></category>
		<category><![CDATA[ascx]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[page methods]]></category>
		<category><![CDATA[reflection]]></category>
		<category><![CDATA[scriptmethod]]></category>

		<guid isPermaLink="false">http://www.chadscharf.com/?p=51</guid>
		<description><![CDATA[While ASCX user controls may not contain page methods (ScriptMethod), pages can. Duh, right! So why canâ€™t I create a single, general page method in my base page class which all of my site pages inherit from, and provide a means, through reflection and custom attributes, along with my base user control class that all my ASCX user controls ultimately inherit from, to dynamically create JavaScript wrappers for calling my pageâ€™s single page method, which in turn knows how to invoke my user control typeâ€™s public static method, passing in any collection of parameters and even providing a wrapper for JSON serialization of the methodâ€™s result back to the client, INCLUDING ANONYMOUS TYPES!!! OK, now Iâ€™m on to something.<p><a href="http://www.chadscharf.com/index.php/2009/11/creating-a-page-method-scriptmethod-within-an-ascx-user-control-using-ajax-json-base-classes-and-reflection/">Creating a Page method (ScriptMethod) within an ASCX user control using AJAX, JSON, base classes and reflection</a> is a post from: <a href="http://www.chadscharf.com">Chad Scharf&#039;s Weblog</a>. For software consulting services please visit <a href="http://www.scharfholdings.com">Scharf Holdings, LLC</a></p>
]]></description>
			<content:encoded><![CDATA[<p>I have searched far and wide for the past week looking for a way to create a page method (a neat feature in ASP.NET which allows you to call static methods in your page decorated with an attribute as an AJAX web service) in an ASCX user control and possibly even a master page. First, a little background (yes, there will be a code download link at the end of the article)</p>
<p> <span id="more-51"></span>
<p>I am currently working on an enterprise level ASP.NET AJAX application to be used in a call center, as most of the applications I create are for use in call center automation and task management. Because Update Panels are evil and this application was riddled with them, I have been slowly but surely stripping them out one by one. The problem, the application loads 90% of its screens and functionality based on configuration data, dynamically building pages and loading user controls located in both ASCX files and server controls located in external assemblies bound at run-time. The major roadblock is that our middle tier is all WCF, which works great, however they are all on a different domain than the web application and use secure SOAP (not REST), therefore I can&#8217;t call them from JavaScript. Not only that, there are only 4 pages in the entire application, everything else is dynamic. With over 130+ and growing user controls, and plug-and-play custom functionality, it would be impossible to put all of these methods in copy-cat services using WCF in the web application itself. Did I mention that the site uses a dozen or so host headers in IIS, which rules out WCF hosted svc files in the web site right there. Page methods seemed like a perfect fit, only I wasn&#8217;t about to put 200+ web methods on a single page when only one or two user controls would ever use them. That would be stupid and the JavaScript would take forever to compile in even a fast browser.</p>
<p>Everything I found on the web searching Google, MSDN forums, user groups, etc has turned up one and only one answer to my dilemma: This can not be done, only public, static methods on an actual ASPX page may contain page methods in this manner because ASCX controls do not have their own unique post-back address like a page does. I thought to myself, This is stupid! Of all the brilliant things Microsoft has done with ASP.NET you would think that they would have built the ability to register methods dynamically on the page through a child control, whether a user control or master page, either as a callback, delegate, etc, at least some model for doing this, but alas, apparently myself and the hundreds of other posters out there have not been diligent in filling out feature requests for this item, which I will do sometime later this week.</p>
<h2>The solution:</h2>
<p>While ASCX user controls may not contain page methods (ScriptMethod), pages can. Duh, right! So why can&#8217;t I create a single, general page method in my base page class which all of my site pages inherit from, and provide a means, through reflection and custom attributes, along with my base user control class that all my ASCX user controls ultimately inherit from, to dynamically create JavaScript wrappers for calling my page&#8217;s single page method, which in turn knows how to invoke my user control type&#8217;s public static method, passing in any collection of parameters and even providing a wrapper for JSON serialization of the method&#8217;s result back to the client, INCLUDING ANONYMOUS TYPES!!! OK, now I&#8217;m on to something.</p>
<p>The end result is a custom attribute which my base user control class detects on static, invoking, public methods, which then registers some well-crafted JavaScript script block with the page&#8217;s ScriptManager, which in turn know how to invoke the page&#8217;s ScriptMethod dynamically passing in some information about the type name and method name to invoke through reflection.</p>
<h3>Now, to the code</h3>
<p>First, we need to create an attribute to attach to our ultra-nifty public static methods in our user controls that we want to expose to our client as ScriptMethods. I&#8217;m going to call my attribute <em><strong>UserControlScriptMethodAttribute</strong></em>, but you can call it whatever you want. This is a very simple attribute, not much to do here. You could add some validation that it&#8217;s on a static and public member, but that&#8217;s up to you.</p>
<pre class="code">[<span style="color: #2b91af">AttributeUsage</span>(<span style="color: #2b91af">AttributeTargets</span>.Method, Inherited = <span style="color: blue">false</span>, AllowMultiple = <span style="color: blue">false</span>)]
<span style="color: blue">public sealed class </span><span style="color: #2b91af">UserControlScriptMethodAttribute </span>: <span style="color: #2b91af">Attribute
</span>{
    <span style="color: gray">/// &lt;summary&gt;
    /// </span><span style="color: green">Initializes a new instance of the </span><span style="color: gray">&lt;see cref=&quot;UserControlScriptMethodAttribute&quot;/&gt; </span><span style="color: green">class.
    </span><span style="color: gray">/// &lt;/summary&gt;
    </span><span style="color: blue">public </span>UserControlScriptMethodAttribute() { }
}</pre>
<h4>BasePage.cs</h4>
<h4></h4>
<p>Then, I needed my base implementation for the &#8220;generalized&#8221; ScriptMethod. This would be on the page class that all of my pages inherit from, exposing the capability of using these ScriptMethod from any user control or master page that I want to.</p>
<p>There are several important things going on in the base page class. First, I needed to create my script method. This method has a simple signature, basically taking a fully qualified type name (including the assembly if need be), as well as the method name to invoke in that type and a boxed object array for any additional arguments which should be passed through as parameters when invoking the method. I&#8217;ve hard-coded my response format as JSON and HttpGet=false. You could theoretically create several versions of these method for different options and add these options as well to your custom parameter for consumption, but I didn&#8217;t need anything that sophisticated here.</p>
<pre class="code">[<span style="color: #2b91af">WebMethod</span>(EnableSession = <span style="color: blue">true</span>)]
[<span style="color: #2b91af">ScriptMethod</span>(ResponseFormat = <span style="color: #2b91af">ResponseFormat</span>.Json, UseHttpGet = <span style="color: blue">false</span>)]
<span style="color: blue">public static string </span>PageServiceRequest(<span style="color: blue">string </span>typeName, <span style="color: blue">string </span>methodName, <span style="color: blue">object</span>[] args)
{
    <span style="color: #2b91af">Type </span>ctl = <span style="color: #2b91af">Type</span>.GetType(typeName);
    <span style="color: blue">if </span>(ctl != <span style="color: blue">null</span>)
    {
        <span style="color: blue">object </span>o = ctl.InvokeMember(
            methodName,
              System.Reflection.<span style="color: #2b91af">BindingFlags</span>.Static
            | System.Reflection.<span style="color: #2b91af">BindingFlags</span>.InvokeMethod
            | System.Reflection.<span style="color: #2b91af">BindingFlags</span>.Public
            | System.Reflection.<span style="color: #2b91af">BindingFlags</span>.IgnoreCase,
            <span style="color: blue">null</span>, <span style="color: blue">null</span>, args ?? <span style="color: blue">new object</span>[]{});
        <span style="color: blue">if </span>(o != <span style="color: blue">null</span>)
        {
            <span style="color: blue">if </span>(o <span style="color: blue">is string </span>|| o.GetType().IsValueType)
                <span style="color: blue">return </span>o.ToString(); <span style="color: green">// If it is a string or value type, return a string

            // If it is a complex object, return a serialized version of it.
            </span><span style="color: #2b91af">JavaScriptSerializer </span>serializer = <span style="color: blue">new </span><span style="color: #2b91af">JavaScriptSerializer</span>();
            <span style="color: blue">return </span>serializer.Serialize(o); <span style="color: green">// allow anonymous types, etc
        </span>}
    }
    <span style="color: blue">return </span><span style="color: #a31515">&quot;{}&quot;</span>; <span style="color: green">// return an empty JSON object
</span>}</pre>
<p>Notice that once I get the Type I need from the type name, getting the method using some simple binding flags is rather easy, then invoking it passing the arguments object array straight through. From there, I take the result of the method invocation and determine if it is a value type or a string, if it is, I simply return the value.ToString(), otherwise I&#8217;m serializing it to JSON and still returning a string (only this string is JSON). The JavaScriptSerializer even allows me to take an anonymous type from the invocation target and serialize it directly back to the client in JSON without having to any further work, which you&#8217;ll see a little later in this article, is really freakin&#8217; cool!</p>
<p>Next, I need to expose a more friendly wrapper around the ScriptMethod in JavaScript so my user controls will have to know less about how to invoke this guy and it makes it a bit more usable.</p>
<pre class="code"><span style="color: blue">private void </span>RegisterPageServiceRequestProxy()
{
    <span style="color: #2b91af">ScriptManager</span>.RegisterClientScriptBlock(
        <span style="color: blue">this</span>,
        GetType(),
        <span style="color: #a31515">&quot;PageServiceRequestProxy&quot;</span>,
        <span style="color: #a31515">&quot;function InvokeServiceRequest(typeName,methodName,successCallback,failureCallback){if(PageMethods.PageServiceRequest){try{var parms=[];for(var i=4;i&lt;arguments.length;i++){parms.push(arguments[i]);}PageMethods.PageServiceRequest(typeName,methodName,parms,successCallback,failureCallback);}catch(e){alert(e.toString());}}}&quot;</span>,
        <span style="color: blue">true</span>);
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>Wow, this a really long, condensed line of JavaScript which you don&#8217;t necessarily need to understand, other than the fact that it really will make life easy for you. Essentially it creates a wrapper method taking the type name, method name, callbacks and allows you to pass in any number of additional arguments; as many as you want after the failure callback. This wrapper will then simply take those extra parameters and build an Array object to pass as the â€œargsâ€ parameter to the base ScriptMethod. I need to call this method OnInit as seen below:</p>
<pre class="code"><span style="color: blue">protected override void </span>OnInit(<span style="color: #2b91af">EventArgs </span>e)
{
    <span style="color: blue">base</span>.OnInit(e);
    RegisterPageServiceRequestProxy();
}</pre>
<h4>BaseUserControl.cs</h4>
<p>Our base user control, which all ASCX pages will inherit is a bit more involved. For one, we need to obfuscate the innards of how our new attribute is consumed. We also want to hide all the minutia around passing fully qualified type names and method names, etc. We also want to expose some nicely formed methods on the client via JavaScript that can be called using the same method name and similar parameter signature as the method in the ASCX code-behind, with the exception of the callback client methods (the whole point of asynchronous client processing).</p>
<p>First, I want to emit and register my scripts and &#8220;stuff&#8221; during the Pre-Render phase of the page life-cycle, so I&#8217;m going to override OnPreRender to call my register method.</p>
<pre class="code"><span style="color: blue">protected override void </span>OnPreRender(<span style="color: #2b91af">EventArgs </span>e)
{
    <span style="color: blue">base</span>.OnPreRender(e);
    RegisterUserControlWebMethods();
}</pre>
<p>Next, let&#8217;s build out the implementation of our RegisterUserControlWebMethods method stub. I made it private because it doesn&#8217;t need visibility outside of our base class, remember our attribute will take care of this for us.</p>
<pre class="code"><span style="color: blue">private void </span>RegisterUserControlWebMethods()
{
    <span style="color: blue">foreach </span>(<span style="color: #2b91af">MethodInfo </span>method <span style="color: blue">in this</span>.GetType().GetMethods(<span style="color: #2b91af">BindingFlags</span>.Static | <span style="color: #2b91af">BindingFlags</span>.Public | <span style="color: #2b91af">BindingFlags</span>.InvokeMethod))
        <span style="color: blue">if </span>(method.GetCustomAttributes(<span style="color: blue">typeof</span>(<span style="color: #2b91af">UserControlScriptMethodAttribute</span>), <span style="color: blue">true</span>).Length &gt; 0)
            RegisterUserControlWebMethod(method);

    <span style="color: #2b91af">Type </span>baseType = <span style="color: blue">this</span>.GetType().BaseType;
    <span style="color: blue">if </span>(baseType != <span style="color: blue">null </span>&amp;&amp; (baseType.Namespace == <span style="color: blue">null </span>|| !baseType.Namespace.StartsWith(<span style="color: #a31515">&quot;System&quot;</span>)))
        <span style="color: blue">foreach </span>(<span style="color: #2b91af">MethodInfo </span>method <span style="color: blue">in </span>baseType.GetMethods(<span style="color: #2b91af">BindingFlags</span>.Static | <span style="color: #2b91af">BindingFlags</span>.Public | <span style="color: #2b91af">BindingFlags</span>.InvokeMethod))
            <span style="color: blue">if </span>(method.GetCustomAttributes(<span style="color: blue">typeof</span>(<span style="color: #2b91af">UserControlScriptMethodAttribute</span>), <span style="color: blue">true</span>).Length &gt; 0)
                RegisterUserControlWebMethod(method);
}</pre>
<p>In the example above, you can see our initial search within the current type for any methods with the appropriate binding flags, being static, public and invoke, as well as a test for our custom attribute. If we find any, for each one that we find we&#8217;re going to further call our RegisterUserControlWebMethod (more on this in a few lines). You&#8217;ll notice that we also do a second round through reflection to get the base type and check any methods in there for these super special attribute decorated methods. I could have made this a bit cleaner in the recursion department, but again, I didn&#8217;t need to for my purposes, I&#8217;m sure there are better ways to do this. The reason I&#8217;m doing this second loop on base types is simple, depending on your project structure, either a Web Project or Web Site, you will find that your methods exist not in the current type, but the base type as the current type you have loaded is some temporary type drummed up in the CLR at run-time or located in a special page or directory assembly, etc.</p>
<p>Now that we&#8217;ve found the methods we need to be able to invoke on the client, we need to emit and register wrappers for those methods, obfuscating the details around type names, method names, etc and providing a neat and concise means of invoking them on the client.</p>
<pre class="code"><span style="color: blue">private void </span>RegisterUserControlWebMethod(<span style="color: #2b91af">MethodInfo </span>method)
{
    <span style="color: blue">string </span>blockName = <span style="color: blue">string</span>.Concat(method.Name, <span style="color: #a31515">&quot;_webMethod_uc&quot;</span>);

    <span style="color: #2b91af">StringBuilder </span>funcBuilder = <span style="color: blue">new </span><span style="color: #2b91af">StringBuilder</span>();
    funcBuilder.Append(<span style="color: #a31515">&quot;function &quot;</span>);
    funcBuilder.Append(method.Name);
    funcBuilder.Append(<span style="color: #a31515">&quot;(successCallback,failureCallback&quot;</span>);
    <span style="color: blue">foreach </span>(<span style="color: blue">var </span>par <span style="color: blue">in </span>method.GetParameters())
        funcBuilder.AppendFormat(<span style="color: #a31515">&quot;,{0}&quot;</span>, par.Name);
    funcBuilder.Append(<span style="color: #a31515">&quot;){if(PageMethods.PageServiceRequest){try{var parms=[];for(var i=2;i&lt;arguments.length;i++){parms.push(arguments[i]);}PageMethods.PageServiceRequest(&quot;</span>);
    funcBuilder.AppendFormat(<span style="color: #a31515">&quot;'{0}','{1}'&quot;</span>, method.DeclaringType.AssemblyQualifiedName, method.Name);
    funcBuilder.Append(<span style="color: #a31515">&quot;,parms,successCallback,failureCallback);}catch(e){alert(e.toString());}}}&quot;</span>);

    <span style="color: #2b91af">ScriptManager</span>.RegisterClientScriptBlock(<span style="color: blue">this</span>, GetType(), blockName, funcBuilder.ToString(), <span style="color: blue">true</span>);
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>The RegisterUserControlWebMethod method takes the method info through reflection and builds a JavaScript function with the same name as the method, then adds the appropriate callback parameters which are always the first and second parameter respectfully, then takes the parameter collection (much like the base page registered method did) and passes those an a JavaScript Array, invoking the PageServiceRequest through the PageMethods namespace. When invoking the PageServiceRequest method, it also passes the fully qualified type name of the method info&#8217;s declaring type and the method name through reflection, keeping these values in the function wrapper as coded string values.</p>
<h4>ServerTime.ascx</h4>
<p>ServerTime is my example User Control which gets loaded on a simple page, Default.aspx. There i no code on Default.aspx, therefore there is no need to put anything here for it. All I did was drop the ServerTime.ascx user control onto the designer surface of Default.aspx in Visual Studio so the page would host my user control. Keep in mind I&#8217;m setting my base page type and base user control type in my web.confg as shown here:</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">system.web</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">pages </span><span style="color: red">pageBaseType</span><span style="color: blue">=</span>&quot;<span style="color: blue">ScharfHoldings.BasePage</span>&quot; <span style="color: red">userControlBaseType</span><span style="color: blue">=</span>&quot;<span style="color: blue">ScharfHoldings.BaseUserControl</span>&quot;</pre>
<p><a href="http://11011.net/software/vspaste"></a>The code-behind file, ServerTime.ascx.cs looks like this below:</p>
<pre class="code"><span style="color: blue">using </span>System;
<span style="color: blue">using </span>System.Collections.Generic;
<span style="color: blue">using </span>System.Linq;
<span style="color: blue">using </span>System.Web;
<span style="color: blue">using </span>System.Web.UI;
<span style="color: blue">using </span>System.Web.UI.WebControls;

<span style="color: blue">public partial class </span><span style="color: #2b91af">ServerTime </span>: ScharfHoldings.<span style="color: #2b91af">BaseUserControl
</span>{
    [ScharfHoldings.<span style="color: #2b91af">UserControlScriptMethod</span>]
    <span style="color: blue">public static string </span>GetTime()
    {
        <span style="color: green">// Return a simple string to the client. This by-passes serialization since it is only a string.
        </span><span style="color: blue">return </span><span style="color: #2b91af">DateTime</span>.Now.ToLongTimeString();
    }

    [ScharfHoldings.<span style="color: #2b91af">UserControlScriptMethod</span>]
    <span style="color: blue">public static </span><span style="color: #2b91af">ComplexTime </span>GetComplexTime()
    {
        <span style="color: green">// Return a strongly typed object instance to the client.
        </span><span style="color: blue">return new </span><span style="color: #2b91af">ComplexTime</span>() { Time = <span style="color: #2b91af">DateTime</span>.Now.ToLongTimeString(), MachineName = <span style="color: #2b91af">HttpContext</span>.Current.Server.MachineName };
    }

    [ScharfHoldings.<span style="color: #2b91af">UserControlScriptMethod</span>]
    <span style="color: blue">public static object </span>GetAnonymousTime()
    {
        <span style="color: green">// Return an anonymous type instance to the client.
        //    this anonymous type is intended to mimic our ComplexTime type, only it is anonymous, however will
        //    behave the exact same when it is serialized to the client through JavaScript.
        </span><span style="color: blue">return new </span>{ Time = <span style="color: #2b91af">DateTime</span>.Now.ToLongTimeString(), MachineName = <span style="color: #2b91af">HttpContext</span>.Current.Server.MachineName };
    }

    [ScharfHoldings.<span style="color: #2b91af">UserControlScriptMethod</span>]
    <span style="color: blue">public static object </span>GetTimeWithParameter(<span style="color: blue">string </span>clientMessage)
    {
        <span style="color: green">// Return an anonymous type instance to the client.
        //    The clientMessage parameter gets passed in dynamically from the client and we're going to set the
        //    MachineName property to this value to pass back from the server to prove we got the client value in the parameter.
        </span><span style="color: blue">return new </span>{ Time = <span style="color: #2b91af">DateTime</span>.Now.ToLongTimeString(), MachineName = clientMessage };
    }

    [<span style="color: #2b91af">Serializable</span>]
    <span style="color: blue">public class </span><span style="color: #2b91af">ComplexTime
    </span>{
        <span style="color: blue">public string </span>Time { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
        <span style="color: blue">public string </span>MachineName { <span style="color: blue">get</span>; <span style="color: blue">set</span>; }
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a>As you can see I have 4 of my custom script methods to show-case the different capabilities built into this methodology. One is a simple call, with no parameters, which returns a string.</p>
<p>GetComplexTime takes no parameters and returns an object of type ComplexType which has a property, Time and MachineName.</p>
<p>GetAnonymousType showcases the ability for this method to return anonymous types to the client, which is a very powerful feature and presents itself more like JavaScript rather than .NET. The anonymous type I am created here is intended to look exactly like ComplexType for no other reason than to re-use code on client and show it can be done.</p>
<p>GetTimeWithParameter takes a simple type parameter (a string in this case) and returns another anonymous type, but this time plugging the parameter into the MachineName property instead of the server&#8217;s machine name. This again is for ease of example and code re-use.</p>
<p>Now, let&#8217;s take a look at the client side of this. First, I have a simple structure for displaying my data and a button to invoke all of my server methods asynchronously:</p>
<pre class="code"><span style="background: #ffee62">&lt;%</span><span style="color: blue">@ </span><span style="color: #a31515">Control </span><span style="color: red">Language</span><span style="color: blue">=&quot;C#&quot; </span><span style="color: red">AutoEventWireup</span><span style="color: blue">=&quot;true&quot; </span><span style="color: red">CodeFile</span><span style="color: blue">=&quot;ServerTime.ascx.cs&quot; </span><span style="color: red">Inherits</span><span style="color: blue">=&quot;ServerTime&quot; </span><span style="background: #ffee62">%&gt;
</span><span style="color: blue">&lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">=&quot;myTime&quot;&gt;
    &lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">=&quot;time&quot;&gt;&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">=&quot;complexTime&quot;&gt;&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">=&quot;anonymousTime&quot;&gt;&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">div </span><span style="color: red">id</span><span style="color: blue">=&quot;parameterTime&quot;&gt;&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;
    &lt;</span><span style="color: #a31515">input </span><span style="color: red">type</span><span style="color: blue">=&quot;button&quot; </span><span style="color: red">id</span><span style="color: blue">=&quot;refreshMe&quot; </span><span style="color: red">value</span><span style="color: blue">=&quot;Get Time&quot; </span><span style="color: red">title</span><span style="color: blue">=&quot;Click here to refresh the time from the server&quot; </span><span style="color: red">onclick</span><span style="color: blue">=&quot;refreshTime();return false;&quot; /&gt;
&lt;/</span><span style="color: #a31515">div</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>As you can see, I have a DIV for each method result to show the results of each method call and a simple button labeled Get Time that will call a simple JavaScript function, that in turn calls all of my user control Script methods.</p>
<p>Here is what the page and user control look like upon their initial state:</p>
<p><a href="http://www.chadscharf.com/wp-content/uploads/2009/11/InitialState.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="InitialState" border="0" alt="InitialState" src="http://www.chadscharf.com/wp-content/uploads/2009/11/InitialState_thumb.png" width="244" height="198" /></a></p>
<p>Now we need to make the button do something interesting. Below is the JavaScript block that provides the method that executes all the other methods, refreshTime() as well as the callback methods for success and failure of each ScriptMethod call that we make. the last two methods are simply for displaying the results of the script methods in their respectful DIV elements.</p>
<pre class="code"><span style="color: blue">&lt;</span><span style="color: #a31515">script </span><span style="color: red">type</span><span style="color: blue">=&quot;text/javascript&quot;&gt;
</span><span style="color: green">//&lt;![CDATA[
    </span><span style="color: blue">function </span>refreshTime() {
        <span style="color: blue">try </span>{
            <span style="color: green">// Call the UserControlWebMethod attributed functions on the server.
            </span>GetTime(refreshTime_Success, refreshTime_Failure);
            GetComplexTime(refreshTimeComplex_Success, refreshTimeComplex_Failure);
            GetAnonymousTime(refreshTimeAnonymous_Success, refreshTimeAnonymous_Failure);
            GetTimeWithParameter(refreshTimeWithParameter_Success, refreshTimeWithParameter_Failure, <span style="color: #a31515">'the Client... Hi!'</span>);
        }
        <span style="color: blue">catch </span>(e) { alert(e.message); }
    }

    <span style="color: green">// Delegate functions for the GetTime method
    </span><span style="color: blue">function </span>refreshTime_Success(result) { displayTime(result); }
    <span style="color: blue">function </span>refreshTime_Failure(result) { }

    <span style="color: green">// Delegate functions for the GetComplexTime method
    </span><span style="color: blue">function </span>refreshTimeComplex_Success(result) { displayComplexTime(result, $get(<span style="color: #a31515">'complexTime'</span>)); }
    <span style="color: blue">function </span>refreshTimeComplex_Failure(result) { }

    <span style="color: green">// Delegate functions for the GetAnonymousTime method
    </span><span style="color: blue">function </span>refreshTimeAnonymous_Success(result) { displayComplexTime(result, $get(<span style="color: #a31515">'anonymousTime'</span>)); }
    <span style="color: blue">function </span>refreshTimeAnonymous_Failure(result) { }

    <span style="color: green">// Delegate functions for the GetTimeWithParameter method
    </span><span style="color: blue">function </span>refreshTimeWithParameter_Success(result) { displayComplexTime(result, $get(<span style="color: #a31515">'parameterTime'</span>)); }
    <span style="color: blue">function </span>refreshTimeWithParameter_Failure(result) { }

    <span style="color: green">// Simply set the innerText of the simple time element from the raw result of the service method.
    </span><span style="color: blue">function </span>displayTime(timeAsString) {
        document.getElementById(<span style="color: #a31515">'time'</span>).innerText = timeAsString;
    }

    <span style="color: green">// Evaluate and parse out the JSON object to a type using eval, then build a display string and display the result.
    </span><span style="color: blue">function </span>displayComplexTime(timeAsObj, ctrl) {
        <span style="color: blue">try </span>{
            <span style="color: blue">var </span>obj = eval(<span style="color: #a31515">'(' </span>+ timeAsObj + <span style="color: #a31515">')'</span>);
            <span style="color: blue">if </span>(obj) ctrl.innerText = obj.Time + <span style="color: #a31515">' on ' </span>+ obj.MachineName;
        }
        <span style="color: blue">catch </span>(e) { alert(e.message); }
    }
<span style="color: green">//]]&gt;
</span><span style="color: blue">&lt;/</span><span style="color: #a31515">script</span><span style="color: blue">&gt;</span></pre>
<p><a href="http://11011.net/software/vspaste"></a>As you can see, when we&#8217;re getting back an object (rather than a simple or value type) we have to call eval() on that object&#8217;s JSON string, wrapped in parenthesis in order to get the actual object instance from the JSON (otherwise it is still just a string). Once I have an instance from the JSON using eval, I can get property values from that object, such as you see here, which are exactly the same name as the properties specified in both the ComplexTime class, as well as both uses of the anonymous types.</p>
<p>The end result looks like this once I click the button (notice, depending on your computer&#8217;s speed, you may see all the lines appear or refresh at the same time or like me you may see a slight delay in the asynchronous processing of each of the methods.</p>
<p><a href="http://www.chadscharf.com/wp-content/uploads/2009/11/ButtonClicked.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="ButtonClicked" border="0" alt="ButtonClicked" src="http://www.chadscharf.com/wp-content/uploads/2009/11/ButtonClicked_thumb.png" width="244" height="198" /></a> </p>
<p>Viola! That&#8217;s all there is to it. NEVER let anyone tell you ever again that you can&#8217;t create page methods in an ASCX user control, because using these technique, you most definitely can!</p>
<h3>Source Code Download</h3>
<p>I&#8217;ve created a simple, sample web site in Visual Studio 2008, .NET 3.5 to show off the capabilities and give you a starting point to play around with the code. This is the full working source code that I based the article on. I look forward to getting your comments, feedback and improvements you&#8217;ve made or found or any bugs you might have encountered. I&#8217;m really excited about using this functionality and have already been successfully incorporating it in our enterprise software with great success. Enjoy!</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:8eb9d37f-1541-4f29-b6f4-1eea890d4876:faba7f25-9c43-409f-bd69-d35e7a5611a4" class="wlWriterEditableSmartContent">
<div><a href="http://www.chadscharf.com/wp-content/uploads/2009/11/UserControlPageMethods.zip" target="_self"> Source Code &#8211; UserControlPageMethods.zip &#8211; (130 KB)</a></div>
</p>
</div>
<p>~ Chad.</p>
<p><a href="http://www.chadscharf.com/index.php/2009/11/creating-a-page-method-scriptmethod-within-an-ascx-user-control-using-ajax-json-base-classes-and-reflection/">Creating a Page method (ScriptMethod) within an ASCX user control using AJAX, JSON, base classes and reflection</a> is a post from: <a href="http://www.chadscharf.com">Chad Scharf&#039;s Weblog</a>. For software consulting services please visit <a href="http://www.scharfholdings.com">Scharf Holdings, LLC</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.chadscharf.com/index.php/2009/11/creating-a-page-method-scriptmethod-within-an-ascx-user-control-using-ajax-json-base-classes-and-reflection/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>3-State CheckBox using Microsoft AJAX</title>
		<link>http://www.chadscharf.com/index.php/2008/10/3-state-checkbox-using-microsoft-ajax/</link>
		<comments>http://www.chadscharf.com/index.php/2008/10/3-state-checkbox-using-microsoft-ajax/#comments</comments>
		<pubDate>Thu, 30 Oct 2008 09:53:00 +0000</pubDate>
		<dc:creator>Chad</dc:creator>
				<category><![CDATA[ASP.NET Development]]></category>
		<category><![CDATA[The Client Side]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://chadscharf.com/post.aspx?id=565b0d14-08af-4b2d-8677-11163000d088</guid>
		<description><![CDATA[Preview Blank (or unset): , Checked (or granted): , and unchecked (or denied): . I recently had some very difficult requirements to fulfill on an access control and configuration application with a web front end. Those of you who have designed or implemented access control interfaces know this is a daunting task, especially when the [...]<p><a href="http://www.chadscharf.com/index.php/2008/10/3-state-checkbox-using-microsoft-ajax/">3-State CheckBox using Microsoft AJAX</a> is a post from: <a href="http://www.chadscharf.com">Chad Scharf&#039;s Weblog</a>. For software consulting services please visit <a href="http://www.scharfholdings.com">Scharf Holdings, LLC</a></p>
]]></description>
			<content:encoded><![CDATA[<h2>Preview</h2>
<p>Blank (or unset): <img src="/files/102908_0521_Ajax3statec3.gif" alt="blank" width="13" height="13" />, Checked (or granted): <img src="/files/102908_0521_Ajax3statec1.gif" alt="checked" width="13" height="13" />, and unchecked (or denied): <img src="/files/102908_0521_Ajax3statec2.gif" alt="unchecked" width="13" height="13" />.</p>
<p>I recently had some very difficult requirements to fulfill on an access control and configuration application with a web front end. Those of you who have designed or implemented access control interfaces know this is a daunting task, especially when the access control needs to be fairly flexible. Although it&#8217;s easy to implement a user interface that directly represents your data model, your users may not always be able to easily use or understand how to accomplish tasks using it. Usability is important to consider when tackling complex concepts or data structures through web UI.</p>
<p>The requirements for our security model were for granting or denying access to specific data elements in the database. By default a user has access to everything. If you explicitly grant access to an element, the user then only has access to those elements you&#8217;ve explicitly granted access to. You can also deny access to a given element; however a single element can only have one preference state, un-specified, grant access, or deny access. To top it all off, all the elements are in a recursive tree structure (always makes things more fun).</p>
<p>I had immediately made the decision that whatever we did, it needed to be in a tree fashion to show the end user the structure of what they were granting access to, however the question remained as to how to represent each state in an intuitive and easy to understand way. Enter the 3-State check box.<span id="more-6"></span></p>
<h2>Checkboxes only have 2 states</h2>
<p>This is a very real statement, and there is no way around it. Although you can typically represent a 3<sup>rd</sup> pseudo state by setting the checkbox&#8217;s disabled property, this may not always be intuitive to the end user as to what the intention of this state really is. To solve this I first needed to conceptualize what this 3<sup>rd</sup> state looks like, and bingo! Here are the 3 states, which I created in Adobe Photoshop from a screen shot of a normal checkbox; Blank (or unset): <img src="/files/102908_0521_Ajax3statec3.gif" alt="blank" width="13" height="13" />, Checked (or granted): <img src="/files/102908_0521_Ajax3statec1.gif" alt="checked" width="13" height="13" />, and unchecked (or denied): <img src="/files/102908_0521_Ajax3statec2.gif" alt="unchecked" width="13" height="13" />.</p>
<h2>Why AJAX?</h2>
<p>Given that I&#8217;ve decided to create a new server control to handle my 3-state check-box, I need to make some decisions about its behavior. The Microsoft AJAX library in .NET 3.5 offers some powerful APIs for implementing your own behaviors, wiring events and using well-fashioned OO JavaScript among other features. Since on my screen in particular I wasn&#8217;t sure if I wanted to use a WCF service on the checkbox&#8217;s changed event to update the database, or if I wanted a full or partial post-back to completely rebind the tree after a click, the control needed to be as flexable as possible and easily scripted both on the client and server. Because I needed to manage both client and server side behavior in a consistent manner, I decided to go the MS AJAX route.</p>
<h2>The good stuff</h2>
<p>The first step in creating my server control was to create a class library project to put my server control in. I&#8217;m using the .NET 3.5 framework and used the ASP.NET AJAX server control project template to create my new project. After creating a directory for the images in their own folder, I set their build action in the properties to &#8220;Embedded Resource&#8221;. I also had to remove the [WebResource] and [ScriptResource] assembly attributes from the AssemblyInfo.cs file (I like putting these on their relevant pages). Next I need to create my server control. The first thing I do is allocate my embedded resources as web resources at the top of the code page under the using statements and before my namespace declaration. I do this simply as a preference to keep embedded resources together with the specific code page that is using them. If they&#8217;re more universal to your project you may want to put this back in the AssemblyInfo.cs file.</p>
<p><span style="font-size: 10pt; font-family: 'Courier New'">[<span style="color: blue">assembly</span>: System.Web.UI.<span style="color: #2b91af">WebResource</span>(<span style="color: #a31515">"ChadScharf.ThreeStateCheckBox.images.blank.gif"</span>, <span style="color: #a31515">"image/gif"</span>)]</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">[<span style="color: blue">assembly</span>: System.Web.UI.<span style="color: #2b91af">WebResource</span>(<span style="color: #a31515">"ChadScharf.ThreeStateCheckBox.images.checked.gif"</span>, <span style="color: #a31515">"image/gif"</span>)]</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">[<span style="color: blue">assembly</span>: System.Web.UI.<span style="color: #2b91af">WebResource</span>(<span style="color: #a31515">"ChadScharf.ThreeStateCheckBox.images.unchecked.gif"</span>, <span style="color: #a31515">"image/gif"</span>)]</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">[<span style="color: blue">assembly</span>: System.Web.UI.<span style="color: #2b91af">WebResource</span>(<span style="color: #a31515">"ChadScharf.ThreeStateCheckBox.ThreeStateCheckBox.js"</span>, <span style="color: #a31515">"text/javascript"</span>, PerformSubstitution = <span style="color: blue">true</span>)]</span></p>
<h3>Server Control, ThreeStateCheckBox</h3>
<p>The ThreeStateCheckBox server control inherits System.Web.UI.WebControls.CompositeControl (since I&#8217;ll be using child controls and need a wrapper tag, this was the easiest way to get started). I&#8217;m also going to explicitly implement the System.Web.UI.INamingContainer and System.Web.UI.IScriptControl (since we&#8217;re using AJAX behaviors).</p>
<p><span style="font-size: 10pt; font-family: 'Courier New'">[<span style="color: #2b91af">PersistChildren</span>(<span style="color: blue">false</span>)]</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">[<span style="color: #2b91af">ParseChildren</span>(<span style="color: blue">true</span>)]</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">[<span style="color: #2b91af">ToolboxData</span>(<span style="color: #a31515">@"&lt;{0}:ThreeStateCheckBox runat=""server""&gt; &lt;/{0}:ThreeStateCheckBox&gt;"</span>)]</span></p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">public</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">class</span> <span style="color: #2b91af">ThreeStateCheckBox</span> : <span style="color: #2b91af">CompositeControl</span>, <span style="color: #2b91af">INamingContainer</span>, <span style="color: #2b91af">IScriptControl</span></span></p>
<p>I need 2 child controls to manage the checkbox, an ImageButton control and a HiddenField control. The ImageButton will be the actual checkbox. The HiddenField control will represent our client-side state of the checkbox control, therefore our script can modify its value and track it across post-backs if several changes to several of our controls are made at once.</p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">protected</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: #2b91af">ImageButton</span> checkBox;</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">protected</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: #2b91af">HiddenField</span> hidden;</span></p>
<p>Next, I need a private ScriptManager property with a getter. Since this is an AJAX dependant control, it requires that a ScriptManager control be on the page it&#8217;s on, therefore we use something like this:</p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">private</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: #2b91af">ScriptManager</span> ScriptManager</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">{</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">get</span></span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">{</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: #2b91af">ScriptManager</span> manager = <span style="color: #2b91af">ScriptManager</span>.GetCurrent(<span style="color: blue">this</span>.Page);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (manager == <span style="color: blue">null</span>)</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">throw</span> <span style="color: blue">new</span> <span style="color: #2b91af">InvalidOperationException</span>(<span style="color: blue">string</span>.Format(System.Globalization.<span style="color: #2b91af">CultureInfo</span>.InvariantCulture, <span style="color: #a31515">&#8220;The control with ID &#8216;{0}&#8217; requires a ScriptManager on the page. The ScriptManager must appear before any controls that need it.&#8221;</span>, <span style="color: blue">new</span> <span style="color: blue">object</span>[] { <span style="color: blue">this</span>.ID }));</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">return</span> manager;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
<p>Now, I needed to decide what properties would be relevant for working with the control. CompositeControl already exposes some properties relevant to style and CssClass, however we need more meaty, behavioral properties. We&#8217;ll start with the reasoning that we may not want to post-back when the checkbox is clicked, so let&#8217;s add a Boolean AutoPostBack property, which we&#8217;ll store in ViewState. Next let&#8217;s expose the ImageButton&#8217;s CausesValidation property (common among other controls that AutoPostBack such as a DropDownList or CheckBox). Since it could cause validation, we need to expose the ImageButton&#8217;s ValidationGroup property. Next to last we need to convey the state of the checkbox, so we&#8217;ll expose an enumeration value representing the Checked state, called Checked. This could be a number 0 through 2 or any other relevant property if you wish to change it. We&#8217;ll store the Checked state as a string in the HiddenField&#8217;s Value property. Finally, I need to be able to assign a data key value to my checkbox so if there is a key, user id, or other relevant data related to this checkbox I can easily pass it around on the client side as well as the server side if we put it in a more complex container control such as a TreeView, etc. The DataKey value will be stored in our ImageButton&#8217;s CommandArgument value so we can easily retrieve it later.</p>
<h3>Event Handling</h3>
<p>In my <span style="font-size: 10pt; color: blue; font-family: 'Courier New'">protected</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">override</span> <span style="color: blue">void</span> CreateChildControls()</span> I&#8217;m going to wire up the ImageButton&#8217;s Command event and handle that in my server side code. That in turn will check the current Checked state, and change it appropriately, then call OnCheckChanged, which will call the public event CheckChanged, triggering any server side delegates from there.</p>
<p>In the PreRender stage of the page&#8217;s lifecycle I&#8217;m going to set the ImageButton&#8217;s ImageUrl property based on the state of the checkbox pulling from the embedded resource images that we set up earlier. Then, the more important stage of this is to use our IScriptControl interface implementation to register the control with the ScriptManager and register the ScriptDescriptors (we&#8217;ll get to that shortly, but we need a call to it anyway).</p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">base</span><span style="font-size: 10pt; font-family: 'Courier New'">.OnPreRender(e);</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">switch</span><span style="font-size: 10pt; font-family: 'Courier New'"> (Checked)</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">{</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">case</span> <span style="color: #2b91af">CheckedState</span>.Blank:</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">checkBox.ImageUrl = Page.ClientScript.GetWebResourceUrl(<span style="color: blue">this</span>.GetType(), <span style="color: #a31515">&#8220;ChadScharf.ThreeStateCheckBox.images.blank.gif&#8221;</span>);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">break</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">case</span> <span style="color: #2b91af">CheckedState</span>.Checked:</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">checkBox.ImageUrl = Page.ClientScript.GetWebResourceUrl(<span style="color: blue">this</span>.GetType(), <span style="color: #a31515">&#8220;ChadScharf.ThreeStateCheckBox.images.checked.gif&#8221;</span>);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">break</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">case</span> <span style="color: #2b91af">CheckedState</span>.Unchecked:</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">checkBox.ImageUrl = Page.ClientScript.GetWebResourceUrl(<span style="color: blue">this</span>.GetType(), <span style="color: #a31515">&#8220;ChadScharf.ThreeStateCheckBox.images.unchecked.gif&#8221;</span>);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">break</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">this</span><span style="font-size: 10pt; font-family: 'Courier New'">.ScriptManager.RegisterScriptControl&lt;<span style="color: #2b91af">ThreeStateCheckBox</span>&gt;(<span style="color: blue">this</span>);</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">this</span><span style="font-size: 10pt; font-family: 'Courier New'">.ScriptManager.RegisterScriptDescriptors(<span style="color: blue">this</span>);</span></p>
<h3>IScriptControl Interface Implementation</h3>
<p>There are 2 methods in the IScriptControl interface, <span style="font-size: 10pt; color: #2b91af; font-family: 'Courier New'">IEnumerable</span><span style="font-size: 10pt; font-family: 'Courier New'">&lt;<span style="color: #2b91af">ScriptReference</span>&gt; GetScriptReferences()</span>, and<span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: #2b91af">IEnumerable</span>&lt;<span style="color: #2b91af">ScriptDescriptor</span>&gt; GetScriptDescriptors()</span>. GetScriptReferences simply returns an enumerable list of script references, in our case we only need one:</p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">yield</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">return</span> <span style="color: blue">new</span> <span style="color: #2b91af">ScriptReference</span>(<span style="color: #a31515">&#8220;ChadScharf.ThreeStateCheckBox.ThreeStateCheckBox.js&#8221;</span>, <span style="color: #a31515">&#8220;ChadScharf.ThreeStateCheckBox&#8221;</span>);</span></p>
<p>And GetScriptDescriptors returns a enumerable list of ScriptDescriptor, in our case a ScriptControlDescriptor that we&#8217;re going to use to initialize our new type client-side in the AJAX framework, setting specific properties to the client instance so it matches our server-side instance.</p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">if</span><span style="font-size: 10pt; font-family: 'Courier New'"> (<span style="color: blue">this</span>.Page != <span style="color: blue">null</span> &amp;&amp; <span style="color: blue">this</span>.Visible)</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">{</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: #2b91af">ScriptControlDescriptor</span> desc = <span style="color: blue">new</span> <span style="color: #2b91af">ScriptControlDescriptor</span>(<span style="color: #a31515">&#8220;ChadScharf._ThreeStateCheckBox&#8221;</span>, <span style="color: blue">this</span>.ClientID);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">desc.AddProperty(<span style="color: #a31515">&#8220;checked&#8221;</span>, <span style="color: blue">this</span>.Checked.ToString());</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">desc.AddProperty(<span style="color: #a31515">&#8220;imgBlank&#8221;</span>, <span style="color: blue">this</span>.Page.ClientScript.GetWebResourceUrl(<span style="color: blue">this</span>.GetType(), <span style="color: #a31515">&#8220;ChadScharf.ThreeStateCheckBox.images.blank.gif&#8221;</span>));</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">desc.AddProperty(<span style="color: #a31515">&#8220;imgChecked&#8221;</span>, <span style="color: blue">this</span>.Page.ClientScript.GetWebResourceUrl(<span style="color: blue">this</span>.GetType(), <span style="color: #a31515">&#8220;ChadScharf.ThreeStateCheckBox.images.checked.gif&#8221;</span>));</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">desc.AddProperty(<span style="color: #a31515">&#8220;imgUnchecked&#8221;</span>, <span style="color: blue">this</span>.Page.ClientScript.GetWebResourceUrl(<span style="color: blue">this</span>.GetType(), <span style="color: #a31515">&#8220;ChadScharf.ThreeStateCheckBox.images.unchecked.gif&#8221;</span>));</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">desc.AddProperty(<span style="color: #a31515">&#8220;buttonId&#8221;</span>, <span style="color: blue">this</span>.checkBox.ClientID);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">desc.AddProperty(<span style="color: #a31515">&#8220;autoPostBack&#8221;</span>, <span style="color: blue">this</span>.AutoPostBack);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">desc.AddProperty(<span style="color: #a31515">&#8220;hiddenFieldId&#8221;</span>, <span style="color: blue">this</span>.hidden.ClientID);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">desc.AddProperty(<span style="color: #a31515">&#8220;dataKey&#8221;</span>, <span style="color: blue">this</span>.DataKey);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">yield</span> <span style="color: blue">return</span> desc;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
<h2>Client Side Script</h2>
<p>Now it&#8217;s time to create our client behavior, YAY! JavaScript is every web developers favorite technology to work with (GAG!), so I&#8217;ll try to keep this part as simplistic as possible and if you don&#8217;t want to learn the &#8220;why&#8221; and &#8220;how&#8221; you can simply lift the code and be happy <img src='http://www.chadscharf.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> . No one will blame you.</p>
<p>As you can see earlier I referenced my script file as an embedded resource using the WebResource directive, passing PerformSubstitution = true. This is not imperitive, however I like the Substitution ability with embedded web resources so you can reference other embedded resources without having to write code to do so (e.g. in embedded CSS files referencing embedded images, etc). I use this to set the 3 image URLs appropriately in the JS file.</p>
<p>The first thing I do in my behavior script is reference the MicrosoftAjax.js file so I can have intellisense (THANK YOU VS 2008!) and register the client-side namespace for my behavior:</p>
<p><span style="font-size: 10pt; color: green; font-family: 'Courier New'">/// &lt;reference name=&#8221;MicrosoftAjax.js&#8221;/&gt;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">Type.registerNamespace(<span style="color: #a31515">&#8216;ChadScharf&#8217;</span>);</span></p>
<p>I won&#8217;t go into too many details on specifying the client side behavior code however I&#8217;ll try to give a good overview.</p>
<p>The next thing I want to do is declare my constructor for my behavior &#8220;type&#8221;. In the constructor function I&#8217;m going to specify defaults for all my private properties:</p>
<p><span style="font-size: 10pt; font-family: 'Courier New'">ChadScharf._ThreeStateCheckBox = <span style="color: blue">function</span> ChadScharf$_ThreeStateCheckBox(element) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._checked = <span style="color: #a31515">&#8216;Blank&#8217;</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._buttonId = <span style="color: blue">null</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._hiddenFieldId = <span style="color: blue">null</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._autoPostBack = <span style="color: blue">false</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._clickHandler = <span style="color: blue">null</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._dataKey = <span style="color: blue">null</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._imgBlank = <span style="color: #a31515">&#8216;&lt;%=WebResource(&#8220;ChadScharf.ThreeStateCheckBox.images.blank.gif&#8221;)%&gt;&#8217;</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._imgChecked = <span style="color: #a31515">&#8216;&lt;%=WebResource(&#8220;ChadScharf.ThreeStateCheckBox.images.blank.gif&#8221;)%&gt;&#8217;</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._imgUnchecked = <span style="color: #a31515">&#8216;&lt;%=WebResource(&#8220;ChadScharf.ThreeStateCheckBox.images.blank.gif&#8221;)%&gt;&#8217;</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: green">// Call base initializer</span></span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">ChadScharf._ThreeStateCheckBox.initializeBase(<span style="color: blue">this</span>, [element]);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
<p>If you&#8217;ll notice, the type name, ChadScharf._ThreeStateCheckBox is the same as we have in our GetScriptDescriptors() method on the server side, and you&#8217;ll also notice some commonalities in the properties we&#8217;re setting there using the AddProperty method. This is a neat feature of the AJAX framework for writing custom behaviors and makes your client code work more like your server code with far fewer headaches. The most important part here is to call our base initialization method (OO JavaScript and Inheritance rocks!).</p>
<p>Next are all the property accessors for the client control behavior. In the MS AJAX model, we use the syntax get_propertyName() {}, and set_propertyName(value) {}, where propertyName is the actual name of the property. The framework automatically implies these are get and set property accessors (pretty neat!).</p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$get_checked() {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (arguments.length !== 0) { <span style="color: blue">throw</span> Error.parameterCount(); }</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">return</span> <span style="color: blue">this</span>._checked;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$set_checked(value) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._checked = value;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> ($get(<span style="color: blue">this</span>._buttonId)) { $get(<span style="color: blue">this</span>._buttonId).setAttribute(<span style="color: #a31515">&#8216;checked&#8217;</span>, value); }</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> ((<span style="color: blue">this</span>._hiddenFieldId) &amp;&amp; $get(<span style="color: blue">this</span>._hiddenFieldId)) { $get(<span style="color: blue">this</span>._hiddenFieldId).value = value; }</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$get_imgBlank() {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (arguments.length !== 0) { <span style="color: blue">throw</span> Error.parameterCount(); }</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">return</span> <span style="color: blue">this</span>._imgBlank;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$set_imgBlank(value) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._imgBlank = value;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$get_imgChecked() {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (arguments.length !== 0) { <span style="color: blue">throw</span> Error.parameterCount(); }</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">return</span> <span style="color: blue">this</span>._imgChecked;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$set_imgChecked(value) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._imgChecked = value;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$get_imgUnchecked() {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (arguments.length !== 0) { <span style="color: blue">throw</span> Error.parameterCount(); }</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">return</span> <span style="color: blue">this</span>._imgUnchecked;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$set_imgUnchecked(value) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._imgUnchecked = value;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$get_buttonId() {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (arguments.length !== 0) { <span style="color: blue">throw</span> Error.parameterCount(); }</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">return</span> <span style="color: blue">this</span>._buttonId;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$set_buttonId(value) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._buttonId = value;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$get_autoPostBack() {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (arguments.length !== 0) { <span style="color: blue">throw</span> Error.parameterCount(); }</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">return</span> <span style="color: blue">this</span>._autoPostBack;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$set_autoPostBack(value) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._autoPostBack = value;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$get_hiddenFieldId() {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (arguments.length !== 0) { <span style="color: blue">throw</span> Error.parameterCount(); }</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">return</span> <span style="color: blue">this</span>._hiddenFieldId;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$set_hiddenFieldId(value) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._hiddenFieldId = value;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$get_dataKey() {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (arguments.length !== 0) { <span style="color: blue">throw</span> Error.parameterCount(); }</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">return</span> <span style="color: blue">this</span>._dataKey;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$set_dataKey(value) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._dataKey = value;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
<p>WOW!â€¦ that was a lot of getters and setters. Now we need to expose our checkChanged event so other components or client scripts can consume our events using event handlers. In this case the add_ and remove_ prefixes next to our method&#8217;s that take a single parameter (handler) act similarly to our getters and setters, they are simply for adding or removing an event handler to a specific event of your element, and since our base type exposes the get_events() method, which allows us to add or remove handlers to our Sys.UI.Control, this is all the code we need to accomplish this feat:</p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$add_checkChanged(handler) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>.get_events().addHandler(<span style="color: #a31515">&#8216;checkChanged&#8217;</span>, handler);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$remove_checkChanged(handler) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>.get_events().removeHandler(<span style="color: #a31515">&#8216;checkChanged&#8217;</span>, handler);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
<p>Next we need our own event handler methods for when our image button is clicked and when our checked state is changed:</p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$_onButtonClick(eventElement) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">switch</span> (<span style="color: blue">this</span>._checked) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">case</span> <span style="color: #a31515">&#8216;Blank&#8217;</span>:</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._checked = <span style="color: #a31515">&#8216;Checked&#8217;</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">eventElement.target.src = <span style="color: blue">this</span>._imgChecked;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">break</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">case</span> <span style="color: #a31515">&#8216;Checked&#8217;</span>:</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._checked = <span style="color: #a31515">&#8216;Unchecked&#8217;</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">eventElement.target.src = <span style="color: blue">this</span>._imgUnchecked;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">break</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">case</span> <span style="color: #a31515">&#8216;Unchecked&#8217;</span>:</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._checked = <span style="color: #a31515">&#8216;Blank&#8217;</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">eventElement.target.src = <span style="color: blue">this</span>._imgBlank;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">break</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">eventElement.target.setAttribute(<span style="color: #a31515">&#8216;checked&#8217;</span>, <span style="color: blue">this</span>._checked);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">$get(<span style="color: blue">this</span>._hiddenFieldId).value = <span style="color: blue">this</span>._checked;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (!<span style="color: blue">this</span>._autoPostBack) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">eventElement.preventDefault();</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._onCheckChanged();</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$_onCheckChanged() {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">var</span> handler = <span style="color: blue">this</span>.get_events().getHandler(<span style="color: #a31515">&#8216;checkChanged&#8217;</span>);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (handler) {handler(<span style="color: blue">this</span>, Sys.EventArgs.Empty)};</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
<p>We also need our most important initialize and dispose methods to clean up our event handlers and delegates to prevent memory leaks in IE:</p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$dispose() {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: green">// IDisposable</span></span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (<span style="color: blue">this</span>._clickHandler &amp;&amp; $get(<span style="color: blue">this</span>._buttonId)) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">$removeHandler($get(<span style="color: blue">this</span>._buttonId), <span style="color: #a31515">&#8216;click&#8217;</span>, <span style="color: blue">this</span>._clickHandler);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._clickHandler = <span style="color: blue">null</span>;</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">ChadScharf._ThreeStateCheckBox.callBaseMethod(<span style="color: blue">this</span>, <span style="color: #a31515">&#8216;dispose&#8217;</span>);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">function</span><span style="font-size: 10pt; font-family: 'Courier New'"> ChadScharf$_ThreeStateCheckBox$initialize() {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: green">// Initializer</span></span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">ChadScharf._ThreeStateCheckBox.callBaseMethod(<span style="color: blue">this</span>, <span style="color: #a31515">&#8216;initialize&#8217;</span>);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">if</span> (!<span style="color: blue">this</span>._autoPostBack) {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: blue">this</span>._clickHandler = Function.createDelegate(<span style="color: blue">this</span>, <span style="color: blue">this</span>._onButtonClick)</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">$addHandler($get(<span style="color: blue">this</span>._buttonId), <span style="color: #a31515">&#8216;click&#8217;</span>, <span style="color: blue">this</span>._clickHandler);</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
<h3>Implement the behavior</h3>
<p>Finally in order to register our control behavior and make it useable we need to create the prototype for it and then register it, specifying its inheritance). The prototype will stage the public properties and methods from our type definition above and package it in a nice neat container that we can register with the ScriptManager and the AJAX framework for use in our code elsewhere.</p>
<p><span style="font-size: 10pt; font-family: 'Courier New'">ChadScharf._ThreeStateCheckBox.prototype = {</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">get_checked: ChadScharf$_ThreeStateCheckBox$get_checked,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">set_checked: ChadScharf$_ThreeStateCheckBox$set_checked,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">get_imgBlank: ChadScharf$_ThreeStateCheckBox$get_imgBlank,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">set_imgBlank: ChadScharf$_ThreeStateCheckBox$set_imgBlank,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">get_imgChecked: ChadScharf$_ThreeStateCheckBox$get_imgChecked,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">set_imgChecked: ChadScharf$_ThreeStateCheckBox$set_imgChecked,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">get_imgUnchecked: ChadScharf$_ThreeStateCheckBox$get_imgUnchecked,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">set_imgUnchecked: ChadScharf$_ThreeStateCheckBox$set_imgUnchecked,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">get_buttonId: ChadScharf$_ThreeStateCheckBox$get_buttonId,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">set_buttonId: ChadScharf$_ThreeStateCheckBox$set_buttonId,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">get_autoPostBack: ChadScharf$_ThreeStateCheckBox$get_autoPostBack,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">set_autoPostBack: ChadScharf$_ThreeStateCheckBox$set_autoPostBack,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">get_hiddenFieldId: ChadScharf$_ThreeStateCheckBox$get_hiddenFieldId,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">set_hiddenFieldId: ChadScharf$_ThreeStateCheckBox$set_hiddenFieldId,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">get_dataKey: ChadScharf$_ThreeStateCheckBox$get_dataKey,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">set_dataKey: ChadScharf$_ThreeStateCheckBox$set_dataKey,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">add_checkChanged: ChadScharf$_ThreeStateCheckBox$add_checkChanged,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">remove_checkChanged: ChadScharf$_ThreeStateCheckBox$remove_checkChanged,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">_onButtonClick: ChadScharf$_ThreeStateCheckBox$_onButtonClick,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">_onCheckChanged: ChadScharf$_ThreeStateCheckBox$_onCheckChanged,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">dispose: ChadScharf$_ThreeStateCheckBox$dispose,</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">initialize: ChadScharf$_ThreeStateCheckBox$initialize</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">ChadScharf._ThreeStateCheckBox.registerClass(<span style="color: #a31515">&#8216;ChadScharf._ThreeStateCheckBox&#8217;</span>, Sys.UI.Control);</span></p>
<h2>Finally</h2>
<p>Finally! Now that I&#8217;ve probably copied and pasted WAY too much code in my blog post we get ready to do the final implementation of our three state checkbox control, consume it in a web page.</p>
<p>We&#8217;ll start by creating a web site in VS 2008, and adding a project reference to our class library. Then, in the Web.config file we&#8217;ll add a simple entry so we can use our new control without any other code in any of the pages:</p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">&lt;</span><span style="font-size: 10pt; color: #a31515; font-family: 'Courier New'">pages</span><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">&gt;</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">&lt;</span><span style="font-size: 10pt; color: #a31515; font-family: 'Courier New'">controls</span><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">&gt;</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">â€¦</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">&lt;</span><span style="font-size: 10pt; color: #a31515; font-family: 'Courier New'">add</span><span style="font-size: 10pt; color: blue; font-family: 'Courier New'"> </span><span style="font-size: 10pt; color: red; font-family: 'Courier New'">tagPrefix</span><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">=</span><span style="font-size: 10pt; font-family: 'Courier New'">&#8220;<span style="color: blue">chad</span>&#8220;<span style="color: blue"> </span><span style="color: red">namespace</span><span style="color: blue">=</span>&#8220;<span style="color: blue">ChadScharf.ThreeStateCheckBox</span>&#8220;<span style="color: blue"> </span><span style="color: red">assembly</span><span style="color: blue">=</span>&#8220;<span style="color: blue">ChadScharf.ThreeStateCheckBox</span>&#8220;<span style="color: blue">/&gt;</span></span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">&lt;/</span><span style="font-size: 10pt; color: #a31515; font-family: 'Courier New'">controls</span><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">&gt;</span><br />
<span style="font-size: 10pt; color: blue; font-family: 'Courier New'">&lt;/</span><span style="font-size: 10pt; color: #a31515; font-family: 'Courier New'">pages</span><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">&gt;</span></p>
<p>Now with that out of the way, we can test the new control by putting it on a page:</p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">&lt;</span><span style="font-size: 10pt; color: #a31515; font-family: 'Courier New'">chad</span><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">:</span><span style="font-size: 10pt; color: #a31515; font-family: 'Courier New'">ThreeStateCheckBox</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: red">ID</span><span style="color: blue">=&#8221;MyCheckBox&#8221;</span> <span style="color: red">runat</span><span style="color: blue">=&#8221;server&#8221;</span> <span style="color: red">AutoPostBack</span><span style="color: blue">=&#8221;false&#8221;</span> <span style="color: red">CausesValidation</span><span style="color: blue">=&#8221;false&#8221;</span> <span style="color: blue">/&gt;</span></span></p>
<p>Of course, I could wire up an event to it as well, such as the CheckChanged event. This event will only be called if AutoPostBack is set to true.</p>
<p><span style="font-size: 10pt; color: red; font-family: 'Courier New'">OnCheckChanged</span><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">=&#8221;MyCheckBox_CheckChanged&#8221;</span></p>
<p><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">protected</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">void</span> MyCheckBox_CheckChanged(<span style="color: blue">object</span> sender, <span style="color: #2b91af">EventArgs</span> e)</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">{</span><br />
<span style="font-size: 10pt; font-family: 'Courier New'"><span style="color: green">// &#8230;</span></span><br />
<span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
<p>You can control whether your control posts back or not by setting AutoPostBack=&#8221;true&#8221; or &#8220;false&#8221;. If you set it to &#8220;false&#8221; (the default), your page will not post-back when you click the checkbox, but you should see the state change instantly, and if another control, like a button, causes a post-back, you will also notice the server side state of the control has changed as well!</p>
<h2>That&#8217;s it</h2>
<p>This was simply a high level overview; however you can always download the entire source code <a href="/files/ThreeStateCheckBox.zip">here</a>. Feel free to modify the images, scripts etc or just let me know what you think. This is definately a quick-fix for a not-so-simple business requirements problem using creative design. The 3-stage checkbox is a bit more common in windows forms applications and I&#8217;ve seen a lot of requests for this type of control on web development forums, typically asking how you would do a tree showing not all the options under a parent node are checked/selected. This could be done by simply altering the 3rd state of the checkbox and image to reflect whatever you wanted it to.</p>
<p><a href="http://www.chadscharf.com/index.php/2008/10/3-state-checkbox-using-microsoft-ajax/">3-State CheckBox using Microsoft AJAX</a> is a post from: <a href="http://www.chadscharf.com">Chad Scharf&#039;s Weblog</a>. For software consulting services please visit <a href="http://www.scharfholdings.com">Scharf Holdings, LLC</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.chadscharf.com/index.php/2008/10/3-state-checkbox-using-microsoft-ajax/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Creating a JavaScript HashTable</title>
		<link>http://www.chadscharf.com/index.php/2008/05/creating-a-javascript-hashtable/</link>
		<comments>http://www.chadscharf.com/index.php/2008/05/creating-a-javascript-hashtable/#comments</comments>
		<pubDate>Fri, 02 May 2008 20:10:00 +0000</pubDate>
		<dc:creator>Chad</dc:creator>
				<category><![CDATA[ASP.NET Development]]></category>
		<category><![CDATA[The Client Side]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://chadscharf.com/post.aspx?id=c576418c-aa11-4297-ac60-ee72cb8448e3</guid>
		<description><![CDATA[I use a lot of configuration and provider driven services and variables for developing web applications. Let&#8217;s face it, I don&#8217;t like to recompile. I recently had the need to share my Web.config settings with the client code, but didn&#8217;t want to declare a variable for every possible setting, I just wanted to dynamically create [...]<p><a href="http://www.chadscharf.com/index.php/2008/05/creating-a-javascript-hashtable/">Creating a JavaScript HashTable</a> is a post from: <a href="http://www.chadscharf.com">Chad Scharf&#039;s Weblog</a>. For software consulting services please visit <a href="http://www.scharfholdings.com">Scharf Holdings, LLC</a></p>
]]></description>
			<content:encoded><![CDATA[<p>I use a lot of configuration and provider driven services and variables for developing web applications. Let&#8217;s face it, I don&#8217;t like to recompile. I recently had the need to share my Web.config settings with the client code, but didn&#8217;t want to declare a variable for every possible setting, I just wanted to dynamically create the script of configuration settings in some collection and have access to that in my client side code. Because I wanted this collection to act just like a HashTable in System.Collections, I decided to create a JavaScript type to mirror the storage and access paradigm of the HashTable for use in my applications. <span id="more-7"></span></p>
<h3>The Storage Container</h3>
<p>The basic structure of the HashTable is comprised of an enumerable collection of KeyValuePair objects. To mimic this, I had to define my KeyValuePair object on the client. I decided to use Microsoft&#8217;s AJAX Client Library included in the .NET 3.5 Framework.</p>
<p><span style="font-size: 10pt; font-family: Courier New">KeyValuePair = <span style="color: blue">function</span>(key, value) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">KeyValuePair.initializeBase(<span style="color: blue">this</span>); </span><br />
<span style="font-size: 10pt; font-family: Courier New"><span style="color: green">// Add custom initialization here </span></span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: blue">this</span>._key = key; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: blue">this</span>._value = value; </span><br />
<span style="font-size: 10pt; font-family: Courier New">} </span><br />
<span style="font-size: 10pt; font-family: Courier New">KeyValuePair.prototype = { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: green">// Returns the current Dialer Status key </span></span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â get_key : <span style="color: blue">function</span>() { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">return</span> <span style="color: blue">this</span>._key; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â }, </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â set_key : <span style="color: blue">function</span>(key) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">this</span>._key = key; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â }, </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: green">// Returns the next to execute Dialer Command </span></span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â get_value : <span style="color: blue">function</span>() { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">return</span> <span style="color: blue">this</span>._value; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â }, </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â set_value : <span style="color: blue">function</span>(val) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">this</span>._value = val; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â }, </span><br />
<span style="font-size: 10pt; font-family: Courier New">initialize: <span style="color: blue">function</span>() { </span><br />
<span style="font-size: 10pt; font-family: Courier New">KeyValuePair.callBaseMethod(<span style="color: blue">this</span>, <span style="color: #a31515">&#8216;initialize&#8217;</span>); </span><br />
<span style="font-size: 10pt; font-family: Courier New">}, </span><br />
<span style="font-size: 10pt; font-family: Courier New">dispose: <span style="color: blue">function</span>() { </span><br />
<span style="font-size: 10pt; font-family: Courier New">KeyValuePair.callBaseMethod(<span style="color: blue">this</span>, <span style="color: #a31515">&#8216;dispose&#8217;</span>); </span><br />
<span style="font-size: 10pt; font-family: Courier New">} </span><br />
<span style="font-size: 10pt; font-family: Courier New">} </span><br />
<span style="font-size: 10pt; font-family: Courier New">KeyValuePair.descriptor = { </span><br />
<span style="font-size: 10pt; font-family: Courier New">properties: [ {name: <span style="color: #a31515">'key'</span>, type: String}, </span><br />
<span style="font-size: 10pt; font-family: Courier New">{name: <span style="color: #a31515">'value'</span>, type: String} ] </span><br />
<span style="font-size: 10pt; font-family: Courier New">} </span><br />
<span style="font-size: 10pt; font-family: Courier New">KeyValuePair.registerClass(<span style="color: #a31515">&#8216;KeyValuePair&#8217;</span>, Sys.Component); </span></p>
<p>I then had to create the container to wrap a collection, or in JavaScript&#8217;s case an Array, of these KeyValuePair objects and make them indexed, searchable, and easy to use just like the .NET HashTable class.</p>
<p><span style="font-size: 10pt; font-family: Courier New">HashTable = <span style="color: blue">function</span>() { </span><br />
<span style="font-size: 10pt; font-family: Courier New">HashTable.initializeBase(<span style="color: blue">this</span>); </span><br />
<span style="font-size: 10pt; font-family: Courier New"><span style="color: green">// Add custom initialization here </span></span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: blue">this</span>._items = <span style="color: blue">new</span> Array(); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: blue">this</span>._deletedIndexes = <span style="color: blue">new</span> Array(); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: blue">this</span>._isDeleted = <span style="color: blue">function</span>(index) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">for</span> (<span style="color: blue">var</span> i = 0; i &lt; <span style="color: blue">this</span>._deletedIndexes.length; i++) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">if</span> (<span style="color: blue">this</span>._deletedIndexes[i] == index) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">return</span> <span style="color: blue">true</span>; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">return</span> <span style="color: blue">false</span>; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">} </span><br />
<span style="font-size: 10pt; font-family: Courier New">HashTable.prototype = { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: green">// Returns the next to execute Dialer Command </span></span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â get_value : <span style="color: blue">function</span>(key) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">for</span> (<span style="color: blue">var</span> i = 0; i &lt; <span style="color: blue">this</span>._items.length; i++) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">if</span> (!<span style="color: blue">this</span>._isDeleted(i)) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">var</span> item = <span style="color: blue">this</span>._items[i]; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">if</span> (item.get_key() == key){ </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">return</span> item.get_value(); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">return</span> <span style="color: blue">null</span>; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â }, </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â set_value : <span style="color: blue">function</span>(key, val) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">for</span> (<span style="color: blue">var</span> i = 0; i &lt; <span style="color: blue">this</span>._items.length; i++) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">if</span> (!<span style="color: blue">this</span>._isDeleted(i)) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">var</span> item = <span style="color: blue">this</span>._items[i]; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">if</span> (item.get_key() == key){ </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â item.set_value(val); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">this</span>._items[i] = item; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â }, </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â get_count : <span style="color: blue">function</span>() { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">return</span> <span style="color: blue">this</span>._items.length; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â }, </span><br />
<span style="font-size: 10pt; font-family: Courier New">initialize: <span style="color: blue">function</span>() { </span><br />
<span style="font-size: 10pt; font-family: Courier New">HashTable.callBaseMethod(<span style="color: blue">this</span>, <span style="color: #a31515">&#8216;initialize&#8217;</span>); </span><br />
<span style="font-size: 10pt; font-family: Courier New">}, </span><br />
<span style="font-size: 10pt; font-family: Courier New">dispose: <span style="color: blue">function</span>() { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">this</span>._items = <span style="color: blue">null</span>; </span><br />
<span style="font-size: 10pt; font-family: Courier New">HashTable.callBaseMethod(<span style="color: blue">this</span>, <span style="color: #a31515">&#8216;dispose&#8217;</span>); </span><br />
<span style="font-size: 10pt; font-family: Courier New">}, </span><br />
<span style="font-size: 10pt; font-family: Courier New">addPair : <span style="color: blue">function</span>(pair) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">if</span> (pair == <span style="color: blue">null</span>) { <span style="color: blue">return</span>; } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">var</span> exists = <span style="color: blue">this</span>.get_value(pair.get_key()); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">if</span> (exists) { <span style="color: blue">return</span>; } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">this</span>._items.push(pair); </span><br />
<span style="font-size: 10pt; font-family: Courier New">}, </span><br />
<span style="font-size: 10pt; font-family: Courier New">remove : <span style="color: blue">function</span>(key) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">for</span> (<span style="color: blue">var</span> i = 0; i &lt; <span style="color: blue">this</span>._items.length; i++) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">if</span> (!<span style="color: blue">this</span>._isDeleted(i)) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">if</span> (<span style="color: blue">this</span>._items[i].get_key() == key){ </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">this</span>._items[i].set_key(<span style="color: blue">null</span>); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">this</span>._items[i].set_value(<span style="color: blue">null</span>); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">this</span>._deletedIndexes.push(i); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: blue">return</span>; </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">}, </span><br />
<span style="font-size: 10pt; font-family: Courier New">addItem : <span style="color: blue">function</span>(key, value) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">this</span>.addPair(<span style="color: blue">new</span> KeyValuePair(key, value)); </span><br />
<span style="font-size: 10pt; font-family: Courier New">} </span><br />
<span style="font-size: 10pt; font-family: Courier New">} </span><br />
<span style="font-size: 10pt; font-family: Courier New">HashTable.descriptor = { </span><br />
<span style="font-size: 10pt; font-family: Courier New">properties: [ {name: <span style="color: #a31515">'count'</span>, type: Number} ] </span><br />
<span style="font-size: 10pt; font-family: Courier New">} </span><br />
<span style="font-size: 10pt; font-family: Courier New">HashTable.registerClass(<span style="color: #a31515">&#8216;HashTable&#8217;</span>, Sys.Component); </span></p>
<p>And that&#8217;s it! With this new client component I can store configuration entries on the client for use by my page&#8217;s script. I simply do the following on the server, in my code behind in order to create the collection itself.</p>
<p>Client:</p>
<p><span style="font-size: 10pt; color: green; font-family: Courier New">// Declare our global config variable </span><br />
<span style="font-size: 10pt; font-family: Courier New"><span style="color: blue">var</span> Config = <span style="color: blue">new</span> HashTable(); </span></p>
<p>ASP.NET Form:</p>
<p><span style="font-size: 10pt; font-family: Courier New"><span style="background-color: yellow">&lt;%</span><span style="color: blue">=</span>GetConfigScript()<span style="background-color: yellow">%&gt;</span></span></p>
<p>Server:</p>
<p><span style="font-size: 10pt; font-family: Courier New"><span style="color: blue">public</span> <span style="color: blue">string</span> GetConfigScript() </span><br />
<span style="font-size: 10pt; font-family: Courier New">{ </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: #2b91af">StringBuilder</span> script = <span style="color: blue">new</span> <span style="color: #2b91af">StringBuilder</span>(); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â script.AppendLine(<span style="color: #a31515">&#8220;&lt;script type=\&#8221;text/javascript\&#8221;&gt;&#8221;</span>); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â script.AppendLine(<span style="color: #a31515">&#8220;//&lt;![CDATA["</span>); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: blue">foreach</span> (<span style="color: blue">string</span> key <span style="color: blue">in</span> <span style="color: #2b91af">ConfigurationManager</span>.AppSettings.AllKeys) </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â script.AppendFormat(<span style="color: #a31515">"Config.addItem(\"{0}\",\"{1}\");"</span>, </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â key.Replace(<span style="color: #a31515">@"\"</span>, <span style="color: #a31515">@"\\"</span>), </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â Â Â Â Â <span style="color: #2b91af">ConfigurationManager</span>.AppSettings[key].Replace(<span style="color: #a31515">@&#8221;\&#8221;</span>, <span style="color: #a31515">@&#8221;\\&#8221;</span>)); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â script.AppendLine(<span style="color: #a31515">&#8220;//]]&gt;&#8221;</span>); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: blue">return</span> script.ToString(); </span><br />
<span style="font-size: 10pt; font-family: Courier New">} </span></p>
<h3>Conclusion</h3>
<p>Now, whenever I want to access a configuration setting on the client, I call Config.get_value(&#8220;key&#8221;); and it returns that value or null, just like using Configuration.AppSettings["key"] or a HashTable to store values by key, I just happened to use it for configuration settings but it could be used any time I need a searchable HashTable for storing key-value pairs.</p>
<p><a href="http://www.chadscharf.com/index.php/2008/05/creating-a-javascript-hashtable/">Creating a JavaScript HashTable</a> is a post from: <a href="http://www.chadscharf.com">Chad Scharf&#039;s Weblog</a>. For software consulting services please visit <a href="http://www.scharfholdings.com">Scharf Holdings, LLC</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.chadscharf.com/index.php/2008/05/creating-a-javascript-hashtable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Shrinking JavaScript Arrays</title>
		<link>http://www.chadscharf.com/index.php/2008/04/shrinking-javascript-arrays/</link>
		<comments>http://www.chadscharf.com/index.php/2008/04/shrinking-javascript-arrays/#comments</comments>
		<pubDate>Sat, 12 Apr 2008 00:21:00 +0000</pubDate>
		<dc:creator>Chad</dc:creator>
				<category><![CDATA[The Client Side]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://chadscharf.com/post.aspx?id=72c5103c-d331-4815-bc84-4d01d62ca7bc</guid>
		<description><![CDATA[Recently I&#8217;ve found myself writing a ton of client code in a new pure JavaScript/WCF project I am working on. Since most of the programming I&#8217;m doing for the UI is in JavaScript files, I&#8217;ve found myself having to work with the Array object for many different things. The one thing I&#8217;ve noticed however, is [...]<p><a href="http://www.chadscharf.com/index.php/2008/04/shrinking-javascript-arrays/">Shrinking JavaScript Arrays</a> is a post from: <a href="http://www.chadscharf.com">Chad Scharf&#039;s Weblog</a>. For software consulting services please visit <a href="http://www.scharfholdings.com">Scharf Holdings, LLC</a></p>
]]></description>
			<content:encoded><![CDATA[<p>Recently I&#8217;ve found myself writing a ton of client code in a new pure JavaScript/WCF project I am working on. Since most of the programming I&#8217;m doing for the UI is in JavaScript files, I&#8217;ve found myself having to work with the Array object for many different things. The one thing I&#8217;ve noticed however, is that you cannot remove an item from a JavaScript array, say, in the middle of the array and have the array size shrink without losing data at either end, however having to check for array_name[i] != null every single time I iterate the array was getting annoying, to say the least. <span id="more-8"></span></p>
<p>I decided to flex the muscle of the prototype, which in JavaScript allows you to extend a types method and properties. This new method I created, called shrink(), aptly removes all of the nulls from my array and shrinks the total length without losing any data. I&#8217;m not sure how efficient it is, but it works and I no longer have to check for null where at least it doesn&#8217;t make sense to anyway.</p>
<p><span style="font-size: 10pt; font-family: Courier New">Array.prototype.shrink = <span style="color: blue">function</span>() { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: blue">var</span> sync = <span style="color: blue">new</span> Array(); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: blue">while</span> (<span style="color: blue">this</span>.length &gt; 0) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">var</span> obj = <span style="color: blue">this</span>.shift(); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">if</span> (obj !== <span style="color: blue">null</span>) sync.push(obj); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â <span style="color: blue">while</span> (sync.length &gt; 0) { </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">var</span> obj = sync.shift(); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â Â Â Â Â <span style="color: blue">if</span> (obj !== <span style="color: blue">null</span>) <span style="color: blue">this</span>.push(obj); </span><br />
<span style="font-size: 10pt; font-family: Courier New">Â Â Â Â } </span><br />
<span style="font-size: 10pt; font-family: Courier New">}</span></p>
<p><a href="http://www.chadscharf.com/index.php/2008/04/shrinking-javascript-arrays/">Shrinking JavaScript Arrays</a> is a post from: <a href="http://www.chadscharf.com">Chad Scharf&#039;s Weblog</a>. For software consulting services please visit <a href="http://www.scharfholdings.com">Scharf Holdings, LLC</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.chadscharf.com/index.php/2008/04/shrinking-javascript-arrays/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

