Yanesh Tyagi on ASP.Net

Technical blog of Yanesh Tyagi

  • Implementing Sorting in Generic List (List<T>)

    How to sort a generic list? Well, generic list provides a sort method itself in the form List<T>.Sort(). But wait a sec. This method requires you to implement sorting mechanism in your type. This is because this method uses default sorting mechanism. This is really simple, but what if you don't have sorting mechanism in your type? In that case this method throws InvalidOperationExpression.

    List<T>.Sort() method uses the default comparer Comparer(T).Default for type T to determine the order of list elements. The Comparer(T).Default property checks whether type T implements the IComparable(T) generic interface and uses that implementation, if available. If not, Comparer(T).Default checks whether type T implements the IComparable interface. If type T does not implement either interface, Comparer(T).Default throws an InvalidOperationException.

    If you use system types like String, default comparer works fine. This is because String class implements IComparable interface. If you see the definition of String class, it looks like (you can see this by pressing F12 keeping the cursor on the word 'String' in the code editor of visual studio):

    public sealed class String : IComparable, ICloneable, IConvertible, 
                                 IComparable<string>, IEnumerable<char>, 
                                 IEnumerable, IEquatable<string> 
     
    
    

    But for types that does not implement Icomparable, default sort does not work. However there is one work around. This trick uses delegates.

    To illustrate this example, I created a simple class Post. The code of this class is as below. This class does not implement IComparable interface. So default sort will not work for this.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace Tyagi.Utility
    {
        public class Post : IComparable<Post>
        {
            public String Title { get; set; }
            public String Source { get; set; }
        }
    }
    

    Create another class that will consume this class.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace Tyagi.Utility
    {
        public class PostsList
        {
            List<Post> posts = new List<Post>();
    
            public List<Post> GelPosts()
            {
                posts.Add(new Post { Title = "MSN Space", Source = "Blog" });
                posts.Add(new Post { Title = "CNBC TV 18", Source = "News" });
                posts.Add(new Post { Title = "Independence Day", Source = "Movie" });
    
                posts.Sort(delegate(Post P1, Post P2)
                {
                    return P1.Title.CompareTo(P2.Title);
                });
    
                return posts;
            }
            
            
        }
    }

    The trick is in the use of a delegate in the call to Sort method of the posts object.

    posts.Sort(delegate(Post P1, Post P2)
    {
        return P1.Title.CompareTo(P2.Title);
    });

    The delegate accepts two parameter, both of the same class Post. It the uses the CompareTo method. This method is defined in the type of property. In this example, Title property of Post class is of type string. So the CompareTo method of string class will be called in this case. CompareTo method returns int. Sort method of List<T> uses this integer to compare two objects.

    The above code returns list in the ascending order of title. To reverse the order, simply reverse the code as be below:

    posts.Sort(delegate(Post P1, Post P2)
    {
        return P2.Title.CompareTo(P1.Title);
    });
    

     

    This is one way. You can implement the sorting functionality in your class as well. I will discuss this in the next post.

    kick it on DotNetKicks.com

  • Implementing Delete Confirmation Dialog in ListView Control (ASP.Net)

    Listview control is one of my favorite controls added in asp.net version 3.5. It provides easy way to implement view (list), update, insert and delete functionality. Using SQL Data Source or LINQ Data Source control, you can create a page that will display data from database in your desired format. It will also allow you to edit, insert or delete a record from the listview itself. And the good part is that you don't need to write any code. This may be disappointing to a hard core programmer like me. But again this saves lot of development time.

    But one of the lacking feature in the listview control is delete confirmation. If somebody clicks on the delete button by mistake, there is no way to cancel the delete action. To solve this issue, I used client side JavaScript and confirm function.

    JavaScript's confirm function display an modal alert popup with the user specified confirmation message. It also have two buttons - OK and Cancel. Pressing OK or Cancel return boolean true or false. When confirm function is used with form submission, it cancels the form submission if Cancel button is pressed by the user. If user presses OK button, form submits as usual.

    I used confirm function in the OnClientClick event of the ListView's delete button.The code to use this is given below. Please note that in the code I used LinkButton instead of auto generated Button. This is for usability purpose and the code works well with the Button also.

    <asp:LinkButton ID="DeleteButton" runat="server" CommandName="Delete" ForeColor="Red" Text="Delete"
    OnClientClick="return confirm('Are you certain you want to delete?');" />

    And the dialog box shown by this code is :

    image

    kick it on DotNetKicks.com

  • Converting Text into Image On-The-Fly

    Sometimes we need to convert text into the images on the fly. This code converts the text into image and displays it onto the web page without saving it into a file on the disk. It also takes care of text wrapping.

     

    TextToImageConvertor can either be used in a web page or in a module. I have used this code in a web page. To use TextToImageConvertor in a module, you will need to make some changes in the step 8.

    The code for TextToImageConvertor is self explanatory. However, I am going to describe this step-by-step.

    Step 0 - Include Namespaces

    using System.Drawing;
    using System.Drawing.Imaging;

    Step 1 - Declare Properties

    Declare some variables that will control the behavior and color of the image.

    string Text = Request.QueryString["Text"];
    Color FontColor = Color.Blue;
    Color BackColor = Color.White;
    String FontName = "Times New Roman";
    int FontSize = 10;
    int Height = 150;
    int Width = 150;

    Step 2 - Create a Bitmap Object to Hold The Image

    Bitmap bitmap = new Bitmap(Width, Height);

    Step 3 - Create a Graphics object using this Bitmap object

    Graphics graphics = Graphics.FromImage(bitmap);

    Step 4 - Create Color, Font, and  PointF objects.

    Color color = Color.Gray; ;
    Font font = new Font(FontName, FontSize);
    //define where the text will be displayed in the specified area of the image
    PointF point = new PointF(5.0F, 5.0F);

    Step 5 - Create Brushes and Pen

    SolidBrush BrushForeColor = new SolidBrush(FontColor);
    SolidBrush BrushBackColor = new SolidBrush(BackColor);
    Pen BorderPen = new Pen(color);

    Step 6 - Draw Rectangle using Graphics object

    Rectangle displayRectangle = new Rectangle(new Point(0, 0), new Size(Width - 1, Height - 1));
    graphics.FillRectangle(BrushBackColor, displayRectangle);
    graphics.DrawRectangle(BorderPen, displayRectangle);
    Step 7 - Draw Text string on the specified rectangle using Graphics object
    //Define string format 
    StringFormat format1 = new StringFormat(StringFormatFlags.NoClip);
    StringFormat format2 = new StringFormat(format1);
    //Draw text string using the text format
    graphics.DrawString(Text, font, Brushes.Red, (RectangleF)displayRectangle, format2);
    Step 8 - Send the bitmap to page output stream in JPEG format
    Response.ContentType = "image/jpeg";
    bitmap.Save(Response.OutputStream, ImageFormat.Jpeg);

     

    Using TextToImageConvertor

    TextToImageConvertor is developed as a web page which can be accessed directly by passing the text in he query string.

    To demonstrate the use of this tool, create a webpage with a textbox, a button and an image control. On the click event of the button, set the image URL to the convertor page and pass the text of text box into the query string. In the example code below, I have named my image control as img1 and text box as txtNote.

    img1.ImageUrl = "default2.aspx?Text=" + txtNote.Text;

    Technorati Tags: ,
     
    kick it on DotNetKicks.com

  • Ajax Control Toolkit - Controls Disabled in Tool Box

    Having my PC broken, I had to work on another machine. I downloaded Visual Web Express and Ajax Control Toolkit. I installed the toolkit as described by Nannette. But nothing appeared on my toolbox. Thinking that I might have missed something, I tried to repeat the process. When I was giving the name during the tab creation step, VWD responded by saying that

    Tab name 'Ajax Control Toolkit' already exists.

    I was surprised to know that the tab has been successfully created but it was not dislayed. Playing around with different options, I clicked 'Show All' option. This option comes when you right click on the empty area of general tab. Checking this option showed me a number of tabs which I haven't seen earlier.

    This also showed me my 'Ajax Control Toolkit' tab. But all the options (controls) in this tab disabled (grayed out). I had code view of a aspx page opened on the screen. Thinking that these might get active on the design view, I switched to it. But this did not worked.

    Then I restart VWD and opened the website again. But still these are grayed out. Finally I shut down the PC calling it a day. Next day, when I opened the project again, all ajax tab were there and all controls were enabled.

    So, if you are also facing the same error, do the following.

    1. Restart Visual Web Express. If it does not work,
    2. Restart the Pc.

    I also found one more solution somewhere on the net later on. This is described below:

    1. Close VWb and any other express product installed running such as Visual C# EE.
    2. Open windows explorer and navigate to the
      'C:\Documents and Settings\<your user name>\Application Data\Microsoft\VWDExpress\9.0'
      folder. You might have to enable 'Show Hidden Files' under the folder options' View tab.
    3. Delete any .pdb file, you found in this folder.
    4. Start VWD and reinstall the ACT as described here.

    By the way, In one of the comments on nannette blog, skain said,

    "Am I the only one who thinks it is utterly ridiculous that we're supposed to use a dll from the WebSite project as the main reference for the toolkit?  Why isn't this in a separate class library project?"

    skain, I also agree with you. I think that there should be some installer package that will do all this on a single click.