Freigeben über


Return of the FBI (Fish Based Interface)

Since I last took to the keyboard to write a blog entry, things have changed. For a start, I've supplemented the Dell Venue Pro 8 device I've been using with a Surface Pro. I couldn't resist getting one of the 1st gen Surface Pro devices when it went on sale at a special price (keep checking MicrosoftStore.com in case it happens again) and it's a great device. I have a work-supplied ThinkPad Twist, and the Dell of course, but the Surface Pro is now the computer I bring with me the most often.

The fabled Power Cover keyboard for the Surface Pro went on pre-order from Microsoft the other day (it is in stock at time of writing, but check for yourself as its status has changed several times over the past few days), and this should resolve perhaps the only issue with the machine: a less than record-breaking battery life. I've also signed up for a Kickstarter called "FreedomCase" which will even resolve the fact the built-in stand has only one tilt position (only one angle? How can we live like this?!)  although it will currently not work with the Power Cover, only the standard Type and Touch covers. Fingers crossed a compatible version will be available at some point in the future.

FBI

Rumor has it that many years ago, I wrote a little utility for the Pocket PC for launching apps. This app was called “Fish Based Interface” (or “FBI”) as the icons were all in the shape of fish. I’m not entirely sure why I did it, but I was young and naïve and probably thought it was funny. Rumor further has it, that this app was shown to Bill Gates at a trade show, who looked at it, and said “Huh”. The only remaining mention of it on the Web which I can find says "This program is mainly a novelty for now…. kind of an interactive screensaver of sorts. I found that I never used this program."

In order to celebrate these extraordinary events, I have resurrected the Fish Based Interface, albeit in a slightly more mature and subtle way, as I’m now in my 40s and try to act like a sensible member of society (hahahaha). As you may or may not know, I like writing task management apps, as it’s more fun than doing actual tasks. So I’ve combined my love of piscine user interfaces (PUI - I just copyrighted that term) and lists of tasks, to create a new task management app which is currently on the Windows Store.

The app is simple, and it’s designed to load up on your Windows 8 tablet and quickly remind you of what you need to do today. You can add tasks, and move them around to assign priority. Each task is a TextBlock which is stored in a GridCollection, using databinding to link them to an ObservableCollection of my task object. Here's a screenshot to prove you can hardly see the fish moving around in the background at all.

Note: If you ever create a class called "Task" in your C# app, you will find your program compiles and runs perfectly, until you start messing with Await/Async and then things go downhill very quickly. Obviously there is an existing class called "Task" that you shouldn't try to replace with your own class. This confused me for an embarrassingly long time.

The interface of this latest task management app is designed primarily for touch: touch the tasks to drag them around, double-tap them to edit them. Drag-and-drop them to move or mark them as completed. I like my Windows tablets, you see, and stabbing the screen with my stubby fingers makes me happy.

Do you see the curved edges of the task tiles in the screenshot above? I'm not afraid to be different and move away from rectangles. If you want to add curves to your XAML shapes, wrap them in a <Border> object, and use the CornerRadius property. 

Drag-and-drop

Drag-and-drop is nice and simple to implement in WindowsRT apps. You set AllowDrop to be true on the XAML controls you wish you accept a dropped object, and also add a Drop event so you know when it actually happens. You might also want to support DragOver and DragLeave events, to give you a chance to change the appearance of the drop target so your users know something will happen.

The source of the dragging-and-dropping objects was my GridView, the control bound to the task database. I simply needed to set the CanDragItems and CanReorderItems options to true, and the rest was.. no wait, I tell a lie: It was also important to handle the DragItemStarting event from the GridView. This event must be handled in order to set up the data that will appear when something is dropped into the target. Here's what that code looks like:

 

private void TaskGrid_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
        {
            var item = e.Items.FirstOrDefault();
            if (item == null)
                return;

            e.Data.Properties.Add("item", item);
            e.Data.Properties.Add("gridSource", sender);

        }

 

The implementation of the actual drop handler can then extract the necessary information, like this:

 

private void TaskDeleteDrop(object sender, DragEventArgs e)
        {
          

            object gridSource;
            e.Data.Properties.TryGetValue("gridSource", out gridSource);

            if (gridSource == sender)
                return;

            object sourceItem;
            e.Data.Properties.TryGetValue("item", out sourceItem);
            if (sourceItem == null)
                return;

            // sourceItem is the object that the user dropped.
            // So now you need to do something with it.

        }

 

Overall, implementing this was a very pleasant experience for something that makes your project very tactile. For more details, check out this MSDN topic.
 

 

Serialization

In previous apps, I've struggled with saving the state of the app. The trickiest part was converting the internal data used by the app into a format I could save: this is known as "serialization".

This time, I found the absolutely best way to do it – using DataContractSerializer . Using this class, you provide the datatype of the data you need to save (and this is probably the class you created to store all your app's individual bits and pieces, or arrays of bits and pieces) and the data object itself: and then you get a stream back, reading for saving. It's super, super convenient. To think I ended up writing my own XML Parsers in previous apps.. shudder..

So, as an example, here's the Save() code from my app:

  public static async Task SaveData()
        {
         
            StorageFile userdetailsfile = await ApplicationData.Current.RoamingFolder.CreateFileAsync("MyAppsDataFilename", CreationCollisionOption.ReplaceExisting);
            IRandomAccessStream raStream = await userdetailsfile.OpenAsync(FileAccessMode.ReadWrite);
            using (IOutputStream outStream = raStream.GetOutputStreamAt(0))
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(MyAppsDataType));
                serializer.WriteObject(outStream.AsStreamForWrite(), App.MyAppsData);
                await outStream.FlushAsync();
                outStream.Dispose();
            }
            await raStream.FlushAsync();
            raStream.Dispose();
            raStream = null;
            userdetailsfile = null;
}

 

And that's it – the data stored in MyAddsData (which was an ObservableCollection which I made static and stored in App.xaml.cs so I can access it from any class) is converted and saved. Painless.

There is one catch: you must include a constructor, even an empty one, in your data class in order for DataContractSerializer to work. Leave it out, and you get weird errors.

For some more information on Serialization, here's a good topic on c-sharpcorner.