Great User Interface: Read Users’ Mind

Ever looking up a word online and having to look up another word in the original word’s definition? Here are the steps to do it if you look up the word online.

  1. Go to dictionary.com
  2. Enter the word to look up
  3. Read the definition
  4. (Upon finding another new word) Copy the new word and paste it to the search box

Step 4 may not be much, or it may be (a sequence of a double mouse click, CTRL+C, move mouse cursor to the search box, CTRL+V, and ENTER), but dictionary.com has managed to simplify that step 4 into the following sequence of steps: click the new word, click the tooltip immediately above the new word. That’s it–two clicks and barely a muscle to move the mouse.

Edit Post Screen (Variant II)

I thought of this during the long wait at In-n-Out drive-thru (yes, it was good).

Utilizing the pivot control, I could place the writing area in one view and the auxiliary components (less used features) in another view. Which components are more or less used is up for pointless debate, though.

I can see how this is beneficial for the workflow of writing a blog post. When writing a post, I would normally start with a title and move on to writing the content. While writing, I’m focusing on writing and only writing. When I’m finished, I would set the categories. Writing the post content and setting the attributes of the post are two separate tasks in the post writing workflow; hence, the separation of the views.

Edit Post Screen with Pivot Control

The UI Design and Interaction Guide for Windows Phone 7 does not recommend pivot control for this kind of usage, however. The following are excerpts from the guide that the pivot control in Edit Post screen violates.

Pivot pages should not be used for task flow.

The pivot control should only be used to display items or data of similar type.

I understood why the first item of guideline is there. A task flow requires a strict order; user has to complete task one before proceeding to task two. Pivot control does not enforce that. User can navigate to views in pivot control in any order (except there is always one same initial view). This is less of an issue for this scenario. The big issue is that pivot control does not guarantee that a user will navigate to all views. I could click [save] and realize that I forgot to assign categories in the other view.

For the second item in the guideline. I could argue that I do use the control to display items of similar type: blog post’s properties of most used, and less used. But the author(s) of the guideline may disagree with that. Microsoft uses the email reader to show how a pivot control should be used. In the email reader, pivot control is used to display emails with status unread, flag, and the like in the different views.

Whether a pivot control is appropriate for the Edit Post screen, I need a usability testing to know if it will work for users.

Verbose WHERE Clause with LINQ to SQL

Table Persons

If you come from the world of always-use-stored-procedures or at least you always write your own SQL query, you’d be curious how LINQ to SQL translates your C# code to SQL query. Say you have table Persons with fields PersonId, FirstName, LastName, and Age. PersonId is the primary key of the table Persons.

In this example, we want to update a particular row (PersonId = 1) with a new Age value. So, we write the following block of code in our application.

Entities.DataContext context = new Entities.DataContext();

int personId = 1;
Entities.Person person =
    context.Persons.SingleOrDefault(p => p.PersonId == personId);
person.Age = 24;
context.SubmitChanges();

To see the generated SQL query, we want to redirect the log of DataContext object to console.

Entities.DataContext context = new Entities.DataContext();
context.Log = Console.Out;

int personId = 1;
Entities.Person person =
    context.Persons.SingleOrDefault(p => p.PersonId == personId);
person.Age = 24;
context.SubmitChanges();

Now, when we run the application, you will see the SQL queries generated by your code in console window. The SQL query will look something similar to the following.

UPDATE [dbo].[Persons]
SET [Age] = @p4
WHERE ([PersonId] = @p0) AND ([FirstName] = @p1) AND ([LastName] = @p2) AND ([Age] = @p3)
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- @p1: Input NVarChar (Size = 4; Prec = 0; Scale = 0) [John]
-- @p2: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [Smith]
-- @p3: Input Int (Size = 0; Prec = 0; Scale = 0) [23]
-- @p4: Input Int (Size = 0; Prec = 0; Scale = 0) [24]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926

If you’re used to writing your own query, you probably wonder why the WHERE clause is verbose (or wordy, an English major will say). You see the query tries to find the row to update by matching every single field in the table with their old values. “Well, that’s dumb, ain’t it?” you say. “We can find the row to update by matching only the value of the primary key, PersonId.” Here’s how.

Properties Window

  1. Go to your Solution Explorer in Visual Studio and double click the .dbml file.
  2. Click the property PersonId on the class diagram.
  3. Go to Properties window (it’s on bottom right on default window setup) and find the property Update Check. The current value should be Always.
  4. Change it to Never.

Repeat step 2-4 for all properties (FirstName, LastName, and Age).

Update the application to update the Age to 25 (previously 24). Rebuild and re-run the application. You will see the update statement that you probably always write.

UPDATE [dbo].[Persons]
SET [Age] = @p1
WHERE [PersonId] = @p0
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [25]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926

So, what’s the purpose of the property Update Check? The property description says it all. It’s to control the frequency of optimistic concurrency checking.