Blogs

Paul Kimmel's Blog

April 2009 - Posts

  • Lansing GiveCamp Redux

         

    The Lansing GiveCamp is a great way to help charities in need and beef up or learn some new skills for the volunteers. The basic idea is charities submit proposals and developers with various skills volunteer. The volunteers are matched up with the charities for three solid days of development on the charity’s behalf. In essence many of the more committed volunteers basically live at the venue and some work around the clock. As a result it is helpful if the various sponsors help provide a venue, food, beverage and snacks. Developer Express was just one such sponsor. Developer Express provided door prizes and one of the several meals for all attendees. Developer Express also graciously permitted developers and the charities to use Developer Express tools and components free of charge.

    I volunteered and passed out swag, including hats, and t-shirts. Our group was best served by a web portal, so it made sense given the time allowed to use DotNetNuke. The downside is our team didn’t get to use a lot of the cool Developer Express technology that was available. I did demonstrate CodeRush and Refactor for a couple of team members, and as always I am surprised when I meet people that haven’t used these tools before. (Of course, one guy was a state employee and sometimes “budget” is used as a reason for not leveraging tools. Makes me think of Ben Franklin’s “penny wise-pound foolish” sentiment.)

    For more about Lansing GiveCamp check out the lansinggivecamp.org web site.

  • Lansing GiveCamp

         

    Tomorrow, April 24th at 4 PM the 2009 Lansing Give Camp at the Impression 5 Science Center in Lansing, Michigan opens its doors. (The event continues until Sunday April 26th.) I will be there pitching, giving away some fun Developer Express swag, and more importantly helping to build Web sites for registered charities like the Ronald McDonald House of Mid-Michigan, Boys & Girls Club of Lansing, and the Community Meals Program, Inc to name a few.

    To quote the web site (http://lansinggivecamp.org/Home.aspx), a GiveCamp is a weekend-long event where software developers, designers, and database administrators donate their time to create custom software for non-profit organizations.

    More details are available at http://lansinggivecamp.org/Home.aspx. Its not too late if you want to sign up. If you are a brand new aspiring programmer or a hotshot GiveCamp has some work for you to do, and you might get some cool Developer Express swag and a free lunch on us.

  • Keeping Your iTunes on an External Drive

         

    I purchased a new computer last week. I have a couple of servers, a half dozen PCs, and several laptops in my home. I work from a home office so this makes sense. I used to replenish these computers annually but it gets to be too time consuming and too expensive, but I do eventually replace them. The challenge with replacing development workstations is that a lot of software and patches have to be installed and this takes time. Consequently I have no patience for software that doesn’t make it easy for me to swap out hardware.

    An example of a challenge I experienced is swapping CPUs but maintaining existing burned Cd's on iTunes. Currently I have about 3500 songs on an external  My Book USB hard drive. No sane person wants to burn CDs over--or re-import libraries--we just want to point the software at the folder containing the data and go. This is true for any application. There are a lot of blogs, articles, and posts out there about how to “use an external hard drive with iTunes” because your hard drive fills up or to make your library more portable or whatever. Unfortunately each post seems to fall just a bit short of an accurate solution. So one of the things I do is when I have a computer problem I write down the solution and post it on the Web so if I ever need it again I can find it. (Documenting tricks, tips, and techniques is part of my day job at Developer Express too.) To that end I have documented the steps that work well for me when using existing burned songs for a new PC.

    If you want to move iTunes music files to a location other than the default location—for example, because your hard drive fills up or you are upgrading hardware—then try these steps (for Windows):

    1. Open iTunes
    2. Select Edit|Preferences and change to the Advanced tab
    3. Next to the iTunes Music folder location click the Change button; navigate to the new desired location and change the path
    4. Close the iTunes preferences dialog by clicking OK. This steps modifies a file named “iTunes Music Library.xml”, modifying the path information for elements in your iTunes library
    5. Close iTunes
    6. Using Windows Explorer copy just the files in the “iTunes Music” folder to the location you specified in step 3—the new location. (iTunes Music is usually accessible in user:Music:iTunes)
    7. Delete the files in the “iTunes Music” folder once they have been copied to the new location
    8. Return to the user:Music:iTunes folder and locate “iTunes Library.itl” and “iTunes Music Library.xml” and make a copy of them. (The “iTunes Library.itl” is a binary version of the “iTunes Music Library.xml” file.) iTunes reads iTunes Library.itl not the .xml file; unfortunately it appears that Edit|Preferences updates the .xml file leaving the file-move somewhat wanting
    9. Next, open the .itl file in Notepad. (If its a big file Notepad might get sluggish.)
    10. Select all of the contents of the .itl file (Ctrl+A) and delete them
    11. Select File|Save As and save the filename as iTunes Library.itl, the file type as All files (*.*), and the encoding as Unicode.

    The last step is the one that many of the blog posts have left off, but seems to be the critical step. When you are finished with the steps above re-open iTunes and you should be off to the races.

    Why did I write about this subject? Besides having told you the World Wide Web is part of an extension of my memory, and besides the fact that iTunes can be challenging in the aforementioned regard and should be made easier, I wanted to illustrate a point. The point is that as conscientious as we at Developer Express try to be sometimes we don’t know some thing is wrong until we have to share your pain or you tell us. We are working diligently to make more great products and make the ones we have better, but sometimes you experience pain in a way that we haven’t. I encourage you to share your thoughts—share your pain—and we’ll try to make it go away.

  • Central Ohio Day of .NET

         

    I am at the Central Ohio Day of .NET in Wilmington. There is a good turnout. I am surprised by the mixed bag of Developer Express users, but equally surprised by the number of people that don’t use our controls or tools. I am of the school that a “craftsman is known by his tools”. I’d go nuts without tools: CodeRush, Refactor, Fiddler, Reflector, SnagIT (and Camtasia, both made in my town of Okemos, Michigan), SQL Refactor, Windows Live Writer, and our (Developer Express) controls.

    A few of the folks said they use what the customer is using and some say they have no budget for extra-party tools. These arguments are specious. If a tool or component saves my more than the expenditure of time otherwise then its money well spent.

    Hint: A reasonably good strategy is that if you are on a budget then attend your local user group, free Day of .NET events, or Givecamps and sometimes you can pick up freebies that include some of these tools. At least pick up your free 60 controls from Developer Express; that’s a price everyone can afford.

  • Tweaking Images Displayed from a Database

         

    The folks at Developer Express exchange ideas and information just like a lot of you probably do with your co-workers. One of my go to guys is Mehul Harry. I probably drive him a little nuts with questions about code samples and videos, but Mehul generally comes through for me and has a good disposition when imposed upon. Many of you have probably seen some of his videos like the “How to Display Images Direct(ly) From the Database” at http://tv.devexpress.com/ASPxBinaryImageIntro.movie. (They discourage me from doing videos because someone posted on on YouTube and mothers of little children complained.)

    In Mehul’s video he demonstrated how to show display an image directly from a database old school by using an <img> tag with the src attribute referring to an .aspx page. You can swap out the .aspx page with an IHttpHandler (an .ashx page) too if you want to. And then Mehul sagely demonstrates how much easier it is just to use an ASPxGridView and an ASPxBinaryImage which will manage all of the plumbing for rendering the image for you. This blog entry expands on Mehul’s video. In the example I will show you how to tweak the video by using GDI+ to add content to the database image before showing it. (The example also uses the Northwind Employees table which has OLE headers stuffed in the Photo column, making it a little harder to show these pictures directly without tweaking.)

    To prepare the example create a Web Site project and add an ASPxGridView to the Web page. Use the Chose Data Source option from the grid’s Smart tags menu and add a SqlDataSource that refers to the Employees table. Add whatever columns you’d like, include the FirstName, LastName, and Photo columns at a minimum because they are used in the sample. One minor nuisance is that the Photo column will be returned but a column won’t be added to the grid. The Photo column can be added from the Smart tags menu’s Columns item. Just add a Column and set the FieldName property to Photo. The next step is to select Edit Templates from the ASPxGridView’s Smart tags menu and pick the DataItemTemplate from the Photo column. In the DataItemTemplate drag and drop an ASPxBinaryImage into the template (look at Figure 1).

    image 
    Figure 1: Drag and drop an ASPxBinaryImage to the DataItemTemplate and bind the Photo column to the ASPxBinaryImage’s Value attribute for basic image display.

    Now, if the image weren’t whacked out then binding the ASPxBinaryImage’s Value attribute to the Photo column would be the final step in displaying the image from the database (see Listing 1). The Northwind images have OLE headers in them and it helps to strip these off. Plus, I want to show you how to add content to the image with GDI+.

    Listing 1: The ASP.NET shows how to bind an image column to an ASPxBinaryImage control (shown in bold).

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>

    <%@ Register assembly="DevExpress.Web.ASPxGridView.v9.1, Version=9.1.2.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" namespace="DevExpress.Web.ASPxGridView" tagprefix="dxwgv" %>
    <%@ Register assembly="DevExpress.Web.ASPxEditors.v9.1, Version=9.1.2.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" namespace="DevExpress.Web.ASPxEditors" tagprefix="dxe" %>

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

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
          <dxwgv:ASPxGridView ID="ASPxGridView1" runat="server"
            AutoGenerateColumns="False" DataSourceID="SqlDataSource1"
            KeyFieldName="EmployeeID">
            <Columns>
              <dxwgv:GridViewDataTextColumn FieldName="EmployeeID" ReadOnly="True"
                VisibleIndex="0">
                <EditFormSettings Visible="False" />
              </dxwgv:GridViewDataTextColumn>
              <dxwgv:GridViewDataTextColumn FieldName="LastName" VisibleIndex="1">
              </dxwgv:GridViewDataTextColumn>
              <dxwgv:GridViewDataTextColumn FieldName="FirstName" VisibleIndex="2">
              </dxwgv:GridViewDataTextColumn>
              <dxwgv:GridViewDataTextColumn FieldName="Photo" VisibleIndex="3">
                <DataItemTemplate>
                  <dxe:ASPxBinaryImage ID="ASPxBinaryImage2" runat="server" Value='<%# Eval("Photo") %>' >
                  </dxe:ASPxBinaryImage>
                </DataItemTemplate>
              </dxwgv:GridViewDataTextColumn>
            </Columns>
          </dxwgv:ASPxGridView>
          <asp:SqlDataSource ID="SqlDataSource1" runat="server"
            ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
            SelectCommand="SELECT [EmployeeID], [LastName], [FirstName], [Photo] FROM [Employees]">
          </asp:SqlDataSource>
        </div>
        </form>
    </body>
    </html>

    Now, if you want to tweak the image—let’s say draw the employee’s name on top of the graphic—then replace the simple script block that binds Photo to Value with a function call, and you can pass column values into the function. Here is a replacement tag for the ASPxBinaryImage that will call a method called GetPhoto, passing in the Photo, FirstName, and LastName.

    <dxe:ASPxBinaryImage ID="ASPxBinaryImage1" runat="server" Value='<%# GetImage( Eval("Photo"), Eval("FirstName"), Eval("LastName")) %>' >
    </dxe:ASPxBinaryImage>

    To support the script block statement add a protected method named GetImage that returns a byte[] and accept three arguments: Photo, FirstName, and LastName. Images with OLE headers need the first 78 bytes stripped—according to dozens of other blogs and articles—but most images won’t need this extra bit of effort. Listing 2 contains the implementation of the GetImage method.

    Listing 2: The implementation of the code-behind showing the GetImage method.
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Drawing;
    using System.IO;
    using System.Drawing.Imaging;

    public partial class Default2 : System.Web.UI.Page
    {
      private Font font = new Font("Courier New", 10, FontStyle.Bold);
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected byte[] GetImage(object photo, object FirstName, object LastName)
        {
          if (photo == null) return null;

          byte[] data = (byte[])Convert.ChangeType(photo, typeof(byte[]));

          MemoryStream stream = new MemoryStream(data, 78, data.Length - 78);
          System.Drawing.Image image = System.Drawing.Image.FromStream(stream);

          Bitmap bitmap = new Bitmap(image.Width, image.Height);
          Graphics graphics = Graphics.FromImage(bitmap);
          graphics.DrawImage(image, 0, 0);
          graphics.FillRectangle(Brushes.Black, 0, image.Height - 22, image.Width, 22);
          graphics.DrawString(string.Format("{0} {1}", FirstName.ToString(), LastName.ToString()),
            font, Brushes.White, 2, image.Height - 20);

          stream.SetLength(0);
          bitmap.Save(stream, ImageFormat.Jpeg);
          return stream.ToArray();
        }
    }

    In a nutshell GetImage converts the byte array to an image, a Bitmap is used as the canvas to create the GDI+ object, and support the custom drawing. The Employee name is drawn in a black box on the image and it is re-converted to a byte[] which is what the ASPxBinaryImage expects.  If you are using Northwind images with an OLE header then strip the first 78 bytes out of the array; this step is shown in the creation of the MemoryStream. If the image displays fine all by itself then modify the MemoryStream constructor as follows: MemoryStream stream = new MemoryStream(data).

     

    You can use this technique to create completely custom graphics and drawings too. Simply create a bitmap, create a Graphics object from the Bitmap and draw away. When you are finished stuff the output in the HttpResponse stream or return (as demonstrated above) as part of a binding statement for an ASPxBinaryImage.

  • Defining Custom Script Properties

         

    With the introduction and wide acceptance of asynchronous callbacks (generally referred to as Ajax now) I find myself writing a lot less JavaScript. The whole point of JavaScript was to make the Web experience rich like Windows chunk clients usually are. However, with Ajax (and Developer Express controls) it is now pretty easy to create a rich client experience without the apparent re-paint and roundtrip that the user experienced prior to Ajax. I still write JavaScript though because sometimes there is nothing quite like code on the client. And, sometimes when you need JavaScript you also need server values to be accessible on the client. This is where our CustomJSProperties event comes into play.

    CustomJSProperties is an event that is called on every postback and callback. The CustomJSProperties event has a ASPxGridViewClientJSPropertiesEventArgs argument. This argument has a Properties property that is a Dictionary<string, object>. The string template parameter is the key and the object parameter is the value. Put any value in the Properties dictionary element and that item becomes a first class property as far as the owning object is concerned on the client. In the following example an ASPxGridView was added to a page. A SqlDataSource is connected to the Northwind Employees table. The ASPxGridView's ClientInstanceName is set to 'grid'. The ClientInstanceName provides you with any easy way to refer to Developer Express controls in script. Next, I add a CustomJSProperteis event for the grid and stored the grid's PageIndex in the property (see Listing 1). From ASP.NET and JavaScript's perspective cpCurrentPage can be accessed as grid.cpCurrentPage.

    Listing 1: A demonstration of the CustomJSProperties event. 

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;

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

        }
        protected void ASPxGridView1_CustomJSProperties(
          object sender,
          DevExpress.Web.ASPxGridView.ASPxGridViewClientJSPropertiesEventArgs e)
        {
          e.Properties["cpCurrentPage"] = ASPxGridView1.PageIndex;
        }
    }

    Tip: Use a lowercase cp prefix for ASPxGridView custom properties so as to avoid overwriting pre-existing properties. This is just a requirement added by us to prevent property collisions.

    To use the value add a button that invokes a JavaScript function that uses the client name 'grid' and calls accesses the dynamic property. Here is an HTML tag that defines a button and the <script> block. The debugger statement breaks the code at that point and Figure 1 shows the dynamic cpCurrentPage property in the Quick Watch window.

    Listing 2: A <Script> block and an <input> tag added to the ASP.NET to make use of the dynamically added  (through the server side CustomJSProperties event) cpCurrentPage property.

    ...
    <script type="text/javascript" language="javascript">
      function DisplayCurrentPageIndex() {
        debugger;
        alert("Current page: " + grid.cpCurrentPage);  }
    </script>
    </body>

    ...
          <input type="button" value="Current Page Index" onclick="DisplayCurrentPageIndex()" />
        </div>
        </form>
    </body>
    </html>

    image
    Figure 1: The cpCurrentPage property added in the CustomJSProperties event looks like a first class property to the debugger and JavaScript.

  • For Fun and Profit (Well, Profit Maybe Not So Much)

         

    I suspect that out there in Internet-land I have many as yet unmet kindred spirits. By this I mean programmers that I haven't met that bend and twist what a language can do just for fun. (You know the kind of activity that might cause a normal person to tell you to get a life.) Some people drink wine, some watch Adam Lambert on American Idol (hey his spin on Dilana Smith's spin on Johnny Cash's Ring of Fire is awesome if you like Nine Inch Nails), some fly planes, write poetry, cook, play instruments, take TaeKwonDo lessons with Master Shinn, and some, like me, like to take the language out for a spin and see what she'll do. So, if you are really serious--of the "programming is about solving problems" set or you have lost your inner child on the path of life--then you can skip this blog entry because it suffers from an excess of frivolity.

    A month ago a reader responded to an article I wrote on calculating prime numbers--http://www.codeguru.com/columns/vb/article.php/c6575. In essence his first missive can be Cliff-noted as you are an idiot and your algorithm sucks! Of course, if I had wanted to start a digital bar fight, I could have called him a Nazi. Since I am only an Internet white belt I sent back a pleasant:  thank you for your feedback and thank you for taking your valuable time to improve on my grossly inferior article. Diffused he wrote back and apologized. The reader indicated that he had been refining the Sieve of Eratosthenes for 40 years--that's 4-0 years--and felt partial to it. (What I wanted to write back is if you can't do a better job than me after 40 years of effort then you are complete idiot as well as a jerk. I didn't. I didn't because I obsess about algorithms in the same way. I work and re-work algorithms dozens, if not hundreds of times. I like doing it. My girlfriend has a name for it that sounds like "asp" and "burger" . My girlfriend means "obsessing", and when I do it take it as intense interest.

    One such obsessive algorithm for me is an object state dumper. I write so much code and so many tests that it is intrinsically useful to me to know what state my objects are in. (Hey, I got the idea from Dave Thielen's No Bugs!: Delivering Error-Free Code in C and C++and so did everyone else after Dave.) Consequently I have written (and published) dozens of things on an object's state dumper. (Of course, Microsoft came out with the ObjectDumper and killed my claim to fame.) And, I have re-written the state dumper several times. In this blog I thought I'd try writing a state dumper with LINQ. (I know it took forever to get to the point but writing and coding all day sometimes causes meanderitis.) Listing 1 contains an object state dumper written in LINQ. I hope you have fun with it.

    Listing 1: An object state dumper courtesy the lone way around of Dave Thielen and Jeffrey Kenton.

    public static void LinqDump<T>(IEnumerable<T> list, TextWriter writer)
    {
      string mask = "{0} : {1}";

      var results = from obj in list
                         let properties = typeof(T).GetProperties()
                           from prop in properties
                           select
                             prop.GetValue(obj, null) != null ?
                               string.Format(mask, prop.Name, prop.GetValue(obj, null)) :
                               string.Format(mask, prop.Name, "unk.");

      Array.ForEach(results.ToArray(), s => writer.WriteLine(s));
    }

    The code essentially uses a nested from to iterate the list of incoming objects and then the properties to return an enumerable collection of strings stating the property name and value. The Array.ForEach sends the results out to whatever TextWriter happens to be (like Console.Out). The first drawback--among several, including esoterrorism--is that the function uses a second pass to send the results to the TextWriter. Listing 2 contains a side-effects version that uses a generic function type to display the results while iterating.

    Listing 2: Using side-effects to send the value to the stream while iterating.

    public static void LinqDump<T>(IEnumerable<T> list, TextWriter writer)
    {
      string mask = "{0} : {1}";

        Func<string, string> sideEffects = obj =>
        {
          writer.WriteLine(obj);
          return obj;
        };

        var results = from obj in list
                           let properties = typeof(T).GetProperties()
                             from prop in properties
                             select
                               prop.GetValue(obj, null) != null ?
                               sideEffects(string.Format(mask, prop.Name, prop.GetValue(obj, null))) :
                               sideEffects(string.Format(mask, prop.Name, "unk."));

    }

    In Listing 2 results is wasted, but you avoid iterating over the data a second time.

    OK. Time to fess up. What has any of this to do with Developer Express's controls? Nothing directly. My boss Ray said blog about LINQ because you wrote a book--LINQ Unleashed for C#--and it should be easy for you to whip out some blogs on LINQ, so I wrote about LINQ stuff. It is also worth noting that Developer Express is a great place to work, the people are smart--like Oliver Sturm, Mehul Harry, Mark Miller and others--and I have witnessed first hand how they expend a lot of energy figuring out what would make you guys more productive, do a better job, and have more fun. Since, its after 6PM I thought I would pitch in on the fun factor bit.

    If you can improve on the code above--make it smaller, faster, or cooler then respond to the blog. If you are going to the Central Ohio Day of .NET in Columbus on April 18th or TechEd in LA in May then stop by the Developer Express booth and say hello.

More from DevExpress
Live Chat
Have a pre-sales question?
Need assistance with your evaluation?
We are here to help.
Chat is one of the many ways you can contact members of the DevExpress Team. We are available Monday-Friday between 8:30am and 5:00pm Pacific Time.
If you need additional product information, require pre-sales assistance, or want help with your order, write to us at info@devexpress.com or call us at
+1 (818) 844-3383.