Saturday, March 29, 2008

AjaxControlToolkit - Using the ReorderList with simple collections

Download Sample Project

Recently I've been working with the AjaxControlToolkit and Microsoft's Ajax technologies in .net 3.5. While I love the AjaxToolkit, I find the documentation and code-sample is somewhat lacking.

The ReorderList is also one of the lest intuitive controls in the Toolkit.

There are several other samples around the net, but all the ones I found assumed your were binding to a DataSource control of some sort, and most didn't demonstrate persisting changes to an underlying data store.

The few that showed persistence assumed a SqlDataSoruce control that would automate persistence with two-way binding (outside of demo-land, this is a a rare case  in my experience).

So when I first tried out this control, I was surprised at how difficult it was to use it with a simple collection such as an array, or a generic list.

Here is the basic markup you need in your page:

<ajaxToolkit:ReorderList ID="OrderList" runat="server" AllowReorder="true"
            LayoutType="Table" OnItemReorder="OrderList_ItemReorder" 
            PostBackOnReorder="true">
            <ItemTemplate>
                <span style="cursor: pointer;">
                    <asp:Label ID="ItemName" runat="server" 
                               Text='<%# Container.DataItem %>' />
                </span>
    </ItemTemplate>
</ajaxToolkit:ReorderList>

We're setting the text of the label control to the Container.DataItem directly rather than using an Eval or Bind method. That's because simple collections don't have properties that Eval and Bind can use, so you put the content of the data item directly in your output. This is the same with almost all bindable controls with simple collections, but is also one of those things the documentation just sort of "assumes" you already know... which is probably why I coded asp.net for about 4 years before I discovered this little trick.

On a postback or callback, there is no reliable way to get at the data items in their re-arranged state. If you put a button on the page to postback to the server and try to look at the items in the control, you will only be able to see them in the order they had been in when the control was first bound to the collection.

This means you can't just let the user make changes on the client and just submit the page back when they are done. The only reliable way to keep up with the user made reordering is to let the control postback each time the user makes a change, then manually keep track of the changes yourself.

Annoyingly, if you let the control post back to the server as the users makes their changes, the control will re-render itself with the original items in their original order. This will cause the list to reset after each postback effectively undoing the user's changes.

The only way around that seems to be to manually rebind the control yourself on each postback after you've updated the collection that you are using to manually track the changes.

To get all this to work together, the trick is to cache a copy of the items. When a user reorders the list you rearrange your copy of the items, recache it, and re-bind the ReorderList control to your updated copy.

How you choose to cache the items might depend on how much information is in the collection. For small collections you can just use ViewState, but for larger collections you'd probably want to cache them on the server with the Cache API or session variable.

This example will use ViewState since it assumes small and simple collection.

Here is the code that does all this:

protected void Page_PreRender(object sender, EventArgs e)
{
    // doing this at PreRender so we don't have to worry about when/if 
    // we should bind based on if it's a postback or callback and what not.
    OrderList.DataSource = OrderItems;
    OrderList.DataBind();
}

protected void SaveOrder_Click(object sender, EventArgs e)
{
    //normally you'd save to reordered list to the DB or whatever
    foreach(string s in OrderItems)
    {
        // output the re-ordered values to page
        Message.Text = Message.Text + s + "
";
    }
}

protected void OrderList_ItemReorder(object sender, ReorderListItemReorderEventArgs e)
{
    string[] items = OrderItems;
    List list = new List(OrderItems);
    //using a list for the reordering (convienience)
    string itemToMove = list[e.OldIndex];
    list.Remove(itemToMove);
    list.Insert(e.NewIndex, itemToMove);
    OrderItems = list.ToArray();
    //you could save this to the DB now, but this example uses a 
    //save button to batch up changes
}

As you can see, this is pretty straight forward. We maintain our own copy of the items collection putting it into ViewState between server trip. When the user makes a change the event handler just syncs our copy of the items collection. On PreRender we rebind the ReorderList to our collection, which should always be in sync with the client's copy. And finally, the save button can just commit the changes using our copy.

Dell XPS M1730 - Review (part 3): Keyboard and Touchpad

Dell has offered pretty much the same keyboard on their laptops for the last 10 years. They have been notoriously high quality with a comfortable layout, full size keys. a decent tactile feel, and reasonable durability. But over the years there has been no more than very minor tweaks to the basic design.

The XPS Keyboard Into

Breaking from the old and moldy, the Dell XPS M1730 (and some Vostro 17" models) now sport a much newer keyboard design featuring a full-sized numeric keypad.

The keypad is a very welcome change for quite a lot of people. These have been around from other 17" laptop vendors for many years, but for some reason Dell just never adopted it before.

This was also one of the features that excited me most about the XPS M1730 too.

The M1730 keyboard has pretty much the same overall feel and construction quality as the older designs, plus it has handy back-lit keys.

The Layout - Short-Bus Keys

But I have a less favorable feeling about the layout of the keys.



On the older keyboards, there were two rows of half-sized keys at the top-right side of the keyboard where most of the special keys reside... delete, home, page-up, page-down, etc. The nice thing about dell's old design was that the keys had the same relative layout as a desktop keyboard in that the insert key was above the delete key, the home was above the end, and page-up was above page-down... in that order.

On the new keyboard, there is no second row of keys at the top.

As you can see from the diagram, all of the special keys are in the same row as the function keys (F1 - F12). This breaks the normal pattern of use for these keys. I thought that this would be something I'd just get used, but after about 120 hours of use I've discovered that the positioning of these keys still annoys me just as much as when I started.

This laptop is marketed heavily toward gamers, so the breaking of the traditional relationships between these keys makes little sense. Games often map commands to these specific keys based on their relative positions so it seems strange that dell would choose to break the traditional pattern here. As a programmer I make frequent use of all of these keys so it does have quite an impact on me too.

No sleep for you hippie!

Another thing that annoys me is that the old "sleep" key (fn + Esc) is absent on this keyboard. Instead they have a new hibernate key (fn + F1). Sure, hibernate is "safer" for your data, but with 4GB of RAM hibernate also takes a LOT of time to get into and out-of.

The first thing most technical and power users do is turn off the "sleep when the lid is closed" feature... yes... that feature REALLY pisses us off!

So this leaves the XPS without an actual "sleep" button or key combination. There is, as far as I can find, no way to remap the fn + F1 key to sleep mode.

If you are like me and aren't going to be leaving the laptop unused for a week, then you will highly favor sleep mode so you don't have to wait 5 minutes before you can pack up and move. Vista is smart enough to power back up from sleep mode and do a formal hibernate if the battery starts to run dangerously low while the system sleeps.

The fact that the system might automatically power up from sleep to hibernate is something you should keep that in mind!.

Laptops run hot very quickly if they don't get good air-flow. If you store it in a laptop bag and it comes on to hibernate, it could overheat itself before it finishes hibernating... I've had that happen with my old Inspiron before, and I'm sure the XPS is more prone to this due to the more powerful components.

For this reason I always store my laptop with the back-vents up, and leave the top open... just in case.

Don't plan on taking any breaks!

And one other minor annoyance for me is the strange location of the pause key. The old keyboard layout had a dedicated key for pause/break, but this one moves it to fn+F12. When you are playing a game and need to take a break, it is quite annoying to have to go looking around for the magic key combination.

As a programmer I run into the problem with the other function for this key, the break command which is used by many development tools. Fortunately the tools I use can remap this command, but command line debuggers and compilers often do not.

Oddly enough, it does sport a dedicated print screen button. Surely it would make more sense to the vast majority of users, gamer and regular folk both, to have pause there instead of print screen?

Touch Pad:

The touch pad is not worth much talking about. It is a standard Synaptics touchpad and is pretty common these days on must about all laptops. It has a shape that is close to proportional with the wide-screen display, and has the expected two buttons and scroll regions. It is also pressure sensitive and has good configuration tools for sensitivity and pointer control... nothing special or new here.

The touchpad does appear very small, but that's just because the rest of the laptop is so big. I've compared it to my old Inspiron and it's the exact same size and shape. There really isn't much room to have mounted a larger touchpad anyway and just about everyone will prefer an external wireless mouse anyway.

The only notable thing about the touchpad is that it has a really pretty LED back-light that causes the giant XPS logo in the middle to glow... and you can set it for  any of 16 amazingly bright colors.

Bottom line:

In general I'm happy to have a real number pad back. I've been using laptops for so long now that I'd gotten used to not having one and no longer miss them. Having it back is like getting to known an old friend again.

On the flip side though, I find that having the main keys offset from the center of the screen is annoying. With desktop keyboards you can physically move it around so you are centrally aligned with the screen,  on a laptop you are stuck with the offset position and end up sitting off to the left of center when using the machine.

I personally prefer the older Dell keyboard designs without the keypad, but that's probably a minority opinion. Most people learned to type on a desktop, and loosing the numberpad really annoys them, as it did me when I first made the switch to laptops. So having the keypad will outweigh any other aspect for the majority.

Friday, March 21, 2008

TicketDesk - Open Source Help Desk Issue Tracker

For the last several weeks I've been spending most of my spare time working on a new application, and now I'm proud to announce...

TicketDesk!

TicketDesk is an open source issue tracker. It is a fast, simple, and nearly effortless tool that will assist Help Desks in servicing the needs of their users.

TicketDesk is written in C# on the .NET 3.5 framework. It can be hosted on any IIS 6 or IIS 7 web server with SQL Server 2005 (or SQL 2005 Express). And it makes use of Microsoft's Ajax and LINQ to SQL technologies.

Background:

At my employer's office we use a help-desk application called Census by MetaQuest software. Census, to put it mildly, is total crap. It is slow, cumbersome, complex, and annoying to use. It is also a nightmare to install, keep running, and administer.

When searching for alternatives I came to realize that nearly all of the help desk applications on the market suffer from the same kinds of problems.

They all have these complex customizable workflows you have to manage, complex permission systems, and so many fields that even the dedicated IT staff end up ignoring most of them. They Also tend to be hard to install, difficult to configure, and tedious to maintain.

Then you have the endless categorization... what's the priority, what's the severity, what's the impact on the users, what kind of problem is it, what kind of user reported the problem, what operating system is installed on the system with the problem, what gender was your first pet dog....

ENOUGH!

The end-user's don't want complexity.

Requiring end-users to fill out complex forms with all kinds of technical jargon just scares them... which means they don't fill out tickets until their small problems have become really big ones.

The help desk doesn't want complexity either.

Sure, they are used to complexity, but your help desk is overworked, under-staffed, and are under a lot of pressure to fix everything RIGHT NOW!

It doesn't matter if it is a 5 person mom-and-pop shop or a fortune 50 company, your help desk is always under the gun and they just don't have time to fill out a "detailed" report with 500 fields just to say "I rebooted the server and everything is fine now". 

The marketing for most help-desk applications will go on about searchability, knowledge-bases, and how your help desk tickets can be used to build a database of problems and solutions which will improve efficiency by leveraging past experiences. Some even promise to turn your issue tracker into a customer-facing self-help support web site (if you aren't ready to vomit now, you haven't worked on a real help desk before).

That's a great idea, and it does well the sales meetings with upper management.

But it also total bullshit!

It overlooks the obvious fact that a help-desk issue tracking system is exactly the wrong source for that kind of knowledge sharing. End users describe their problems as best as they can, which means they describe their problems badly at best. The help desk staff will do an equally poor job explaining what they did and how they fixed the problem.

That's just how it is.

No amount of policy, management directives, training, or threats will change the fact that data in your issue tracking system will be hard to search, sketchy about the details, and will totally fail to make a useful knowledge base.

To be successful, your ticket tracking system needs to be efficient, fast, and easy to use. It needs to allow for quick and frictionless communications between the users and IT staff. And most importantly, the system must NOT get in the way. It must be nearly effortless to use and so simple that even a Mac user could figure it out.

TicketDesk is born:

TicketDesk wasn't "planned". It was just something I decided to in my spare time. I needed to write it in only a couple of weeks using no more than 4 hours a day of my time.

It needed to support the end-users and IT staff, but without any unnecessary administration or maintenance.

So the general idea was to implement the simplest ticket tracking system as possible. It would have a very simple non-customizable workflow, as few data fields as possible, and be easy to setup, maintain, and administer.

The other goal was to use as little code as possible. So TicketDesk would have to leverage everything the .net 3.5 framework could muster that might reduce complexity and improve my productivity.

In formulating the basic idea, I also realized that TicketDesk could probably meet the needs of most small IT shops, and probably many larger ones as well. It would also be a good learning tool for beginning programmers and could act as sample code for experienced developers that might be new to asp.net to the 3.5 framework.

So I decided that it would be a great open source project for CodePlex (I may be wrong on that, only time will tell there).

TicketDesk Design:

TicketDesk is designed as a pure help desk issue tracking system. The focus is on the relationship between your users and your IT staff.

It doesn't attempt to be a customer facing support product.

It doesn't attempt to be a customer relationship management system.

And it is not a bug-tracking system to support the software development life cycle.

TicketDesk allows users to submit tickets. It provides help desk with a way to keep track of the tickets. And it facilitates smooth communication between users and help desk.

That's all it does.

TicketDesk concentrates on being simple and effortless. It has very few data entry fields, and demands almost no configuration or administration overhead.

TicketDesk leverages several common web 2.0 concepts to make tickets easier to track and to make working through a ticket more like having a conversation.

TicketDesk probably isn't for everyone though. Large shops that demand tight administrative control over process and permissions will certainly not like it.

But if you have a help desk that wants a system that gets things done, take a look at TicketDesk over at CodePlex...

It's simple to install and free.
 

Wednesday, March 19, 2008

Dell XPS M1730 - Review (part 2): Power and Battery

When choosing a laptop, an important aspect battery life. For me, this is perhaps THE most important aspect, so I'll be spending quite a lot of text on this post.

Battery Life of the XPS M1730

The XPS M1730 gets much better battery life than older gaming systems, especially the original gaming rigs that used hacked-up desktop parts.

My particular XPS has:
  • Core 2 Extreme at 2.8GHz

  • Dual gForce 8700M video cards 

  • Dual 7200 RPM hard drives
Here are some numbers from my informal tests:
  • Power Saver Mode, no wireless: 2 hours 10 minutes.

  • Power Saver Mode, wireless on: 1 hour 40 minutes.

  • Balanced Mode, no wireless: 1 hour 50 minutes

  • Balanced Mode, wireless on: 1 hour 25 minutes
 I don't test high performance mode because that shouldn't be used with battery unless you are a moron... but when I accidentally left it in high perf mode it got about 30 mins with wireless turned on.

While 1 to 2 hours is still pretty short compared to many other laptops, it is a reasonable amount of time considering how powerful the hardware is.

If you need more than about an hour and a half out of it, you'll want to buy a spare battery.

Power Management:

There have been tons of advancements in power management over the years, but prior to Vista the OS had limited ability to use those features. The hardware manufacturers were often lazy and so their drivers neglected power management.

But the XPS was built from newer hardware that heavily supports intelligent power management, and most of the drivers are designed to give control of those features to Vista.

The result for the M1730 is a system that can scale from very low power states to very high states in very small increments as demand increases. It has amazingly fine control over how much power is being used, when, and where.

Most impressive are the power management improvements in the newer gForce 8700M video cards.

The XPS M1730 can balance power usage against performance much more aggressively and intelligently than with any other system I've ever used before.

Tweaking for more Battery Life:

Other than turning off wireless, almost nothing else seems to matter much to battery life on the M1730. Turning off the numerous LEDs, keyboard light, and lowering the screen brightness didn't help at all. The difference between the "balanced mode" and "power saver mode" in Vista also didn't push the time out much.

So basically, just put the thing in the dell recommended power scheme (balanced) and turn off wireless when you don't need it.  The system will do about as good as it can all by itself.

The Bad.
  • Longer Recharge Time: 
     
    Most Dell laptop models have a rapid recharger build-in which allows them to recharge very fast (under an hour on my old Inspiron). Sadly, the XPS lacks this rapid charger. The battery will charge to about 90% rather quickly (45 minutes to an hour), but capping off that last 10% can take another 30 to 45 minutes more.

  • No Secondary Battery:  Having a secondary battery gives you more time, but it also allows you to swap out the primary battery without fully shutting down or hibernating. With 4GB of RAM hibernating and restarting can cost you 5 to 10 minutes.
     
    If it had a secondary battery, even a small one, it would save me quite a lot of time.

  • No External Charger:
     
    This has been true for almost all laptops for years now, but it still annoys me.  
Minor points:
  • The Battery for the XPS M1730 is shaped funny which makes it hard to fit the battery into most pouches on most laptop bags.
        
  • The battery release latch is placed exactly in front of the finger hold making it difficult to swap the battery without turning the system completely over and using both hands.
     
  • The Power Supply for the XPS M1730 is huge... like X-Box big! It's about the same size as an external USB hard drive, and a tad heavier. It is so large that carrying it with you is very cumbersome and adds a lot of weight to an already very heavy package.
     
  • The power cord is very thick and heavy. It also doesn't fit very well into the power socket on the laptop. Sometimes I've noticed that the weight of the cord alone can unplug your laptop... which is VERY annoying indeed!

Bottom line:

The XPS M1730 has VERY aggressive power management features. Battery life is shorter than most laptops, but it still can get enough time to be usable for most people. It certainly does better than the rumors would have you believe.

Gaming will run batteries dry significantly faster, but compared to older gaming models the XPS still does quite well.



Dell XPS M1730 - Review (part 1)

I recently has to replace my old laptop (a Dell Inspiron 9400; a.k.a. Inspiron E1705).

It was a fine machine and served me well for just over 2 years. But last week all the smoke leaked out through a hole in the video card and it stopped working.

I'm a programmer, but I do quite a lot of my work outside the office. So rather than muck about trying to keep a home and work desktop both setup with identical development environments, I prefer a beefy laptop instead.

I don't travel professionally though, so things like weight and space haven't been all that important to me.  Instead, I want as much power as I can get in my laptop, and so I've always tended to buy very high end systems (usually in the $3000 - $4000 price range).

In researching a replacement for my old system, I became a victim of timing.

Currently it's very hard to get a non-gaming laptop that has any serious muscle. True, there are a few good high-end business and personal laptops, but right now the number of options is small, and all of the systems topped out just shy of where I wanted them to be.

So for the first time, I started looking seriously towards gaming laptops.
I always "look" at gaming laptops of course. I got my start in the industry building custom PCs, and I've always been a bit of a hardware enthusiast at heart. But this was the first time I could seriously consider a gaming laptop as a viable option.

Anyway... I ended up choosing an XPS M1730.

When I was looking for practical reviews about the M1730, I noticed that there weren't many well researched reviews out there, and the few I could find concentrated exclusively on the pure gaming aspects. The reviews totally glossed over most of the really important questions that I had about the viability of a gaming laptop for other uses.

There is also a lot of misinformation out there about gaming laptops in general, and the M1730 reviewers seemed too lazy to investigate and tell you which were true and which were not.

So, I've decided to post a series of mini-reviews about the M1730 from the perspective of a programmer and power user. I'll be covering the more mundane, but very important things that aren't being covered in the mainstream reviews.