I have the hardware, but do I have the time to take Windows Phone ChordFactory and port it to iOS and Android?
I thought I might look at Xamarin Studio and see how easy it is…...
Primarily thoughts on Silverlight and other Microsoft UI Technologies, plus personal rants
I have the hardware, but do I have the time to take Windows Phone ChordFactory and port it to iOS and Android?
I thought I might look at Xamarin Studio and see how easy it is…...
I found out today how to do outer joins in LINQ and thought I’d save it as an Aide Memoire post.
Given a typical Foreign-Key relationship:
class Preference
{
public int Id { get; set; }
public string Description { get; set; }
}
class Person
{
public int Id { get; set; }
public string Forename { get; set; }
public string Surname { get; set; }
public int? PreferenceId { get; set; }
}
And this sample data:
var peopleList = new List<Person>();
peopleList.Add(new Person {Id = 77, Forename = "Fred", Surname = "Flintstone", PreferenceId = 2 });
peopleList.Add(new Person {Id = 154, Forename = "Barney", Surname = "Rubble", PreferenceId = 1 });
peopleList.Add(new Person {Id = 308, Forename = "Wilma", Surname = "Flintstone" });
peopleList.Add(new Person {Id = 462, Forename = "Betty", Surname = "Rubble", PreferenceId = 1 });
peopleList.Add(new Person {Id = 616, Forename = "Bam Bam", Surname = "Rubble", PreferenceId = 4 });
peopleList.Add(new Person {Id = 770, Forename = "Pebbles", Surname = "Flintstone" });
var preferenceList = new List<Preference>();
preferenceList.Add(new Preference {Id = 1, Description = "Coffee"});
preferenceList.Add(new Preference {Id = 2, Description = "Tea"});
preferenceList.Add(new Preference {Id = 3, Description = "Hot Chocolate"});
preferenceList.Add(new Preference {Id = 4, Description = "Fruit Juice"});
The obvious LINQ query:
var peopleWithPreferences = from p in peopleList
join pr in preferenceList
on p.PreferenceId equals pr.Id
select new {p.Forename, p.Surname, pr.Description};
Produces results that contain only the inner joined pairs of people and their beverage preference:
Forename Surname Description
Fred Flintstone Tea
Barney Rubble Coffee
Betty Rubble Coffee
Bam Bam Rubble Fruit Juice
In order to retrieve the full list of people with their beverage preference if they have one, the LINQ query becomes:
var peopleAnyPreferences = from p in peopleList
join pr in preferenceList
on p.PreferenceId equals pr.Id into joinedPreferences
from j in joinedPreferences.DefaultIfEmpty()
select new {p.Forename, p.Surname, pref = j != null ? j.Description : string.Empty};
Forename Surname Description
Fred Flintstone Tea
Barney Rubble Coffee
Wilma Flintstone
Betty Rubble Coffee
Bam Bam Rubble Fruit Juice
Pebbles Flintstone
The differences being the intermediate results joinedPreferences and its use with the DefaultIfEmpty extension, with a null check for the nullable column.
UPDATE: From a technique shown in this post by Jim Wooley:
A way of avoiding the need for intermediate results, using old-fashioned T-SQL style joins via a LINQ Where extension:
var betterPeopleAnyPreferences = from p in peopleList
from pr in preferenceList
.Where(x => p.PreferenceId == x.Id)
.DefaultIfEmpty()
select new {p.Forename, p.Surname, pref = pr != null ? pr.Description : string.Empty};
It seems that the handy ForEach method has been removed from the List of T class in the WinRT. According to Wes Haggard of the .NET Framework Bas Class Library (BCL) Team:
“List<T>.ForEach has been removed in Metro style apps. While the method seems simple it has a number of potential problems when the list gets mutated by the method passed to ForEach. Instead it is recommended that you simply use a foreach loop.”
Which is a shame, as I use this method quite a bit to invoke method group calls to do one-time iterations over Lists, like this:
keywordResults.ForEach(this.searchActivity.Keywords.Add);
public void ForEach(Action<T> action)
{
if (action == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
for (int index = 0; index < this._size; ++index)
action(this._items[index]);
}
public static void ForEach<T>(this IEnumerable<T> list, Action<T> action)
{
if (action == null)
{
throw new ArgumentNullException("action");
}
foreach (var t in list)
{
action(t);
}
}
Yeugh!!
Despite my good intentions, it’s been a year since I posted the second part of my set of posts on Building Silverlight Chord Factory (see Part 1 and Part 2). The third part – on the View in the Model-View-ViewModel (MVVM) triptych has been a bit delayed, mainly by work and other pressures, but also by my attention being diverted by the arrival of Windows Phone 7 (WP7).
My practice of exploring new development platforms and languages by converting my hobby project – the Openfeature Chord Factory – kicked in and the application got yet another transformation. Which worked out quite well as it illustrated some of the power and benefits of the MVVM pattern. Converting the Silverlight Chord Factory code to WP7 Silverlight code was pretty simple and the main area of change – the View – was nicely isolated from the remaining code allowing the XAML markup to be adapted to the WP7 Control Toolkit easily and the custom controls in the app to work with virtually no modifications for the new platform.
So now this belated post can be both a look at the original View and at the adaptions involved in moving the app to the WP7 platform.
Here are a few screenshots of the Silverlight application in a couple of incarnations, running in a browser:
Note the unfinished musical stave controls…
Screenshots of Silverlight ChordFactory application
And here are screenshots of the Wp7 application:
Screenshots of WP7 app
Leaving aside my relative lack of UI/UX design capability, you can see that basically the User Experience is the same for both versions of the ChordFactory app. And in some of the UI itself the styling is exactly the same – the keyboard keys for example.
In fact I was able to reuse large chunks of the Openfeature Silverlight music controls (Keyboard, Octave and PianoKey controls) that I developed for the browser app because they consist of generic, compatible XAML markup and C# code. The Views in either case are of course nothing more than the markup/styling with bindings to the appropriate data sources in the ViewModel. With the Model and ViewModel classes being completely platform independent, they needed no redevelopment at all.
So I was able to get the WP7 ChordFactory app up and running in not much more than an easy afternoon of working on it. The majority of the work required lay in adding XNA code to play piano note samples added to the app so that the user can hear the selected chord or scale. Something I couldn’t do as easily with the browser version and hadn’t got around to implementing with MediaElements. Registering with the App Hub and submitting the app took a few trips back and forth to cross all the ‘Ts’ and dot all the ‘Is’, but the app is now live here: