As a software developer and a geek before all, I dream that paper and pencil become useless by replacing them by their numeric counterpart. Obviously, we are far from this dream. However, with the advent of Pocket PC, and the Pocket Framework specifically, I've found a powerful tool in the pursuit of this dream.
In my quest for the perfect project for the Code Project competition, I happened to find one of those little pieces of paper that my girlfriend uses, week after week, for her shopping list. Great! I've found my project, and also I've found a way that pencil and paper become useless. I'm going to build a Pocket PC application for shopping planning!
This article is written as an extremely condensed analysis document. You will find information regarding the requirements, the user interface guideline, the system's design, and finally, a section where you will find implementation details about some of the most interesting parts of the code.
The following terminology is used throughout the Shopping App discussions:
- Cart: Represents a list of Cart Items. This is a shopping list, the numeric counterpart of a piece of paper used for shopping planning.
- Cart Item: Represents a specific item in a Cart, each item being a product you want to buy.
- Product: A product is a Cart Item.
Background - The User Requirements
The main challenge here with the shopping application was not really the code part, but the design part. Obviously, the goal was to build a funny application, but before all, a useful one that can really be integrated in day to day life.
The requirements for the application can be summarized as:
- User intuitive: People don't read help files! I think any professional developer who's involved with customers will confirm that people don't read help files. Application should be intuitive and user friendly or else people will not use it.
- User should have the possibility to categorize things as much as possible in order to filter information.
- User should have the possibility to define products for quick entry.
- User should have the possibility to define products' units. Each product should offer a default unit which is empty by default.
- User input should be kept to a minimum.
- Using the application should be an advantage versus using a piece of paper: if the user does not get benefits from using the Shopping application, he will get rid of it.
The Shopping Application - User Interface Guideline
When the Shopping application opens, it displays a list of existing carts. The first time you open it, you face a blank screen. Available carts' list can be filtered to display carts that meet specific criteria based on the categories in which the cart belongs.
To add a new cart, either click on the New icon, or select an existing cart in the list and click on the Clone icon to use the selected cart as a template for your new cart. Opening an existing cart can be achieved either by double clicking a cart in the list, or by selecting a cart in the list and clicking the Open icon.
Figure 1 shows the initial screen with several carts that meet the current filter (Category = Grocery).
Figure 1: Starting screen for shopping application.
Figure 2 shows the Product definition screen. This is where the user defines the products needed when creating a new Cart. You access the product definition screen by clicking on the Option button, then selecting Manage/Product Editor menu. To add a new product, click the New button and enter the product's name in the text box. Optionally, you can specify a default unit for each product. Click the Add button to add the product. Changes are automatically saved as the window closes.
Figure 2: Product Definition screen.
Figure 3 shows the Unit definition screen. This is where the user defines the product's units. You access the unit definition screen by clicking on the Option button, then selecting Manage/Unit Editor menu. To add a new unit, click the New button and enter the unit's name in the text box. Click the Add button to add the unit. Changes are automatically saved as the window closes.
Figure 3: Unit Definition screen.
Using the Cart Screen
The Cart screen is the numeric counterpart of a paper based shopping list. This screen presents the shopping list items with the following information: product's name, quantity, format, and notification icon (a note icon stands next to the product's name if there is a note associated with the entry). Cart's title and category can be changed on the Properties tab.
The Plus and X icons are used to add and remove items in the list. Items can also be moved up and down on the list with the Up and Down arrow icons. The last icon is used to toggle the operating mode from shopping to editing. In shopping mode, an item can be set as checked by clicking on it with the stylet. While in shopping mode, it is not possible to add or remove an item.
Changes are automatically saved as the window closes.
Figure 4: Cart screen.
The Item Editor
This screen shows off when you click the Plus icon in the Cart screen, or when an existing item is double-clicked. To add a new item to the list, select a product from the list, specify the quantity, and optionally change the item's unit if it is not the correct one.
The products list can be easily filtered by using the ToggleCategory button. When you click on a toggle category (Mno, for example), then only products beginning with the letter 'm' or greater are displayed. Clicking repetitively on a toggled category alternates the category's letters (Mno, mNo, mnO, Mno ...).
The Notes tab contains a text area used to add a note to the item. As mentioned previously, when a note is attached to an item, an icon stands next to the item's name.
Changes are saved with the Saved (green) button, while the Cancel (red) button is used to cancel changes.
Figure 5: Item Editor Screen.
Design & Implementation
The design follows the 2-tier architecture (user interface, business logic). The data-layer tier has been included in the business rule to simplify. The project has been divided into three assemblies:
- Shopping.GUI: this is the executable. All forms can be found there.
- McSoft.UILib: All user controls used by the Shopping assembly are located there.
- Shopping.Engine: this is the business rules.
The application's design is rather simple. The business rules consist in only six public classes.
ShoppingApp: This class is an abstraction of the application. This class contains several methods to manage carts like: creating, deleting, opening, and cloning.
Product: This class is mainly used by the Product Editor screen, it represents a single product. This class offers a serialize method that encapsulates the XML serialization of the products list.
Cart: This class is an abstraction of a shopping list. It contains a collection of
CartItem and provides a serialize method that encapsulates the XML serialization of a
CartItem: This class is an abstraction of an item in a
Cart. It provides a serialize method that encapsulates the XML serialization of a single item.
ProductsComparer: This class is used for custom sorting of
ArrayList. For more information, see section: Implementing Custom sorting on
CST: This is a utility class where you will find only public constants that are used by other assemblies.
User Controls and Double Buffering
Several issues with the Compact Framework were raised during the coding of the Shopping application. However, the most obvious one is the fact that available user controls are very limited in terms of features and diversity. As an example, the
Button control does not have a
picture property, which is a shame. So, I decided I had to get my hands dirty and write my own controls.
I wrote 9 user controls and 2 supporting classes for this project. I will not go into the details of each control but I will pinpoint some of the most helpful tips to writing your own controls for the Compact Framework.
- For each control you write, override the
OnClick method, and be sure that the following code is present:
protected override void OnClick(EventArgs e)
If you forget to do so, clicking on your control does not set the focus on it. The side effect is that your other controls will not receive the
LostFocus event. In my case, I solved the problem by creating an abstract class, inheriting from
McSoftControl). All my controls inherit from this class, so I don't need to care about it. If you override
OnClick for any of the descendant controls, don't forget to call
- If you write your own controls, the first thing you will discover is, to do fancy and cool controls, you absolutely need to understand how to override the
OnPaint event and custom draw your control. I will not go into details on how to use the
Graphics class. However, I want to specify that if you want to do a clean job, you need to use double buffering in order to remove flickering.
Double buffering is a technique where you render your control into an image buffer into memory, then update the actual control's display with the buffer's contents. The following piece of code demonstrates the technique as you can find it in the
protected override void OnPaint(PaintEventArgs e)
Bitmap offScreen = new Bitmap(this.ClientSize.Width,
Graphics gOffScreen = Graphics.FromImage(offScreen);
e.Graphics.DrawImage(offScreen, 0, 0,
Also, when using double buffering this way, do not forget to override
OnPaintBackground, but without any implementation, like in the following:
protected override void OnPaintBackground(PaintEventArgs e)
Implementing Custom sorting on ArrayList with IComparer
One of my favorite classes in the .NET framework is the
SortedList collection. Unfortunately, this class does not exist in the Compact Framework. My first intend was to use the
SortedList collection to add the available products in order to sort them based on their name. After a quick research, I've found, it is possible to achieve the same functionality with an
ArrayList collection and a custom comparer based on
In my case, I have created a custom comparer called
ProductsComparer which compares the
name property of two instances of
Product objects. Here is the complete implementation of the
public class ProductsComparer : IComparer
int IComparer.Compare(Object x, Object y)
return( (Product)x).Name.CompareTo( ((Product)y).Name);
And here is where I use this class to sort an
Product instances based on their
IComparer myComparer = new ProductsComparer();
Implementing the OnDoubleClick Event
Do not search for the
OnDoubleClick event in the Compact Framework, it doesn't exist. I had in mind to override the
OnDoubleClick events on my lists in order to allow a cart to be opened when the user double clicks a cart in the list. Fortunately, this event can be easily simulated with the
OnClick event. Here is how I have implemented it in
OwnerDrawnListView class (base class for
public delegate void DoubleClickEventHandler(object sender, EventArgs e);
public abstract class OwnerDrawnListView : McSoftControl
public event DoubleClickEventHandler OnDoubleClick;
private int previousClick = SystemInformation.DoubleClickTime + 1;
protected override OnClick(EventArgs e)
int now = System.Environment.TickCount;
if(now - previousClick <= System.information.DoubleClickTime)
if(OnDoubleClick != null) OnDoubleClick(this.selectedIndex, e);
previousClick = now;
This is release 1.0 of the application.
- Add prices to products.
- Add categories to products.
- Clean code to merge together Product, Unit and Category editor.
- Update Carts filtering with more powerful filters.
- Add an option page where users can change application's color, delete confirmation, etc...