While delving further into Android, I’ve been creating a “hello world” type of app – its not as complex as what MahTweetsMobile will be, but it is encompassing a lot of different elements (custom ListAdapter, SQLite for persistent storage, different types of menus, loading external intents, etc).
One “difficult” element has been events. I say “difficult” because by design, its freaking nuts.
Scenario
I’ve got a custom ListViewAdapter, for my custom list elements, where the ListView items include a checkbox. This checkbox is to indicate the status of the items (for reference, its a shopping list app, you tick the checkboxes to show which items you’ve bought while shopping, the items then go grey in colour).

I wanted to add a “long press” context menu so that you could easily bring up a menu (with options such as Edit Item or Delete Item)
The Problem
Normally when “attaching” event listeners with ListViews, you use setOnCreateContextMenuListener on the ListView itself. You then override your Activity’s onContextItemSelected, figure out what menu button was pressed as well as what item it was pressed on.
ListView x = (ListView)findViewById(R.id.ListView01);
x.setOnCreateContextMenuListener(new OnCreateContextMenuListener()
{
public void onCreateContextMenu(ContextMenu contextMenu, View view,
ContextMenuInfo arg2)
{
contextMenu.add(0,CMENU_DELETE, 0, "Delete Item");
}
});
public boolean onContextItemSelected(MenuItem item)
{
AdapterContextMenuInfo menuInfo =
(AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
switch (item.getItemId())
{
case CMENU_DELETE:
//Use menuInfo.position along with the adapter.getItem
//ie Product p = (Product)adapter.getItem(menuInfo.position);
return true;
}
return true;
}
As you can see, its ugly code, but it works. Sort of. The problem was the checkboxes.
As soon as you add checkboxes to the individual items view, any listener created on the ListView never fires – the CheckBox swallows the event!
The Apparent Solution
Apparently this is a known bug (or more accurately, this is by design!). The solution is to set the event handlers on the rows themselves; inside the custom ListAdapter, when you’re inflating the various UI elements – look at my previous post on Custom ListAdapter, it’s under the getView method – on that “rowLayout” use the same setOnCreateContextMenuListener as the code used on ListView above, except only apply it to the individual row’s.
That would be fine if you didn’t care which item was pressed. That’s right, the cast to AdapterContextMenuInfo of item.getMenuInfo() in your Activity’s (yes, your activity has to override this, nowhere else works. argh!) onContextItemSelected always returns null because item.getMenuInfo() is always null.
The Actual Solution
I have no idea how I stumbled across this solution – I think I was in the process of undo-ing lines of code to try and figure out “where I’d gone wrong”.
Fact: To get the event to fire with checkboxes you need it to be set on the rowLayout.
Fact: To get menuInfo to be anything other than null (ie, tell you where it came from), you need it set on the ListView
Solution? Combine them. Wait, what? Two event listeners to get them to work? Yup.
On the rowLayout, set the listener:
rowLayout.setOnCreateContextMenuListener(new OnCreateContextMenuListener()
{
public void onCreateContextMenu(ContextMenu contextMenu, View view,
ContextMenuInfo arg2)
{
}
});
Notice the lack of code inside the onCreateContextMenu? Well, any ContextMenu items added inside this method won’t have AdapterContextMenuInfo – so don’t set anything, no menus will appear.
Now also set the adapter on the ListView using the code above.
Now it all works. WTF doesn’t begin to describe this.
No Comments
Disclaimer: This post presumes you’ve setup the Android SDK and Eclipse. If not, check out the Android Developer Guide
Some of the Android developer documents seem great, but in general there seems to be a lacking of documentation/examples – while the Java language is giving me no problems, how to do things with the Android API can be a bit of a nightmare to figure out.
It is possibly because Android is relatively new or because I’m used to MSDN which is a fantastic resource. Regardless, I started to want to develop MahTweetsMobile for Android and was having difficulty in ‘binding’ a ‘view’ to a list of elements, ala WPF/XAML’s DataTemplates.
It turns out its not as magical as what WPF is and requires manual binding, but its not impossible.
The View
To get a list to display anything other than just a string, you need to define your own view in either XML or code-behind. I find XML to be a little nicer, and its easier to update.
In Eclipse (I’m sure it’ll work in other IDE’s too, but this is what I’m using), you can create a new view by navigating to res –> layout, right clicking on the folder and selecting New –> Other, then from the popup select Android –> Android XML File
Make sure in the next dialog you select the Layout resource type, and give the file a name like "tweetview.xml" (all in lower case, as java/ADK will complain otherwise).
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/widget32"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<TableLayout
android:id="@+id/widget33"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TableRow
android:id="@+id/widget35"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ImageButton
android:id="@+id/imgbtnAvatar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</ImageButton>
<LinearLayout
android:id="@+id/widget39"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="@+id/txtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
>
</TextView>
<TextView
android:id="@+id/txtTweet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
>
</TextView>
</LinearLayout>
</TableRow>
</TableLayout>
</LinearLayout>
The Model
Just a simple class to hold our data,
package mahapps.MahTweets;
import java.util.Date;
public class Tweet {
public int ID;
public String Name;
public String Text;
public Date Timestamp;
public int getID()
{
return this.ID;
}
public String getName()
{
return this.Name;
}
public String getText()
{
return this.Text;
}
public Tweet()
{
}
}
The Custom ListAdapter
This is the "heavy lifting" code – this is what "binds" a Tweet object to the TweetView.
package mahapps.MahTweets;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import java.util.*;
public class TweetAdapter extends BaseAdapter
{
private List<Tweet> elements;
private Context c;
public TweetAdapter(Context c, List<Tweet> Tweets)
{
this.elements = Tweets;
this.c = c;
}
public int getCount() {
return elements.size();
}
public Object getItem(int position) {
return elements.get(position);
}
public long getItemId(int id) {
return id;
}
public void Remove(int id)
{
notifyDataSetChanged();
}
public View getView(int position, View convertView, ViewGroup parent)
{
LinearLayout rowLayout;
Tweet t = elements.get(position);
if (convertView == null)
{
rowLayout = (LinearLayout)LayoutInflater.from(c).inflate
(R.layout.TweetListView, parent, false);
TextView tv = (TextView)rowLayout.findViewById(R.id.txtName);
tv.setText(t.getText());
//...
//and so on for all the properties/UI elements
//...
} else {
rowLayout = (RelativeLayout)convertView;
}
return rowLayout;
}
}
You can then use this in your main Activity:
ListView x = (ListView)findViewById(R.id.ListView01);
x.setAdapter(new TweetAdapter(this, MyListOfTweets));
If you’re using a ListActivity, you’d just set that Activity’s adapter.
Your ListView items should then appear in more detail!

1 Comment
Now that Rafael Rivera and Long Zheng have launched Geosense For Windows (or you can see Long’s post on it), I can happily brag how MahTweets has supported this since before they started working on it.
Geosense and MahTweets both use the Windows 7 Location and Sensor Platform – Geosense being the provider, MahTweet being the consumer. We supported it in MahTweets to geotag tweets and Flickr photos, in the hope that one day Microsoft or the hardware partners would be kind enough to consider Australia a real country and finally release some relevant hardware to the platform here. So far that hasn’t happened, which is where Geosense steps in.
Geosense with .NET
Geosense by itself doesn’t really do anything terribly exciting to the end user – it’s what Geosense enables for developers that is awesome. Location based services and games are primarily on phones only as it can be a hassle for the user to manually enter their location all the time – now it’s dead easy to bring those services and games to the desktop through rich clients.
To start with, grab the Sensor and Location .NET Interop Sample Library.
Below is an abridged version of the MahTweets GlobalPosition class file (it does some other stuff for other platforms that don’t have the sensor API’s, but that’s just a matter of people manually setting their location).
using Windows7.Location;
public class Location
{
public String City { get; set; }
public String Country { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public static class GlobalPosition
{
private static LatLongLocationProvider _provider;
private static CivicAddressLocationProvider _civicprovider;
private static bool _loadproviderthrowsexception = false;
private const uint DEFAULT_REPORT_INTERVAL = 0;
public static Location GetLocation()
{
Location l = new Location();
try
{
if (_loadproviderthrowsexception)
{
return null;
}
if (_provider == null)
{
_provider = new LatLongLocationProvider(DEFAULT_REPORT_INTERVAL);
_civicprovider = new CivicAddressLocationProvider(DEFAULT_REPORT_INTERVAL);
}
var y = _civicprovider.GetReport() as CivicAddressLocationReport;
l.City = y.City;
l.Country = y.CountryOrRegion;
var x = _provider.GetReport() as LatLongLocationReport;
l.Latitude = x.Latitude;
l.Longitude = x.Longitude;
return l;
}
catch (Exception ex)
{
return null;
}
}
}
Easy. The code speaks for itself – create a LocationProvider, query it to get the Latitude/Longitude. The rest is up to you.
Bonus Points
And if you’re a Powershell junkie, the following works too
[Reflection.Assembly]::LoadFile("<absolute location to dll>\Windows7.SensorAndLocation.dll")
$provider = new-object Windows7.Location.LatLongLocationProvider(0)
$position = $provider.GetReport()
$position.Latitude
$position.Longitude
1 Comment
Disclaimer: I’m new to Android, I could be doing this all wrong. If I am, please comment and correct me.
Programming for Android is an interesting experience, coming from a .NET/C# background. I’ve done plenty of Java before in Uni and disliked it, but that was before I started playing with WPF.
Like WPF, Android’s UI is created using XML based documents, but unlike WPF, there aren’t any nice WYSIWYG builders. And most of the time it seems you need a combination of code behind and XML to get what you want for the UI, which can get a bit frustrating.
The divider between the items in this particular app is more annoying than it is useful, so I wanted to get rid of it. I was initially looking for separator or border, but the name is divider, and it has two properties.To set the divider between the ListItems to "nothing", you have two options. The first is in Java,
ListView x = (ListView)findViewById(R.id.ListView01);
x.setDivider(null);
x.setDividerHeight(0);
The alternative is to set it in XML, but in this case its more of a hack than the above of turning it ‘off’.
<ListView
android:id="@+id/ListView01"
android:background="#ffffff"
android:dividerHeight="0px"
android:divider="#ffffff" />
Even though the dividerHeight is set to 0 (0px, 0dp, whatever, the results were the same), a black line was still visible. The best solution is to set the colour (the divider value) to the same as your background. Using a gradient or image as the background? Set it in the code behind.

Comments Off
Awhile ago I heard the saying “Microsoft is a platform company” (rather than lots and lots of products), one great example of that is Windows Home Server. WHS’s is built upon Windows Server 2003, so you can create apps and extend it much like any other Windows OS, but you can also extend the “Home Server Console” very easily using Visual Studio/.NET.
Requirements
Setting up your WHS Add-in
Create a .NET 2.0 Library Project (WHS does not ship with .NET 3.0/3.5, although they will work if installed), then you need to reference two libraries to build WHS add-ins which can be found on your WHS box. That’s right, there is no SDK download, the required libraries are found on your server.
From “C:\Program Files\Windows Home Server” copy HomeServerExt.dll and Microsoft.HomeServer.SDK.Interop.v1.dll from your server to your development machine, then reference both of them in your solution. This will give you the namespace Microsoft.HomeServer.SDK.Interop.v1. Alongside those, for the UI you’ll need to add references to System.Forms and System.Drawing.
WHS requires a particular assembly name structure, so right click on your project, change the Assembly name to “HomeServerConsoleTab.<yourprojectname>”, ie “HomeServerConsoleTab.WHSStats”
WHS Stats

WHS Stats uses Windows Management Interface (WMI) to return the names of several pieces of hardware on the server. This could be turned into a fully fledged hardware monitor, but I’m trying to keep it a very simply example that has more real world value than the veteran Hello World.
WHS Tab Add-ins (which appear in the main WHS Console screen versus Settings Add-in’s which appear after you click Settings from the Console) require two classes. In this case it’s WHSStats(.cs) which implements Microsoft.HomeServer.Extensibility.IConsoleTab and WHSStatsPanel(.cs), a UserControl, which contains the UI.
WHSStats.cs
using System;
using System.Text;
using Microsoft.HomeServer.Extensibility;
using Microsoft.HomeServer.SDK.Interop.v1;
using System.Drawing;
using System.Collections.Generic;
using System.Management;
namespace WHSTempAddin
{
public class WHSTempAddin : Microsoft.HomeServer.Extensibility.IConsoleTab
{
private IConsoleServices services;
private WHSTempAddinUI nPanel;
private WHSInfoClass whsInfo;
public WHSTempAddin(int width, int height, IConsoleServices consoleServices)
{
nPanel = new WHSTempAddinUI();
whsInfo = new WHSInfoClass();
this.services = consoleServices;
nPanel.Load += new EventHandler(nPanel_Load);
}
public Bitmap TabImage
{
get { return Properties.Resources.WHSTempAddinImg; }
}
public bool GetHelp()
{
throw new NotImplementedException();
}
public Guid SettingsGuid
{
get { return Guid.Empty; }
}
public System.Windows.Forms.Control TabControl
{
get { return nPanel; }
}
public string TabText
{
get { return "WHS Stats"; }
}
void nPanel_Load(object sender, EventArgs e)
{
nPanel.lstCPUDetails.DataSource = getCPUDetails();
nPanel.lstGPUDetails.DataSource = getGPUDetails();
nPanel.lstNetworkDetails.DataSource = getNetworkInterfaceDetails();
}
private List<String> getCPUDetails()
{
List<String> data = new List<string>();
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT *
from Win32_Processor");
foreach (ManagementObject adapterObject in searcher.Get())
{
data.Add(adapterObject["Name"].ToString());
data.Add("CPU Load: " + adapterObject["LoadPercentage"] + "%");
}
return data;
}
private List<String> getNetworkInterfaceDetails()
{
List<String> data = new List<string>();
ManagementObjectSearcher searcher = new ManagementObjectSearcher("select *
from Win32_PerfRawData_Tcpip_NetworkInterface");
foreach (ManagementObject adapterObject in searcher.Get())
{
UInt64 i = (UInt64)adapterObject["CurrentBandwidth"];
data.Add("Adapter name: " + adapterObject["Name"]);
data.Add("Current bandwidth: " + (i / 1000000) + "MB/s");
data.Add("KBytes In/sec: " +
((UInt64)adapterObject["BytesReceivedPersec"] / 100000) + "KB/s");
data.Add("KBytes Out/sec: " +
((UInt64)adapterObject["BytesSentPersec"] / 1000000) + "KB/s");
}
return data;
}
private List<String> getGPUDetails()
{
List<String> data = new List<string>();
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT *
from Win32_VideoController");
foreach (ManagementObject adapterObject in searcher.Get())
data.Add(adapterObject["Name"].ToString());
return data;
}
}
}
The constructor, TabText, SettingsGuid, TabImage and GetHelp the minimum methods to implement for a WHS Add-in. Key things to note, TabImage is a Resource added to the project, its recommended to be a 32×32 image (I used one slightly larger, that could explain why it is skewed off to one side); TabText is what appears on the Tab to select your add-in so don’t make it too long!
The rest of the code is hooking up the listboxes (below) to WMI queries about the hardware.
WHSStatsPanel.cs

Building and deploying the project
These particular instructions are mostly copied from MSDN
- Add New Project, select Setup and Deployment Projects, and then select Setup Project.
- In the File System editor (of the Setup Project), select the Application Folder node. Right-click the Application Folder, point to Add, then select Project Output.In the Add Project Output Group dialog, verify that Primary Output is highlighted. Click OK to add the project output and close the dialog box.
- In the File System editor, right-click Application Folder and then click Properties Window. In the properties window, in DefaultLocation, type [ProgramFilesFolder]\Windows Home Server.
- In the Solution Explorer, expand the Detected Dependencies. Right-click HomeServerExt.dll and Microsoft.HomeServer.SDK.Interop.v1.dll, then click Exclude.
- Now in Visual Studio 2008, you’ll need to set the .NET Framework under Launch Conditions to .NET 2.0.That is View –> Editor –> Launch Conditions. Regardless of whether you’ve selected .NET 2.0, 3.0, 3.5 or 3.5 SP1, this needs to be set. VS2008 defaults to .NET 3.5 in the launch conditions, which stops the installer from even running!
- This step is “sort of” optional. If you plan to Remote Desktop into your server and run the installer that way, you don’t need to do this…but if you plan to run the installer through the Windows Home Server console, you need to place the installer in \\Server\Software\Add-Ins. Even then, you need to insert the “WHSLogo” property (and set it to 1) in the MSI before WHS will pick it up.
To do this, you’ll need ORCA (it’s in the Windows SDK, see above for the links to that; Once you install the SDK, you’ll find the ORCA installer in C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\Orca.MSI). 
- With ORCA open, click File, click Open, browse to the location of the MSI file that contains your Add-in, and then click Open.
- In the Tables column, click Property.
- Right-click anywhere in the column area where the Property and Value columns are listed, and then click Add Row.
- In the Add Row dialog, type WHSLogo for the Property, click Value, and then type 1. Click OK to enter the property and to close the dialog.
- Click File, click Save, and then click Exit to close ORCA.

2 Comments
Scanners are perhaps becoming less and less used as we all move towards a paperless environment with digitals bills and digital photos, but a lot of "official" documentation must always be presented with the original physical copy. The wife and I have a huge collection of such documents which have been horribly archived in several filing cabinets – finding the right document is often a nightmare, let alone using any of the information in them. To combat this, I’ve started on a document manager which (aims to) make it a smooth process from scanning, archiving, searching, tagging, etc all in one.
I thought I’d share the scanning code section, because while scanning wasn’t the easiest thing to dig up, it still wasn’t half as daunting as I thought it would be. Further down you’ll also see code to do optical character recognition (OCR) – that is converting a scanned text document into usable text.
TWAIN or WIA?
In years past, TWAIN (commonly known as Technology Without An Interesting Name) was the way to perform scanning, so that was my starting point on my dig for scanning code. However, I came across a mention of Windows Image Acquisition in my scanners drivers.
"In comparison to TWAIN, WIA is said to be more flexible, because it is a standardized interface that doesn’t require a tight bundling of scanner software and driver (TWAIN-only scanners are often limited to functions that are enabled in its driver-software-bundle). Most recent scanners support WIA."
(source: Wikipedia)
Lift the image from a physical file into memory
To access WIA in .NET, you’ll need to add a reference to the COM library, "Microsoft Windows Image Acquisition Library v2.0" (wiaaut.dll).
using WIA;
….
const string wiaFormatJPEG = "{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}";
CommonDialogClass wiaDiag = new CommonDialogClass();
WIA.ImageFile wiaImage = null;
wiaImage = wiaDiag.ShowAcquireImage(
WiaDeviceType.UnspecifiedDeviceType,
WiaImageIntent.GrayscaleIntent,
WiaImageBias.MaximizeQuality,
wiaFormatJPEG, true, true, false);
This isn’t the only way to perform a WIA scan, but it is a very quick and easy way to do it. A standard dialog will appear asking you to select the scanner, and then another dialog will give you a few options (such a previewing, image quality, image mode, which source – by that I mean a document feeder or flatbed depending on your scanners capabilities).
Doing something with the scan
Once the document is scanned in you have to figure out what you want to do with it. If it was a photo for example, simply saving it to JPEG may be suffice, but if it is document you may want to perform OCR to extract the text first.
Saving to JPEG
Saving to JPEG is very easy, wiaImage.SaveFile("temp.jpg");
If you wanted to do more with the JPEG (resize, colour change, filtering, or simply just display in your app) but still wish to treat it as an image, you need to get the image data into either a System.Drawing.Image (WinForms) or System.Windows.Controls.Image (WPF).
WIA.Vector vector = wiaImage.FileData;
Image image = new Image();
image.Source = BitmapFrame.Create(new MemoryStream((byte[])vector.get_BinaryData()));
OCR
OCR is by no means a small task to undertake by yourself, but luckily Office (2003 and up) includes an API named Microsoft Office Document Imaging (MODI) you can program against to let Office process the image for you. Unfortunately, MODI isn’t installed by default with Office 2007 but it is easy enough to add by running the Office setup again, selecting "Add or Remove Features", and then selecting "Scanning, OCR and Indexing Service Filter"
All Office OCR operations must go through the COM library, "Microsoft Office Document Imaging 12.0 Type Library" (that’s for Office 2007) (MDIVWCTL.DLL) so add a reference to it.
MODI.Document mDoc = new MODI.Document();
mDoc.Create("temp.jpg");
mDoc.OCR(MODI.MiLANGUAGES.miLANG_SYSDEFAULT, true, true);
MODI.Image mImage = (MODI.Image)mDoc.Images[0];MessageBox.Show(mImage.Layout.Text);
The key thing to note is that MODI.Document only accept input files from an string representing the filepath, so you have to save the scanned document to disk (in either JPEG or TIFF) rather than reading from memory.
As far as I can tell, this doesn’t retain any layout data (ie, BlockA of text was situation at X,Y) so it doesn’t appear to be the perfect solution for my document manager but it is free (well, so long as you’ve got Office) so I’ll overlook that for now.
1 Comment
Many multi-user applications require a database, be it a web app (probably more often a web app!) or win forms. In single user applications, often it is beneficial if there is a database (in speed, complexity and robustness), but the problem is distributing the database server. I’ve had a few applications that come bundled with MySQL, and it just plain ole sucks.
Some of the reasons for using a database in your application include
- Faster than flat file storage such as XML
- Can have complex relationships
- Can have varying datatypes that don’t break an XML parser
- Can then later redeploy in another project, such as a website using SQL Server easier
One of the easier ways to distribute your winform/WPF application with a database is with Microsoft’s SQL Compact Edition (SQLCE). It has a fairly low footprint, is very fast, and is reasonably powerful despite the reduced operations (which allows it to be fast/low footprint/etc). Visual Studio’s deployment tools even allow you to check for the SQL CE prerequisite on the target machine before installing, and will download SQL CE if it isn’t found!
Adding SQL CE to your project
Providing SQL CE was installed during your Visual Studio install (default install settings), to get a SQL CE database in to your project, all you need to do is add a New Item > Local Database to your project. This will automagically add the references your project will need to access SQL CE databases (although you’ll still need Using System.Data.SqlServerCE;)


Double clicking on your new database in the Project Explorer will activate the Server Explorer, allowing you to add Tables to the database.

Using SQL CE
The way you access data is nearly identical to a normal SQL Server, except it all lives in the System.Data.SqlServerCE namespace, and usually has SqlCeClass rather than SqlClass. ie:
SqlCeConnection sqlCon = new SqlCeConnection(TestApp.Properties.Settings.Default.TestConnectionString);
SqlCeCommand sqlCom = new SqlCeCommand();
sqlCom.Connection = sqlCon;
sqlCom.CommandText = "SELECT * FROM TestTable";
SqlCeDataAdapter sqlDa = new SqlCeDataAdapter(sqlCom);
DataSet ds = new DataSet();
sqlCon.Open();
sqlDa.Fill(ds);
sqlCon.Close();
Using LINQ with SQL CE
In .NET 3.5, you can also use LINQ against SQL CE. Currently (VS2008) you have to use the SQLMetal tool from the Visual Studio CLI, then add the generated dbml file to your project (Add -> Existing Item)
SqlMetal SqlCeFileName.sdf /dbml:LinqClassName.dbml
In the new version of MahTweetsMediaHorn (correction, thanks Will), I’ll be using my own database rather than relying on Windows Media Players database. The LINQ to select all the albums (after generated the dbml via SqlMetal) is..
Music db = new Music(MediaHorn.Properties.Settings.Default.MusicConnectionString);
var album = from a in db.Album select a;
listBox2.ItemsSource = album;
Any and all of the usual tricks for LINQ apply to SQLCE – once you generate the dbml via SQLMetal, it really doesn’t care what is underneath. If you want to bind it properly to WPF with automagic updates for when the datasource updates, I strongly recommend looking into the very clever SyncLINQ by the equally clever Paul Stovell, which also supports Silverlight.
Deploying apps with SQL CE
As I mentioned, the Visual Studio “Publish” tool makes sure the target system has all the prerequisites before installing. SQL CE is automatically added to the list, but if you need to modify it, right click on your project, Properties, then down to the Publish tab, and the Prerequisites option will launch a new dialog.

Just make sure you distribute your application via Build -> Publish :)
Comments Off
Ever noticed how some applications tend to hang when you perform an operation? For example in MahTweets (my Twitter client), it used to have a looong pause every time it updated the Tweet list, and often the application would go black, almost to the ‘not responding’ stage. The GUI and application logic shared the same thread, meaning a massive change in GUI or lots of processing in the logic would stop the other.
The way around this is to use a separate thread for anything that requires a lot of processing, or that is bottled by another factor (Disk IO, or network speed, etc).
public delegate void MyDelegate();
// This method could be the method behind a button.clickpublic void InvokingMethod()
{
Thread myThread = new Thread(new ThreadStart(new MyDelegate(MyMethod)));
myThread.Start();
}
public void MyMethod()
{
//Code to execute on new thread goes here
}
There is one caveat, your new thread cannot access the GUI because this could cause some serious synchronisation issues. The way around this (in WPF at least!) is to use the Dispatcher.Invoke method.
public void GuiMethod()
{
if (!Dispatcher.CheckAccess())
{
Dispatcher.Invoke(DispatcherPriority.Normal, new voidDelegate(GuiMethod));
return;
}
//Code that accesses the GUI
}
If you need to pass parameters, one (quick) way is with an anonymous delegate like below, I’ll let you figure out the different ways to go about it though.
Thread t = new Thread(delegate() { MyMethod(MyParam); });
If you are having problems with concurrency and synchronisation, that’s outside the scope of this post…start looking at wikipedia’s article on threading, and go from there.
Comments Off

Requirements
Introduction
Growl is an application for Apple’s OS X which provides a standard "toasts" interface. Toasts are popups which fade after a short amount of time, and host a small amount of data (usually text, but images, sounds, etc aren’t unheard of).
Snarl is an application for Windows which is inspired by Growl which offers a similar implementation, currently coded in Visual Basic 6.
This article will implement several features of Snarl using Windows Communication Foundation (WCF) and Windows Presentation Foundation (WPF). Before we get started on the actual code, I’ll explain briefly what WCF is.
Continue Reading »
Comments Off
Introduction
When Vista’s codename was still Longhorn, there were grand plans which never eventuated such as WinFS, the global notifications system, and NGSCB, which would have all been rather significant features to the operating system. However, some of the more disappointing features that were dropped (that the general public would have noticed) were to do with the UI. Many elements of the system (such as Explorer) utilised WinFX (which became WPF) – thats right, Explorer was coded in .NET (which in itself is very interesting, such as why was it .NET? why is Vista’s Explorer not .NET? What was the realistic performance of it?)
If you compare the animations between Vista’s Explorer and those we’re able to see in the Longhorn preview video above (and this isn’t necessarily the best Longhorn preview video out there), it is easy to see that WPF is capable of some very cool thing, but again, it is disappointing to see that Microsoft isn’t “dog-fooding” such capabilities (except ironically in XAML tools such as Expression Blend and Design). This is emphasised when you look at some of the new applications coming out from Microsoft, such as those under the “Live” brand. Live Photo could have very well been Phodeo, which would have actually been a great application to demonstrate some “wow” with Vista.
Now that my rant is out of the way, this CodeSnippet will be about recreating the “Music” view from Explorer in the video above (1:22 to 1:25, so not much to really go on, but enough to get something pretty). This will be done using WPF, both its 2D and 3D elements, and API calls to Windows Media Player (so, if you don’t already use WMP, you’ll need to add one or two items to its library otherwise you wont’ see anything appear).
Download
Source
Exe
Requirements
The Interface
Because Blend is particularly good at prototyping interfaces, I started with piecing together roughly what I wanted it to look like. If you’ve never used Blend before, it is much like Visual Studio’s visual interface editor, but with a dark (by default) theme, and somewhat more powerful for creating custom interfaces. If you are unfamiliar with Expression Blend, the included help file is actually pretty useful – its what has taught me all I know about Blend!
For the time being, lets just use a boring 2D element for the large album art view. Later on we’ll replace this with a 3D object created using Zam3D, exported to XAML.
The Logic
Switching over to Visual Studio, open up the project. Since we’re working with WMP’s library, we need a reference to wmp.dll, its under COM under the Add Reference Dialog, Windows Media Player (make sure you select wmp.dll, not msdxm.dll). Any time we need to access WMP, don’t forget to add a “Using WMPLib;“
The general idea is to let WPF’s databinding power do as much work as possible, so we’ll need to arrange our data in a particular way. This isn’t entirely necessary to get the concept working, but in the long run its better practice and allows further flexibility in the program.

public class Albums
{
private List<String> TempAlbumList = new List<String>();
private ObservableCollection<Album> albumList;
public ObservableCollection<Album> AlbumList
{
get { return albumList; }
}
public Albums()
{
albumList = new ObservableCollection<Album>();
WindowsMediaPlayer wmp = new WindowsMediaPlayer();
IWMPPlaylist playlist = wmp.mediaCollection.getByAttribute("MediaType", "Audio");
for (int i = 0; i < playlist.count; i++)
{
IWMPMedia tempPl = playlist.get_Item(i);
String artist = tempPl.getItemInfo("AlbumArtist");
String title = tempPl.getItemInfo("Title");
String album = tempPl.getItemInfo("Album");
String sourceurl = tempPl.getItemInfo("SourceUrl");
String alba = album + artist;
if (!TempAlbumList.Contains(alba) && alba != "") {
try
{
if (artist == "")
artist = tempPl.getItemInfo("Artist");
albumList.Add(new Album(album, artist, Path.GetDirectoryName(sourceurl)));
TempAlbumList.Add(alba);
}
catch (Exception e)
{
// MessageBox.Show(e.Message + " on " + album +title + sourceurl);
}
}
for (int j = 0; j < albumList.Count; j++)
{
if (albumList[j].Title == album)
{
albumList[j].AddTrack(new Track(title, sourceurl));
break;
}
}
}
}
}
ObservableCollections are much like any other generic collections, except WPF laps these up like there is no tomorrow. ObservableCollections don’t reside in System.Collections.Generic, however, they are in System.Collections.ObjectModel, so don’t forget to add a using statement. The reason ObservableCollections is loved by WPF so much is because it implements INotifyCollectionChanged, which allows for dynamic binding to UI elements (such as our ListBoxes) so that when we add, remove or modify anything in our collection, the UI is updated automagically.
public class Album
{
private String title;
public String dir;
private String coverart;
private String artist;
private ObservableCollection<Track> trackList;
public Album(String title, String artist, string dir)
{
this.title = title;
this.dir = dir;
this.artist = artist;
this.coverart = GetArtwork();
trackList = new ObservableCollection<Track>();
}
public String Title
{
get { return title; }
set
{
title = value;
}
}
public String Artist
{
get { return artist; }
set
{
artist = value;
}
}
public String CoverArt
{
get { return coverart; }
set
{
coverart = value;
}
}
public void AddTrack(Track t)
{
trackList.Add(t);
}
public ObservableCollection<Track> TrackList
{
get { return trackList; }
}
private string GetArtwork()
{
string filename = null;
string[] filenames = Directory.GetFiles(this.dir, "AlbumArt*Large.jpg");
if (filenames.Length > 0)
filename = filenames[0];
else
{
FileInfo file = new FileInfo(Path.Combine(dir, "Folder.jpg"));
if (file.Exists)
{
filename = file.FullName;
}
}
return filename;
}
}
public class Track
{
public String Title;
public String path;
public Track(String title, String path)
{
this.Title = title;
this.path = path;
}
public override string ToString()
{
return Title;
}
}
If this was production code, I’d implement INotifyPropertyChanged on both the Track and Album classes, so that the UI would automatically update when changes were made to any of the properties.
Now we switch over to XAML (Window1.xaml) – this can be done via Blend or Visual Studio (or even Notepad), but I find VS a bit more powerful/useful.
<Window.Resources>
<local:Albums x:Key="Albums" />
<!-- this style makes the format gridlike rather than just a list -->
<Style x:Key="AlbumListStyle" TargetType="{x:Type ListBox}">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
</Style>
<!-- Change the artwork from text to actual images -->
<DataTemplate x:Key="AlbumListTemplate">
<StackPanel>
<Border Margin="10,10,10,10">
<Image Source="{Binding Path=CoverArt}" Width="50" Height="50"/>
</Border>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="TrackListTemplate">
<TextBlock Text="{Binding Path=Title}" />
</DataTemplate>
</Window.Resources>
By making local:Albums (note, to get the local prefix, add xmlns:local=”clr-namespace:MediaHorn” to the Window tag) available through the Albums key, we’re able to bind all our elements in XAML markup rather than in C#. In Albums constructor, it populates its albumList, because when the program launches, it immediately calls the class.
<ListBox
x:Name="lbAlbums"
Style="{StaticResource AlbumListStyle}"
ItemsSource="{Binding Source={StaticResource Albums}, Path=AlbumList}"
IsSynchronizedWithCurrentItem="True"
ItemTemplate="{DynamicResource AlbumListTemplate}"
SelectedIndex="0"
MouseDoubleClick="lbAlbums_MouseDoubleClick" />
<ListBox
x:Name="lbTracks"
DataContext="{Binding ElementName=lbAlbums, Path=Items}"
ItemsSource="{Binding Path=TrackList}"
IsSynchronizedWithCurrentItem="True"
MouseDoubleClick="lbTracks_MouseDoubleClick" />
<TextBlock
x:Name="tbTitle"
Text="{Binding Path=Title}"
DataContext="{Binding ElementName=lbAlbums, Path=Items}" />
<TextBlock
DataContext="{Binding ElementName=lbAlbums, Path=Items}"
x:Name="tbArtist"
Text="{Binding Path=Artist}"/>
<Image DataContext="{Binding ElementName=lbAlbums, Path=Items}"
Source="{Binding Path=CoverArt}" />
The Dimensions of Three
Zam3D is a pretty cool little application by Electric Rain. It won’t win awards for sheer power in high end, bump mapped, megatextures; but then again…neither will WPF. If you are into higher end 3D modelling and animation, Zam3D will import from 3DS files (3D Studio Max), and Electric Rain have plugins for other 3D applications.
They’ve released four training/introductory videos, which are a little lengthy but are nice at getting your way around their program.
I’m not going to go into lengths about creating the 3D Model we need using Zam3D because that’s an article in itself. All we want is a box primitive, resized, slightly skewed, and animated such that it does 1.25 revolutions, and then at a slower rate rotates -.25 revolutions. Switch into the advanced editor, hit ‘edit mesh’, select ‘faces selection’ mode, and select the two triangles that make up the front of the box, and apply a bitmap texture. Save, export to XAML, and we’re done with Zam3D.
For simplicity sake, I cut and paste the entirety of the exported XAML file to inside the grid (below the listboxes), then moved it around in Blend.
We’re almost done with our WPF 3D, but there are a few things we need to adjust. First, find the texture you applied, and rename it to “AlbumArtTextureMR2” (making sure you rename all instances of it), as well as deleting the contents of that material group. Next, any time we add our own material, you might notice it is upside down, so find the object (it will be a GeometryModel3D, the name will be something meaningful like Box01OR10GR12, and add to it:
<GeometryModel3D.Transform>
<Transform3DGroup>
<RotateTransform3D >
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Angle="180" Axis="0 0 1"/>
</RotateTransform3D.Rotation>
</RotateTransform3D>
<ScaleTransform3D ScaleX="-1" ScaleY="1" ScaleZ="1"/>
</Transform3DGroup>
</GeometryModel3D.Transform>
The placeholder we had for the 3D element had its source databound to the selected album. Unfortunately, MaterialGroup/ImageBrushes can’t be databound, so we’ll need to handle that in code.
public void onSelectAlbum(Object sender, EventArgs e)
{
if (lbAlbums.SelectedIndex > 0)
{
Album temp = ((Album)lbAlbums.SelectedItem);
if (temp.CoverArt != null)
{
BitmapImage img = new BitmapImage(new Uri(temp.CoverArt, UriKind.Relative));
ImageBrush iB = new ImageBrush(img);
MaterialGroup AlbumArtMaterial = (MaterialGroup)ZAM3DViewport3D.FindResource("AlbumArtTextureMR2");
AlbumArtMaterial.Children.Clear();
AlbumArtMaterial.Children.Add(new DiffuseMaterial(iB));
}
((Storyboard)ZAM3DViewport3D.FindResource("OnLoaded")).Begin(this);
}
}
The line with the storyboard starts our animation every time a new album is selected.
Finishing Touches
To make it a proper media player/viewer, we need to actually allow audio playback. Again we can make use of WMPLib.
public void lbAlbums_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (lbAlbums.SelectedItem != null)
{
Album tempAlb = (Album)lbAlbums.SelectedItem;
IWMPPlaylist tempPL = wmp.playlistCollection.newPlaylist(tempAlb.Title);
foreach(Track t in tempAlb.TrackList)
{
tempPL.appendItem(wmp.newMedia(t.path));
}
wmp.currentPlaylist = tempPL;
}
}
private void lbTracks_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (lbTracks.SelectedItem != null)
{
wmp.URL = ((Track)lbTracks.SelectedItem).path;
}
}
These two functions provide playback for albums and individual tracks respectively. In the first function, we need to create a temporary playlist so that we can play more than one item, which is achieved through simple iteration.
In the second function, we only need to set the URL of the current file to play back a single track.
private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
switch (e.Key)
{
case System.Windows.Input.Key.MediaStop:
wmp.controls.stop();
break;
case System.Windows.Input.Key.MediaNextTrack:
if (wmp.playState == WMPPlayState.wmppsPaused)
wmp.controls.play();
wmp.controls.next();
break;
case System.Windows.Input.Key.MediaPlayPause:
if (wmp.playState == WMPPlayState.wmppsPaused || wmp.playState == WMPPlayState.wmppsStopped)
wmp.controls.play();
else
wmp.controls.pause();
break;
case System.Windows.Input.Key.MediaPreviousTrack:
wmp.controls.previous();
break;
}
}
Since we don’t have any media controls, I added play/pause/skip/stop through ‘media keys’ on keyboards (or some laptops that have ’special’ function keys). This works for that, but the only problem is that it only works when the application has focus.
Conclusion
There are still bugs in this, but remember, it is more of a ‘proof of concept’ application that production ready. Several of the errors are derived from the WMP library which seems to keep a hold of albums that no longer exist, and thus while processing generate a few exceptions (so I’ve just chucked a few try/catch blocks around the offenders).
If you would like to further extend this, I’ve got a couple of ideas
- Add progress bars for how far you are through the track
- Add “+” buttons to build custom playlists
- Different views (ie, video, or list, grid, text, by song name, by artist etc)
- Sorting in different views (artist, a->z, most recently played, etc)
- Implement a way to add to the WMP Library, or create your own library structure that doesn’t rely on WMPLib (maybe just for ‘importing’ a library)
- Add “Now Playing” functionality so that it communicates with WLM
References
1 Comment