Friday, April 30, 2010

Lance Bullit and Windows 3.1

My parents visited recently and brought me a historic gem, a "movie" that I made with some friends 20 years ago. We got our teenage hands on a Hi-8 video camera and the rest is history.

The name of the movie is Lance Bullit, here it is:




Notables:
  • The word processor in the office scene is a predecessor to Word Perfect. It was freeware and I think I was running on a hacked copy of Windows 3.1
  • The sound of the fire in the car explosion scene is actually velcro
  • The bandages in the hospital scene is really TP
  • Dave plays two characters in the movie, and both have masks
  • 2 men jump through the door to assault Lance (that was purposely left in when editing), but Lance only refers to a "thug" *blooper
  • If you listen closely, you can hear Mike counting 3, 2, 1 in the office scene.
Enjoy!

Friday, March 19, 2010

Viewing Powerpoint documents from Silverlight 3.0

I recently had a request to create a link to a User Guide for one of our products. "Great" I said, expecting an HTML page, or some text I could put into a Silverlight page.

What I got was a 10 page Powerpoint presentation with graphics. Silverlight 3 can't natively show a PPT file, so how could I do this?

First, I decided to create a "User Guide" hyperlink that would bring me out of Silverlight, and into an aspx page, here is the click event:
Uri SourceUri = new Uri(HtmlPage.Document.DocumentUri, Application.Current.Host.Source.ToString().Substring(0, Application.Current.Host.Source.ToString().IndexOf("ClientBin") - 1) + "/MSEUserGuide.aspx");
      HtmlPage.Window.Navigate(SourceUri, "_blank"); 
Next, I would use the ASP.net AJAX SlideShow control, Joe Stagner has a nice video tutorial on using the control that I found helpful.

This required a webservice with a list of images, but how to get the images from a PPT file?  Easy.  Open up the PPT file and choose "Save As" with your favourite image type.  I chose .gif and voila - 10 images nicely numbered from 1 to 10.  I then created a webservice to read in the images:
[WebMethod]
    public AjaxControlToolkit.Slide[] GetSlides()
    {
      List slides = new List();

      for (int i = 1; i <= 10; i++)
      {
        string fileName = string.Format("PowerPoint/Slide{0}.GIF", i.ToString());
        slides.Add(new AjaxControlToolkit.Slide(fileName, string.Format("Slide {0}", i.ToString()), string.Format("Slide {0}", i.ToString())));
      }

      return slides.ToArray();
    }
  }
Finally, here is the XAML code from my MSEUserGuide.aspx page (this is the newly created page I navigate to from the click even):
  


That's it! Seems like a complex way to show a simple PPT, but it was pretty quick to create and now you don't have to deal with the document any more which in my opinion is an advantage.

Alternatives to this would be to purchase a 3rd Party product to display the native PPT, or to wait for Silverlight 4 which I believe simplifies this.

Tuesday, February 23, 2010

Meal preparation in the 21st century

Working at Microsoft, I'm seeing an interesting work culture/phenomenon that I've now adopted.

Rather than go out to lunch with folks (getting off campus would involve driving), apart from eating in the MS cafeteria, 80% of the folks here eat at their desk.

Remember the days when you actually prepared a meal from scratch?  Reheating that would be gourmet compared to what some of the folks eat here (myself included).  I actually saw one of my team workers eat 6 slices of white bread for lunch (nothing else - and yes, I counted 6 slices).

I think my favourite lazy observation has got to be the microwave dinners.  They are so easy to prepare, one of the instructions on my dinner said heat on high for 3 minutes, return, stir, then heat for another minute and let sit for one more minute.  Five minutes and you are all set!  Unless you do what a lazy programmer would do and heat on high for 5 minutes straight, burn your mouth, and complain that the prep instructions are too involved.

Welcome to the 21st century...

Friday, December 18, 2009

Interviews - Don'ts and Don'ts

Fresh off the job hunt I can sort of laugh at some of the lessons learned.

I've always thought of myself as a bad phone interviewer and I was wrong.  I'm actually much worst than bad...  I feel much more relaxed when at in-person interviews.  My track record at in person is not too bad, probably 8/10 lifetime record.  My track record for phone interviews? 5 in 100?


How bad are my phone interview skills?  You don't have to be a coder to observe how I can spiral downwards, absolutely freeze and become a complete idiot (more than normal).  Here are some excerpts from last weeks hilarity, none of them were from the company that hired me, rest assured.




Interviewer:  Mark, what prompted you to apply to our company?
Me:  Oh, my friend suggested I apply...

Interviewer:  How can you describe the differences between .Net 1.1, 2.0, and 3.5?
Me:  Ummm.....Ummm......Ummm.....I work with them all the time!....Ummm.....Ummm.....I can't think of any.  Sorry.

Interviewer:  What are the differences between a const and a readonly in .Net?
Me:  A cont variable is a fixed, defined value that cannot be changed by the program, the readonly...?  Hmmm, haven't used one in a few years so not sure how it is different from the const...

My favourite response:

Interviewer:  So how is a protected method different from a private?  (This was basically a question to see if I've ever programmed before)
Me:  Ummm....well, a private method is private to you know, umm, the container object.  The protected method is available to the associated objects.
Interviewer:  Well, who can access the protected method?
Me:  Well, the associated objects, it's public to all associated stuff.

FAIL.

I luckily didn't freeze up on a couple other phone interviews...

Merry Christmas to all!

Monday, November 23, 2009

CDs and DVDs - Why?

I remember when I saw my first CD, it was back in the mid-80s. Revolutionary, you could skip to different song within a second. But that was more than 20 years ago! DVDs delivered more storage, but the same issues as the CD – it easily scratches.

 I remember soon after the CD came out I spent ½ years worth of allowances to purchase my first high storage drive, the Commodore 1581. It could store a whopping 1 Meg of storage (great for my BBS – The Surf Board!), but what I remember distinctly is that it was the first time I used the 3 ½ floppy. Sure you can make fun of the disk now due to it’s low storage, but since the actual magnetic disk was encased in plastic, you could throw it across the room, rub sandpaper across it, and it would still work.

Last week my wife got a DVD from the library for our 3 year old son, Bear and the Big Blue House, and I was frustrated due to the frequent skips. How long does a DVD last with 3 year olds handling it? About 5 minutes I would guess. I feel we’ve advanced so far in all aspects of technology, yet we still seemed plagued with this bad storage medium.

Blue Ray? Slightly better, but still not adopted everywhere. Solid State HDs seem very promising, but I’m not seeing Bear and the Big Blue House on a 2 Gig stick at the library. Or a USB port on my TV that will allow me to play it.

I’m hoping soon CDs and DVDs will be relics on the wall, as for now I’ll continue to Fast Forward and rewind past bad frames…

Thursday, November 12, 2009

Asyncronous file upload in asp.net

I recently had a customer request a feature to upload files to their account.

It's an interesting architectural dilemma, since the file is on the client, the file is to be stored on the Server (in my case, not even the web server), and I definitely wanted to avoid postbacks since it was a rich web app and a postback would look/behave badly.

Some options are AjaxUploader, while it looks solid, I didn't want to pay for the service at the time since paperwork for this type of functionality was more work than coding from scratch.

Another option was the AsyncFileUploader which comes with the latest Microsoft Toolkit, screenshot below. It does an automatic upload on selection, and provides a mind-numbing green background on success, and a red background if it was unsuccessful (which is a nice feature!)


Unfortunately, this great control had errors with IE6. Since a lot of our users are on IE6, this is a show-stopper.

I adopted an idea from a co-worker, kludgy, but effective. Essentially, you put a file upload control in an iFrame (so a postback within the iFrame doesn't postback the entire page), then send a Javascript message from the code behind when the file upload is complete. There were several challenges with this:
  1. asp.net name mangling
  2. Lots of Javascript
  3. Updating the asp.net grid within the UpdatePanel so a full page refresh doesn't happen
Here was the result, works pretty well:

Notice that the filename can be clicked to be viewed, and the delete option, these are all done in the asp.net code behind and done without full postback since the grid is within an UpdatePanel.

So how do you update the grid on file upload?

I added a linkbutton on the grid with associated codebehind (I kept the LinkButton1 name for posterity):
  
protected void LinkButton1_Click(object sender, EventArgs e)
{
   LoadDocs();
}
Now, when the file uploads, simply call the javascript function uploadNotify, via ServerCode:
ClientScript.RegisterStartupScript(this.GetType(), "uploadNotify", script);
Now, the final step? Write the uploadNotify script on the parent page:
function raiseAsyncPostback() {
   __doPostBack("<%= this.LinkButton1.UniqueID %>", "");
}
The UniqueId is resolved to the mangled name (this nuisance now resolved in .net 4.0 - yay!)

That's what it takes! Kludgy, but effective, and gives you highly customizable options. Personally, I'd wait for the Toolkit version to be spiffed up, looks really good.

Thursday, November 5, 2009

Silverlight Autocompletebox with custom dropdown

I needed to create an Autocompletebox for selecting staff. I wanted a robust select so you can type in the first name of the employee, last name, staff id, or even the office the staff member resided in, and the list would be filtered and selectable in the dropdown.

Once selected, the box could fire an event that would load additional info about the employee. Here is what it looks like, this is before I put in pretty formating, keep in mind I'm a coder, not an artist. :)

I decided to get the staff member via a WCF call, here is the GetStaffList() call I defined and am returning a custom class so I can specify the exact search criteria.

[OperationContract]
public List GetStaffList()
{
   Csla.ApplicationContext.ClientContext["HostName"] = // I used CSLA, put address here;

   List staffList = new List();
   StaffViewListClass staffListClass = StaffViewListClass.GetStaff();

   foreach (StaffViewClass staff in staffListClass)
   {
      staffList.Add(new StaffSearchClass(staff.FullName, staff.FirstName,
                  staff.OfficeName, staff.StaffId));
   }
   return staffList;
}

And here is the custom class definition:

[DataContract]
    public class StaffSearchClass
    {
        [DataMember]
        public string FullName { get; set; }
        [DataMember]
        public string StaffId { get; set; }
        [DataMember]
        public string FirstName { get; set; }
        [DataMember]
        public string OfficeName { get; set; }
        [DataMember]
        public string DisplayValue { get; set; }

        public StaffSearchClass(string fullName, string firstName, string officeName, string staffId)
        {
            FullName = fullName;
            FirstName = firstName;
            OfficeName = officeName;
            StaffId = staffId;
            DisplayValue = StaffId + " " + FullName;
        }
    }

Note the use of [DataContract] and [DataMember] attributes. These are important so the ServiceReference knows about them.

The next phase was to create a custom searchable Autocomplete box. Jeff Wilcox Microsoft MVP has a great "missing guide"

Step 1: In your Silverlight project, add a Service Reference to your WCF Service.

Step 2: Get the Staff Data Asyncronously. Here is my MainPage() method:
public MainPage()
        {
            InitializeComponent();

            SilverlightAuto.StaffService.StaffServiceClient client = new SilverlightAuto.StaffService.StaffServiceClient();

            client.GetStaffListCompleted += new EventHandler(client_GetStaffListCompleted);

            client.GetStaffListAsync();

        }

        void client_GetStaffListCompleted(object sender, SilverlightAuto.StaffService.GetStaffListCompletedEventArgs e)
        {
            List list = e.Result.ToList();
            uxAuto.ItemsSource = e.Result.ToList();

            uxAuto.ItemFilter += SearchStaff;

        }

Important to note: In my ServiceReference completed event, I've added an ItemFilter to my Autocompletebox control (uxAuto). This is necessary to custom bind my search criteria (remember that I wanted to search on First name, last name, etc). Autocompletebox can't assume what you want to search on, but makes it pretty easy to customize.

Here is the SeachStaff method, you can put whatever search criteria you want, but be aware of performance if you are parsing a lot of data.

bool SearchStaff(string search, object value)
        {
            search = search.ToLower();
            SilverlightAuto.StaffService.StaffSearchClass staff = value as SilverlightAuto.StaffService.StaffSearchClass;

            if (staff != null)
            {
                if (staff.StaffId.StartsWith(search))
                    return true;
                else if (staff.FullName.ToLower().StartsWith(search))
                    return true;
                else if (staff.FirstName.ToLower().StartsWith(search))
                    return true;
                else if (staff.OfficeName.ToLower().StartsWith(search))
                    return true;
            }

            return false;
        }

As a reference, here is the Xaml for the autocomplete box. Note you need to add the System.Windows.Controls.Input declarative.

  
        
            
                
                    
                        
                        
                    
                
            
        

So remember the requirement that I needed to populate some other stuff once the staff member has been selected? That was tricky, there is no obvious event to hook into when the user has been selected, but if you look, I have an event on DropDownClosed. Seems like an odd event to tie into, but works exactly like I wanted it to since when a staff member is selected the box closes!

Overall I am really impressed with this control. I used to have to do a lot of custom coding to re-create this behaviour in web forms, and it's really kludgy to do in AJAX, if you are lucky enough to get something close to this functionality.