Mike Borozdin's Blog

A blog about programming, web and IT in general

Search

 

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© 2008 Mike Borozdin

ASP.NET Image Uploading (part I)

Download files

Introduction

Is image uploading different from simply file uploading? No, but when creating an image uploading functionality you usually have to perform more operation, than if you application were to receive text files only. Basically, when making an image uploading form, you have to implement the following things:

  • Check if the uploaded file is an image
  • Check if the uploaded file doesn't exceed a certain size
  • Resize the uploaded images without changing the proportions of the picture
  • Save the image

In this particular tutorial, I'll tell you how to perform the 3 operations, while I'll explain how to check the file size in the next part.

Form

First, we need to create a form where a user can pick up a file to upload. This form must accept files, thus the enctype attribute should be "multipart/form-data". We can set it directly in the .aspx file.

<form id="form1" runat="server" enctype="multipart/form-data">

However, if we have a master page, we don't probably want it always to have that enctype value, so in this case, we can set it in the code-behind of a particular form:

protected void Page_Load(object sender, EventArgs e)
{
    Form.Enctype = "multipart/form-data";
}

Then, we need to create a form element that is used for choosing a file, this element is a simply HTML input with type="file" and runat="server":

<input id="fileImage" runat="server" type="file" />

After that, we add a CustomValidator that will validate the file type and a submit button:

<asp:CustomValidator ID="valFileType" runat="server" 
    ErrorMessage="This isn't not an image" 
    onservervalidate="valFileType_ServerValidate" /><br />
<asp:Button ID="btnSubmit" runat="server" Text="Upload" 
    onclick="btnSubmit_Click" />

Validation

Since, we cannot access the file input with JavaScript, we can perform only server-side validation. There are two ways of validating the file type, the first one is to check the extension and the second one is to check the mime/type. The first one isn't very reliable, because a smart user can change the file extension, besides there are lot of extensions of JPEG images - .jpg, .jpeg, .jpe, while the mime/type is the only - "image/jpeg". So, we'll be using the second way, i.e. we will be checking the mime type. Here is the code we should write:

protected void valFileType_ServerValidate(object source, ServerValidateEventArgs args)
{
    string[] acceptedTypes = new string[] 
    { 
        "image/bmp", 
        "image/jpeg", 
        "image/tiff", 
        "image/gif", 
        "image/png" 
    };

    if (!acceptedTypes.Contains(fileImage.PostedFile.ContentType))
    {
        args.IsValid = false;
    }
}

There is an interesting thing in this code, we use the Contains() extension method, that checks if a string belongs to a collection.

Processing Image Upload

In order to process image uploading we should simply add some code to the submit button click event handler:

protected void btnSubmit_Click(object sender, EventArgs e)
{
    if (IsValid)
    {
        Bitmap image = ResizeImage(fileImage.PostedFile.InputStream, 200, 400);
        image.Save(Server.MapPath("~/Photos/") + Guid.NewGuid().ToString() + ".jpg", ImageFormat.Jpeg);
    }
}
Here we invoke the ResizeImage() method (we will write it later) that accepts the input stream and the size constrains, i.e., the maximum allowed image with and the maximum allowed image height.
 

Resizing

This is the most interesting part of the tutorial. We won't simply resize images, but we also retain their proportions. Here is the code:

private Bitmap ResizeImage(Stream streamImage, int maxWidth, int maxHeight)
{
    Bitmap originalImage = new Bitmap(streamImage);
    int newWidth = originalImage.Width;
    int newHeight = originalImage.Height;
    double aspectRatio = (double)originalImage.Width / (double)originalImage.Height;

    if (aspectRatio <= 1)
    {
        newWidth = maxWidth;
        newHeight = (int)Math.Round(newWidth / aspectRatio);
    }
    else
    {
        newHeight = maxHeight;
        newWidth =
        newWidth = (int)Math.Round(newHeight * aspectRatio);
    }

    return new Bitmap(originalImage, newWidth, newHeight);
}

 

Now, you can compile the project and test it by uploading some of new images and seeing the resized ones on the server.

Conclusion

Image uploading is very common problem. ASP.NET provides great tools for developers to accomplishing this task. In the next part, I'll show you how to validate the file size that can be very tricky sometimes.

Download files


Posted by Mike Borozdin on Thursday, August 21, 2008 12:42 PM GMT
Add to Technorati Favorites  Kick it!  
Permalink | Comments (1) | Post RSSRSS comment feed

Static Page Methods Instead of Web Services in ASP.NET AJAX Control Toolkit

As you may already know, it is required to create a web service to make use of some ASP.NET AJAX Control Toolkit controls. However, you can use static methods of your pages instead, you just have to mark them with the [System.Web.Services.WebMethod] attribute and not set the ServicePath parameter in the ACT controls.

In the example from my article on CascadingDropDown we used a web service for populating the drop-down lists, now we'll use static methods instead, we can just copy-paste the methods from the web service to the code-behind file of the page and remove the ServicePath parameters from the controls.

Extract from Default.aspx.cs

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    [System.Web.Services.WebMethod]
    public static CascadingDropDownNameValue[] GetContinents(string knownCategoryValues, string category)
    {
        CascadingDropDownNameValue[] continents = new CascadingDropDownNameValue[2];
        continents[0] = new CascadingDropDownNameValue("North America", "North America");
        continents[1] = new CascadingDropDownNameValue("Europe", "Europe");
        return continents;
    }
 
Extract from Default.aspx
<%--No ServicePath attribute here--%>
<cc1:CascadingDropDown ID="cddContinent" runat="server" TargetControlID="ddlContinent" 
    Category="continent" ServiceMethod="GetContinents" />

If you don't need to expose the methods consumed by the ACT controls, then you can use static methods instead of web services.


Posted by Mike Borozdin on Sunday, August 17, 2008 8:15 PM GMT
Add to Technorati Favorites  Kick it!  
Permalink | Comments (1) | Post RSSRSS comment feed

.aspx extension instead of .php? WHY???

This story is not a debate on "ASP.NET vs PHP", but this story is about the people who develop their web applications with PHP, but pretend that they are using ASP.NET. Yes, such people do really exist. I came across their posts in the forums, where they said that or asked how to change the extension of PHP scripts to .aspx.

Why on Earth are they doing that? Basically, they want to look more serious. For some reason, .aspx looks more sophisticated, serious and more enterpisy. The reason is actually well known, ASP.NET usually powers well known companies that everybody look up to.

However, often it's not the developers who want to "be more serious", but their clients who either demand the pages to have the ".aspx" extension or want to the web site to be written with ASP.NET. The latter is the worst case, I believe, because in such a situation, the developer lies to his client. He was hired to build a web site with ASP.NET, but in fact he does with PHP or with something else. I think it is really a lack of work ethic.

This post is partly inspired by the Rick Strahl's article, which is called "ASP.NET gets no Respect", where he puts his thoughts regarding that fact that people and especially the young developers, who are eager to launch their start-up project, simply disregard ASP.NET and prefers to use a more fashionable platform, like Ruby on Rails. While I agree with him on this point, there are people do an opposite thing - write their web sites with PHP and put the ".aspx" extension at the end of their files. <irony>Well, the world is really ridiculous...</irony>


Tags: , ,
Posted by Mike Borozdin on Friday, August 15, 2008 2:54 PM GMT
Add to Technorati Favorites  Kick it!  
Permalink | Comments (15) | Post RSSRSS comment feed

Creating Linked Drop-Down Lists with the CascadingDropDown Control

Download the project files

Creating dependant drop-down lists is a very common task, for example, when making a registration form, you usually have to add a country and a state fields, the contents of the state drop-down depends on the selected item in the country drop down field. Actually, it's not so difficult to implement that with the standard controls of ASP.NET. However if you don't want the page to be reloaded every time a user selects a value in the drop-down list, you should make use of AJAX. While you can use UpdatePanel for this task, it will be difficult if you have 3 or even linked drop-downs. Hopefully, you don't have to add a lot of UpdatePanels, instead you can pick up the CascadingDropDown Control from ASP.NET AJAX Control Toolkit.

You can see the demo here.

CascadingDropDown is an extender for the standard DropDown control that retrieves the data from a web service. In the example, we'll create 4 linked drop-downs - for the continent, for the country, for the territory and for the city.

Continent: <asp:DropDownList ID="ddlContinent" runat="server" />
<cc1:CascadingDropDown ID="cddContinent" runat="server" TargetControlID="ddlContinent" 
    Category="continent" ServicePath="Helper.asmx" ServiceMethod="GetContinents" />
<br />
Country: <asp:DropDownList ID="ddlCountry" runat="server" />
<cc1:CascadingDropDown ID="ccdCountry" runat="server" TargetControlID="ddlCountry" 
    ParentControlID="ddlContinent" Category="country" 
    ServicePath="Helper.asmx" ServiceMethod="GetCountries" />
<br />
Territory: <asp:DropDownList ID="ddlTerritory" runat="server" />
<cc1:CascadingDropDown ID="ccdTerritory" runat="server" TargetControlID="ddlTerritory" 
    ParentControlID="ddlCountry" Category="territory" 
    ServicePath="Helper.asmx" ServiceMethod="GetTerritories" />
<br />
City: <asp:DropDownList ID="ddlCity" runat="server" />
<cc1:CascadingDropDown ID="ccdCity" runat="server" TargetControlID="ddlCity" 
    ParentControlID="ddlTerritory" Category="city" 
    ServicePath="Helper.asmx" ServiceMethod="GetCities" />

 

I must explain some attributes we have here:

ParentControlID - the ID of the parent drop-down control

Category - the key of the collection we parse in a web service. I'll explain it below.

ServicePath - the path to a web service the control gets the data from

ServiceMethod - the name of the method the control invokes to retrieve the data

Let's proceed to the web service now. First, we should mark it with ScriptService attribute:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
[System.Web.Script.Services.ScriptService]
public class Helper : System.Web.Services.WebService

 

Then, the methods we are going to invoke must have the following signature:

 

[WebMethod]
public CascadingDropDownNameValue[] MethodName(string knownCategoryValues, string category)

 

The parameters names should match as well.

knownCategoryValues - contains the values of the all chosen cascading-drop downs. It can be transformed to a collection by CascadingDropDown.ParseKnownCategoryValuesString() method, which return the StringDictionary collection, the keys of the collection math the Category attributes of CascadingDropDowns.

category - contains the value of the Category atttribute of the CascadingDropDown that invokes the current method.

Some sample methods:

[WebMethod]
public CascadingDropDownNameValue[] GetContinents(string knownCategoryValues, string category)
    {
        CascadingDropDownNameValue[] continents = new CascadingDropDownNameValue[2];
        continents[0] = new CascadingDropDownNameValue("North America", "North America");
        continents[1] = new CascadingDropDownNameValue("Europe", "Europe");
        return continents;
    }

[WebMethod]
public CascadingDropDownNameValue[] GetCountries(string knownCategoryValues, string category)
{
    StringDictionary ddlData = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
    string continent = ddlData["continent"];

    List<CascadingDropDownNameValue> countries = new List<CascadingDropDownNameValue>();

    if (continent == "North America")
    {
        countries.Add(new CascadingDropDownNameValue("United States", "United States"));
        countries.Add(new CascadingDropDownNameValue("Canada", "Canada"));
    }
    else if (continent == "Europe")
    {
        countries.Add(new CascadingDropDownNameValue("United Kingdom", "United Kingdom"));
        countries.Add(new CascadingDropDownNameValue("France", "France"));
    }
    else
    {
        countries.Add(new CascadingDropDownNameValue("N/A", "N/A"));
    }

    return countries.ToArray();
}

 

You can download the entire project here.

Conclusion

CascadingDropDown is a very powerful AJAX enabled control that should be used when you have two or more linked drop-down lists. You can read more here and there.


Posted by Mike Borozdin on Wednesday, August 13, 2008 8:34 PM GMT
Add to Technorati Favorites  Kick it!  
Permalink | Comments (1) | Post RSSRSS comment feed

ASP.NET TreeView and Checkboxes

Download the project files.

Although the TreeView control is a very powerful one, there are some pitfalls that you can run into when using it. One of the most popular problem is using checkboxes in TreeView. Despite the fact that you can enable checkboxes by setting ShowCheckBoxes="All" you still have to write a lot of JavaScript code to make it work properly. The problems are:

  • When you check a parent or a branch node the child nodes don't get checked
  • TreeView doesn't generate <label> tags around the nodes text, so when user click on the text next to the checkbox, the latter don't get checked

My solution written with JavaScript and with the help of ASP.NET AJAX library (so, don't forget to put a ScriptManager to your page) solves both problems. You can view the demo here. It was tested in IE, Firefox, Safari and Opera.

There are some other solutions, but they are missing some features, for instance they don't convert a link click to a checkbox selection.

Providing you have a TreeView on your page, you have similar code:

<asp:TreeView ID="someTree" runat="server" ShowCheckBoxes="All">
    <Nodes>
        <asp:TreeNode Text="Root"> 
            <asp:TreeNode Text="Leaf" />
            <asp:TreeNode Text="Branch">
                <asp:TreeNode Text="Leaf" />
                <asp:TreeNode Text="Leaf" />
            </asp:TreeNode>
        </asp:TreeNode>
        <asp:TreeNode Text="Root">
            <asp:TreeNode Text="Leaf" />
            <asp:TreeNode Text="Leaf" />
            <asp:TreeNode Text="Leaf" />
            <asp:TreeNode Text="Leaf" />
        </asp:TreeNode>
    </Nodes>
</asp:TreeView>

You have to put the following code either to the <head> section or to a separate JavaScript file.

<script type="text/javascript">
    var TREEVIEW_ID ="someTree"; //the ID of the TreeView control
    //the constants used by GetNodeIndex()
    var LINK = 0;
    var CHECKBOX = 1;
    
    //this function is executed whenever user clicks on the node text
    function ToggleCheckBox(senderId)
    {
        var nodeIndex = GetNodeIndex(senderId, LINK);
        var checkBoxId = TREEVIEW_ID + "n" + nodeIndex + "CheckBox";
        var checkBox = document.getElementById(checkBoxId);
        checkBox.checked = !checkBox.checked;
        
        ToggleChildCheckBoxes(checkBox);
        ToggleParentCheckBox(checkBox);
    }
    
    //checkbox click event handler
    function checkBox_Click(eventElement)
    {
        ToggleChildCheckBoxes(eventElement.target);
        ToggleParentCheckBox(eventElement.target);
    }
    
    //returns the index of the clicked link or the checkbox
    function GetNodeIndex(elementId, elementType)
    {
         var nodeIndex;
         if(elementType == LINK)
         {
            nodeIndex = elementId.substring((TREEVIEW_ID + "t").length);
         }
         else if (elementType == CHECKBOX)
         {
            nodeIndex = elementId.substring((TREEVIEW_ID + "n").length, elementId.indexOf("CheckBox"));
         }
         return nodeIndex;
    }
    
    //checks or unchecks the nested checkboxes
    function ToggleChildCheckBoxes(checkBox)
    {
        var postfix = "n";
        var childContainerId = TREEVIEW_ID + postfix + GetNodeIndex(checkBox.id, CHECKBOX) + "Nodes";
        var childContainer = document.getElementById(childContainerId);
        if (childContainer)
        {
            var childCheckBoxes = childContainer.getElementsByTagName("input");
            for (var i = 0; i < childCheckBoxes.length; i++)
            {
                childCheckBoxes[i].checked = checkBox.checked;
            }
        }
    }
    
    //unchecks the parent checkboxes if the current one is unchecked
    function ToggleParentCheckBox(checkBox)
    {
        if(checkBox.checked == false)
        {
            var parentContainer = GetParentNodeById(checkBox, TREEVIEW_ID);
            if(parentContainer) 
            {
                var parentCheckBoxId = parentContainer.id.substring(0, parentContainer.id.search("Nodes")) + "CheckBox";
                if($get(parentCheckBoxId) && $get(parentCheckBoxId).type == "checkbox") 
                {
                    $get(parentCheckBoxId).checked = false;
                    ToggleParentCheckBox($get(parentCheckBoxId));
                }
            }
        }
    }
    
    //returns the ID of the parent container if the current checkbox is unchecked
    function GetParentNodeById(element, id)
    {
        var parent = element.parentNode;
        if (parent == null)
        {
            return false;
        }
        if (parent.id.search(id) == -1)
        {
            return GetParentNodeById(parent, id);
        }
        else
        {
            return parent;
        }
    }
</script>

This code should be put to the bottom of the page, that will assign the event handler created above.

<script type="text/javascript">
    var links = document.getElementsByTagName("a");
    for (var i = 0; i < links.length; i++)
    {
        if (links[i].className == TREEVIEW_ID + "_0")
        {
            links[i].href = "javascript:ToggleCheckBox(\"" + links[i].id + "\");";
        }
    }
    
    var checkBoxes = document.getElementsByTagName("input");
    for (var i = 0; i < checkBoxes.length; i++)
    {
        if (checkBoxes[i].type == "checkbox")
        {
            $addHandler(checkBoxes[i], "click", checkBox_Click);
        }
    }
</script>

 

Although we don't use AJAX here, the code still makes uses of ASP.NET AJAX library because it provide convenient event handling classes and quick shortcuts.

The other way to solve the problem is to use CSS Friendly Control Adapters that contain a TreeView modification that has all the features we need, moreover it generates <ul> and <li> instead of tables that dramatically reduces the size of the HTML code.

The project files are located here.


Posted by Mike Borozdin on Monday, August 11, 2008 4:34 PM GMT
Add to Technorati Favorites  Kick it!  
Permalink | Comments (1) | Post RSSRSS comment feed

Paradox of Open Source Software

Everybody knows the benefits of the open source software. Of course, the main benefit is the availability of the source code and the licence that allows us to perform he modifications and to distribute the derived product. The availability of the source code makes us think that the source code should be perfect. However this is not always true.

Don't get me wrong. I really love some open source projects. In addition to great features, they have neat code that can be used as an excellent learning material. Even Microsoft understands that. CodePlex and MSDN Code Gallery are good examples of that fact.

However there are project, very popular projects, I must admit, that simply badly written. I've been developing with PHP for many years and I ran into really popular, but no so well written applications. I don't imply that it's a fault only by PHP applications, I just had a lot of experience with that.

That may sound really ridiculous, because when the source code is open, many people can read it and make better. However sometimes it doesn't happen, people prefer to concentrate on adding cool features that is right, but on the other hand it makes the code unmaintable and bloated.

That is really a paradox. I think it can be explained by the fact that the open source software is built mostly by the enthusiasts who love to do what they like. I mean that is far more interesting to introduce brand new features rather than to worry about the quality of the source code.

I might be wrong on that though. So, I want to hear your opinion. Have only dealt with well written open source projects? If you have an experience with poor written ones, what do you think is the cause of that?


Posted by Mike Borozdin on Saturday, August 09, 2008 10:51 PM GMT
Add to Technorati Favorites  Kick it!  
Permalink | Comments (4) | Post RSSRSS comment feed

Free Reference Cards on Development Topics or Another Reason to Love DZone

I have already said that I love DZone, but I want to say more - I was really happy to discover another lovely feature of DZone - Refcardz. Refcardz are basically reference cards on development topics available to download for free for DZone members, if you are not a DZone member, then you can register for free.

The reference card are in PDF and ready to be printed. They must be kept near your desk because if you need a quick reference, Refcardz will always help you. I believe the Refcardz on jQuery Selectors and Windows PowerShell will be useful for many people.

The current Refcardz are mostly on Java, RIA and AJAX, as well as on the general programming principles.

General programming principles:

Java:

RIA:

Windows PowerShell:

XML:


They are planning to publish more refcardz, you can subscribe to get notified.


Posted by Mike Borozdin on Thursday, August 07, 2008 12:58 PM GMT
Add to Technorati Favorites  Kick it!  
Permalink | Comments (2) | Post RSSRSS comment feed

Is Microsoft Losing Publicity War?

I guess it's not a secret to anyone that many people complain about Vista, they simply hate it, they post negative comments on the web forums and so on. But are those complaints reasonable? These thing started to happen not after the Vista release, but some time before that! So, when Vista finally came out, it already had a negative image and it still has, no matter if it's a really good operating system. For instance, I know some people who are going to buy a laptop but they are scared to death by Vista, that sounds ridiculous and even stupid, but that's a fact. They don't want to have Windows Vista installed on their laptop instead they are trying to find one with XP installed.

It doesn't have anything to do with Vista qualities, only with its image as a faulty, unstable OS, where many applications don't work and your hardware don't work as well. Of course, it's not true, however that is the image of the OS. Although Microsoft says that Windows Vista sales are pretty ok, that image hurts it.

The same thing applies to Internet Explorer. Although IE8 has successfully passed the Acid Test, it is still considered to be a piece of junk, even though Microsoft deliberately issued a beta version for web developers who can play with it, who can tweak their web sites if they are not properly displayed in IE 8.

So, even though Microsoft release really good products, unfortunately they cannot get over their bad image. However, this applies only to the masses, because the IT professionals are usually better aware of the real quality of the Microsoft products.


Posted by Mike Borozdin on Tuesday, August 05, 2008 11:39 AM GMT
Add to Technorati Favorites  Kick it!  
Permalink | Comments (9) | Post RSSRSS comment feed

Useful Live Writer Plug-Ins for Developers

Although Windows Live Writer is a great tool that simplifies the life of every blogger it doesn't has all the needed features by default. Hopefully there are many plug-ins that can be found in the gallery. If you write about programming that you must be particularly interested in the plug-ins that allows you to paste formatted code snipped, links to MSDN and some other things. I decided to make a categorized list of such plug-ins.

Code:

Console output:

This plug-in allows you to paste a formatted text from the console output, either from Windows PowerShell or from cmd.

Links:

  • MSDN Locator - this plug-in allows you to simply paste a link to a MSDN article by specifying a class or a method name
  • XFN Link Editor - this plug-in allows you specify the XFN attributes of links

There must be some other very useful plug-in, so feel free to share some links :-).


Posted by Mike Borozdin on Monday, August 04, 2008 4:54 PM GMT
Add to Technorati Favorites  Kick it!  
Permalink | Comments (0) | Post RSSRSS comment feed

Adding Client-Side Events To Extender Controls

In the previous articles I wrote about how to use the extender controls available in ASP.NET AJAX Control Toolkit, how to process them on the server, validate the data. It mainly dealt with a server-side part. Today, I'll show you how to add client-side events to the extender controls.

As an example, I'll use Slider again. But unlike the previous article where we processed its value on the server, we'll use its value directly on the page with JavaScript to resize an image, although it won't actually resize the picture, but it will just resize it on the page, i.e., just change the width and height attributes of the <img /> tag.

Let's start, add some image, two sliders for width and height, two text boxes and two labels.

<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
    Width:<br />
    <asp:TextBox ID="txtWidth" runat="server" />
    <asp:Label ID="lblWidth" runat="server" />
    <cc1:SliderExtender ID="sliderWidth" runat="server" TargetControlID="txtWidth"
        BoundControlID="lblWidth" Minimum="100" Maximum="800">
    </cc1:SliderExtender>
    <br />
    
    Height:<br />
    <asp:TextBox ID="txtHeight" runat="server" />
    <asp:Label ID="lblHeight" runat="serBver" />
    <cc1:SliderExtender ID="sliderHeight" runat="server" TargetControlID="txtHeight"
        BoundControlID="lblHeight" Minimum="100" Maximum="532">
    </cc1:SliderExtender>
    <br />
    
    <asp:Image ID="imgPanda" runat="server" ImageUrl="http://upload.wikimedia.org/wikipedia/commons/thumb/3/3c/Giant_Panda_2004-03-2.jpg/800px-Giant_Panda_2004-03-2.jpg" />
</div>
</form>

 

We want to resize the image on moving the slider, since when we move the slider handler, the actual value is being changed in the assigned TextBox, we should add the onChanged even to the TextBox.

 

protected void Page_Load(object sender, EventArgs e)
{
    txtWidth.Attributes.Add("onChange", "ChangeWidth()");
    txtHeight.Attributes.Add("onChange", "ChangeHeight()");
}

And add the JavaScript event handlers.

<script type="text/javascript">
    function ChangeWidth()
    {
        $get("imgPanda").width = $get("txtWidth").value;
    }
    
    function ChangeHeight()
    {
        $get("imgPanda").height = $get("txtHeight").value;
    }
</script>

By the way, please note the we are using the $get() shortcut here that actually invokes document.getElementById()

Let's test it. The image gets really resized but only when you release the button, but not when you just move the slider handle. This can be corrected by setting the RaiseChangeOnlyOnMouseUp to false.

<cc1:SliderExtender ID="sliderWidth" runat="server" TargetControlID="txtWidth"
    BoundControlID="lblWidth" Minimum="100" Maximum="800" RaiseChangeOnlyOnMouseUp="false">
</cc1:SliderExtender>
<%-- some other tags--%>
<cc1:SliderExtender ID="sliderHeight" runat="server" TargetControlID="txtHeight"
    BoundControlID="lblHeight" Minimum="100" Maximum="532" RaiseChangeOnlyOnMouseUp="false">
</cc1:SliderExtender>

Conclusion

In this tutorial we have learnt how to add how add client-side events to the extender controls, how to handle them. We have also learnt about the RaiseChangeOnlyOnMouseUp attribute of the Slider control.

Your feedback is appretiated.


Posted by Mike Borozdin on Sunday, August 03, 2008 5:15 PM GMT
Add to Technorati Favorites  Kick it!  
Permalink | Comments (2) | Post RSSRSS comment feed