Devlink Mobile Smackdown–Code and Retrospective

By benvonhandorf at August 21, 2011 18:19
Filed Under: Android, General

tl,dr;

The code for this is located here, in a BitBucket repository.

What was this?

I was part of the Devlink Mobile Smackdown, organized by Jeff Blankenburg of Microsoft.  The goal of the talk is to give the audience a brief taste of developing for the 3 big mobile platforms… iOS, Windows Phone 7 and Android by writing a very simple twitter stalker application in 15 minutes (with a hard stop).  I was fortunate to have Jeff ask me to represent Android. 

How did it go?

At the end of my 15 minutes, I had forgotten one line of code, but was basically feature complete. 

The other victims… er… participants, had significantly better looking applications by the end of their 15 minutes.  The base UI for an Android app looks HORRIBLE, so yes, this also looks horrible. I didn’t have time to do a single image, styling optimization or anything of the sort.

Java and Android are not the fastest development environments.  Perhaps if I was a little more familiar with the UI designer, I could have avoided some XML editing, but even still there is a lot of ceremony in the code. 

So Android is a bad platform to develop for?

That being said, this demo doesn’t really do anything to show off the true power of the Android platform.  Android’s power lies in the way applications inter-operate.  If you have a mobile app and a website, you can have the mobile app TAKE OVER when the user tries to go to your website.  Yes, really.  If you want to do a lot of work in the background, you can.  If you want to build an interaction story with other applications, or use installed libraries or write to the home screen (widgets) or build animated wallpapers… all these things are possible.

This does lead to a lot of the problems with Android, too… you can install an app and find your battery dead 3 hours later if it is badly behaved.  It’s a power user platform.  (and with great power comes… free cookies?  Something like that.)

THAT being said, it’s also the only platform right now on a lot of low end end prepaid carriers.  So the audience is HUGE for a certain class of application.  All the platforms have things to recommend them.  iOS has the UX so standardized, anyone can use it.  WP7 has a beautiful development story and a strong style (which you will either love or hate).  Android believes the phone is yours and you can do anything you want to with it.  There are things you can do on Android that will NEVER be possible on the other platforms.

Was it fun?

The Mobile Smackdown was a blast.  Live coding in front of a large group with no snippets and no “Julia Child” bail out option is quite a rush.  I had practiced probably 15 or 20 times, several times in front of friends, so I felt fairly prepared but even still I was running 20-35 seconds behind by the end of 15 minutes. 

I look forward to seeing where all 3 platforms wind up in a few years. Several of the things I heard Jeff talk about as new in Mango from from Android.  Several of the new iOS 5 features are straight out of the Android playbook (notifications, for example).  Android is STARTING to understand that they need a better UX out of the gate… the Action Bar replacing the hard menu button is a step in the right direction.  I’m not usually a raging free-market kind of guy, but the competition is driving all 3 platforms forward.

Thanks to Jeff for the opportunity to represent my current mobile platform of choice. 

Feedback?

If you saw the smackdown and have any feedback, please hit me up on twitter (@benvonhandorf) or my first name @benvonhandorf.com.  I’m always looking to improve my speaking abilities, and you only learn by hearing what you did wrong.

If there’s some demand for it, I may do a Honeycomb version of this same application.  It would be a great fit, but it’s nothing I could do in 15 minutes (if for no other reason than the emulator for Honeycomb is tooooo sloooooow).

Ammended (8/27/2011):

Find @samidip’s writeup of his experience doing Windows Phone 7 here.

Find @iamthegeek’s code for iOS here.

Android UI Helper Eclipse Plugin

By benvonhandorf at August 21, 2011 17:49
Filed Under: Android

What is this?

The single most common task I’ve run into as an Android developer is creating and wiring up fields.  Every time you create a new activity, you change your layout.  Every time you change your layout… define the new fields, use findViewById to wire them up to private properties in your activity so that you can actually do something.  It’s not hard, but it is lots of typing and it’s CEREMONY… it’s something you can only really get wrong.

So what did you do about it?

As part of preparing for the Devlink Mobile Smackdown presentation, I decided to try to optimize this workflow a bit.  I wrote an Eclipse plugin that would look at your activitiy’s onCreate and parse any layout files loaded (with setContentView) and create and wire up the private fields.  (I wound up not using it for the Smackdown, but I am using it daily for real work).

What is the workflow?

I’ve created a new Android project, which gets the basic “Hello World” functionality of an almost blank layout.  I went ahead and gave an id to the TextView and added a button.

image

Now, simply go to your activity in the project and right click.  Look for the Android UI Util sub menu and select “Build Private Member Variables from XML”.

image

That will add the private variables, but not the imports, so this screenshot shows errors:

image

After this, it’s a simple matter of having Eclipse update the imports (CTRL-SHIFT-O in the default key bindings).  Now just call findChildren during your onCreate(…).

But what about when you change your layout again?

No worries.  Just run the plugin again.  It won’t destroy any items you’ve already added.

How do I get this?

It should be pretty simple, although I’ll admit I’ve only tested this on a few machines.

  1. Go to the BitBucket repository and download the latest version of the plugin here
  2. Drop it into your eclipse plugin directory.  This is usually <ECLIPSE_ROOT>/plugins.
  3. Restart Eclipse

This Sucks!

Don’t like it?  File a bug on the BitBucket project.  Make it better yourself by pulling down the source!  This was a dead simple attempt that I made to make my own life better.  Hopefully it makes yours better, too!

OpenSpace Tweets and Conftron

By benvonhandorf at June 02, 2011 15:16
Filed Under: Android, General

tl;dr

If you tweet about open spaces in a specific fashion, it’s possible for automated systems to pick them up and for them to show up in conference scheduling applications.  Use the format:

#codestock #OpenSpace Sat 12:30 Write linkedin recommendations for coworkers & friends!

The Goal

I’ve always wanted to attend more open spaces, but at many conferences the open spaces are outside the “main flow”, either physically or temporally.  IMHO, discoverability is the big issue here.

A Proposal

Twitter is a natural solution for this.  Simply tweeting about your open space with the conference hashtag improves the visibility massively… but with a LITTLE extra formatting, we can even make the tweet machine readable and then it can start showing up in people’s conference scheduling applications, like my own Conftron for Android.

My parser looks for the hashtag “#OpenSpace” as well as the conference hashtag, e.g. “#CodeStock”.  It then tries to figure out what time you’re meeting.  If you simply provide a time in military time, it will put it on today if the time is in the future or tomorrow if the time has already passed.  You can also provide the normal 3 letter day abbreviations to schedule it on a future day (Sat).  As a tiny shortcut, you can also use a + to move the date forward a day, or two to move it forward two days, etc... so “+” == tomorrow.

An Example

Alan Barber was kind enough to re-tweet his open space request in the correct format for testing:

alanbarber: #codestock #OpenSpace Sat 12:30 Write linkedin recommendations for coworkers & friends!

This worked perfectly and will now show up in the Open Space feed in Conftron the next time you sync (assuming you have the latest version).

Tooling

I’m going to add a feature to Conftron to help compose these tweets properly, with a date picker and other little niceties, but I’m hoping that this blog post will be enough to get people started.  If there’s enough interest, I’ll gladly post my feed parser somewhere for general use.  It’s making use of the unauthenticated Twitter search API, so you don’t even need any messy OAuth stuff yet… but I’m likely going to revisit this.

Feedback?

Like this idea?  Hate it?  You can find me though the normal ways or send Conftron specific feedback to @conftron on Twitter.  I’d love to either see this become a standard or have someone suggest something better to supplant it!

Sql Server CE assembly version conflict

By benvonhandorf at May 25, 2011 21:03
Filed Under:

First, thanks to Matt for figuring out where to look for the solution to this issue.

In working on the back end services for my Android application, I moved my Entity Framework model from one assembly to another.  After that and some other refactorings, I went to run and was greeted with this error:

[A]System.Data.SqlServerCe.SqlCeConnection cannot be cast to [B]System.Data.SqlServerCe.SqlCeConnection. Type A originates from 'System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' in the context 'Default' at location 'C:\Windows\assembly\GAC_MSIL\System.Data.SqlServerCe\4.0.0.0__89845dcd8080cc91\System.Data.SqlServerCe.dll'. Type B originates from 'System.Data.SqlServerCe, Version=3.5.1.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' in the context 'Default' at location 'C:\Windows\assembly\GAC_MSIL\System.Data.SqlServerCe\3.5.1.0__89845dcd8080cc91\System.Data.SqlServerCe.dll'.

After spending far too much time with the fusion logger and triple checking all my references, Matt made the brilliant suggestion to take a look in the .edmx XML to see if it had any references to the provider.  Lo and behold:

<Schema Namespace="ConferenceDataModel.Store" Alias="Self" Provider="System.Data.SqlServerCe.3.5" ProviderManifestToken="3.5" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">

Changing the 3.5s to 4.0, saving, rebuilding and running resolved the issue.

Android: Problem launching main activity–Permission Denial

By benvonhandorf at May 15, 2011 07:16
Filed Under: Android

Hoping to save someone else (or my future self) a few minutes.

So I’m working on an Android app and I did a minor refactor and reduced the number of activities (screens) in my application and renamed another activity to the name of one of the removed ones.  After recompiling, my app would not start.  “adb logcat” showed the following:

I/ActivityManager(  129): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.benvonhandorf.conftron/.ConferenceListActivity }
W/ActivityManager(  129): Permission Denial: starting Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.benvonhandorf.conftron/.ConferenceListActivity } from null (pid=-1, uid=-1) requires null

After some investigation, it turns out that I had forgotten to remove the extra <activity> element from the AndroidManifest.xml file, so the renamed activity was listed twice, resulting in this fairly cryptic error.  Removing the extra activity registration solved the issue. 

I believe what happened is that Android ignored the earlier registration (which contained the intent filter for MAIN and LAUNCHER) and therefore couldn’t find a way to launch the application.

Rooting your Barnes and Noble Nook Color–Part One–The SD Card is your Friend

By benvonhandorf at May 14, 2011 18:09
Filed Under: Hardware, Android

What’s the Goal?

Our goal for this post is to get an alternative OS booted up on your beautiful Nook Color without damaging anything.  I’m going to select one of the better-known and more mature ROMs available to make our lives simpler, but if you want to experiment, there are a lot of options available.

Before we start

On the off chance that you haven’t even booted your Nook Color (NC) with the default OS yet, do so now.  You need to go ahead and let it go through device registration, creating a BN.com account, etc.  Not doing this MIGHT not cause any issues… or it might brick your device.  I recommend finishing the normal path and playing around with the NC for a bit.  It’s a really nice device straight out of the box.  Maybe you’ll like it enough like that.

Stuff you’ll need

If you’re going to go forward, you’ll need:

  • Your NC, fully charged and preferably plugged into the wall though the charger.  It would really suck to lose your device during the boot for not having it charged.  (This isn’t much of a risk with this method, but with the other methods this could turn it into a very poor boat anchor)
  • A micro SD card of at least 2 gigs that will be totally erased.  This will be where we put the new OS we’re going to create.  You will lose everything on this card.
    Note that speed counts here.  There is a definite difference between say a class 6 and a class 10 card.  If you’re planning to run like this for a while, do a little research and pick out a good one. 
  • A computer where you can write your micro SD card.  I think every computer, netbook and toaster for the past 8 years or so has shipped with an SD card slot, but I figured the need to call it out.

My Kingdom for a ROM

First, we need an actual OS to put on the card.  I recommend CyanogenMod 7 for this foray.  It’s very mature and ported to a lot of devices.  It actually feels a lot more mature than some smart phone OSes I’ve paid a lot of money for in the past.

Credit where Credit is Due

The method I’m describing here was most recently improved by the XDA Forums user “verygreen” in this thread.  His instructions are probably superior to mine, but I’m trying to give friends a single set of instructions rather than sending them all around various forums.

To the Internet!

Time to start downloading the software bits we’re going to need.

Go to the CyanogenMod page for the Nook Color and download the latest Stable Rom.  To get full access to the Market and other Google applications, you should also go to the table at the bottom of this page and download the most recent version of Google Apps for the version of CyanogenMod that you are installing (7).  Set these files to one side.

Now we need “verygreen”’s SD card installer.  At the time of writing, this is a link to the appropriate file, but that may change.  I will attempt to keep this blog post up to date, but the thread linked above will almost certainly be more correct.  Note that this is a .gz file.  If you’re running windows, go forth and download the wondrous 7-Zip and use it to extract the .img file.  If you’re running Linux, you already know what a .gz file is.  If you’re on a Mac, just click on it.  I’m sure the Mac knows to do the right thing.

image

If you’re running Windows, you will also need a utility to burn the SD Card since Microsoft doesn’t trust us to just stream bytes to devices.  The one that seems to be most recommended is Win32DiskImager.  I find the interface for this little bit of kit very confusing, but it seems to work well for most people.  If not, there are other tools available.

Oooh, BURN

Windows

Now, we want to burn the SD card installer from verygreen onto the card.  If you’re using Win32DiskImager, the interface should look something like this:

image

Double and triple check the device dropdown before clicking “Write”.  If you pick the wrong one, you’ll blow away something other than your SD card.  Not what you want.

After the write is complete, eject the SD card from your computer and re-insert it.  You should now have a partition called “BOOT” show up in your windows explorer for your SD card.  Copy the two files we downloaded earlier, the CyanogenMod 7 file and the Google Apps image, onto this partition.

Patience, Grasshopper

Now comes the exciting part.  Eject your SD card from your machine and, if necessary, extract the Micro SD card from the adapter.  Insert it into the Nook Color’s Micro SD card slot (it’s down in the little lanyard notch, accessible from the back).  Now, turn off your Nook Color by holding down the power button (you’ll be prompted).  After it’s off and with the card in place, turn it back on.

This boot will take a little while… it’s actually extracting the disk images you provided and building a full Android system.  It took approximately 20 minutes for me.  I recommend leaving your Nook on mains power while this runs.

At the end of the process, your Nook should reboot.  If everything has gone to plan, you will now be booted into CyanogenMod

Rooting your Barnes and Noble Nook Color–Part Zero

By benvonhandorf at May 14, 2011 01:53
Filed Under: Hardware, Android

Why

Recently several people have seen my rooted Nook Color around and about and been interested.  I’ve send various and sundry forum links to some of them and a few of them have gone through the process of rooting the Nook or trying alternative operating systems to see the power of this incredible device.

After sending out similar forum links several times, I decided to accumulate the instructions into a series of posts in the hopes of making this easier for the adventurous souls willing to go through with it.

But

As with any process called “rooting”, this is not for the faint of heart.  If you’re not comfortable with strange forums, obscure instructions and possibly difficult recovery processes, here there be dragons.

Recommended Alternatives

If you don’t want to risk your beautiful Nook Color, I have some recommendations for you:

  1. Buy an iPad.  Apple has a much better, more curated experience for people who fear the unknown and don’t like risk.  You pay for that experience, both in dollars and in your ability to do whatever you want.  For 99% of people, that trade off is a no-brainer compared to a rooted nook.
  2. Buy a real Android tablet.  The Motorola Xoom is an amazing bit of kit.  Acer has a really impressive tablet out.  Samsung’s line of Android tablets come out very soon.  If you like the Android platform but you fear the command line, this is a great alternative.
  3. The Nook Color is now a beginner tablet.  With the officially supported apps, it’s starting to become quite capable.  It can do so much more with the additional work, but again, for 99% of people, the default experience is worth it.

Still Here?

If you’re through the alternatives and none of them appeals to you, then let’s discuss your options:

  1. Boot off the SD card.  This is a non-destructive process that allows you to try out different operating systems and see what suits you.  To revert to the default experience, simply take out the card and reboot.  Highly recommended at least until you find an OS that you like more than the default  This is the easiest and least-risky option.
  2. Root the Nook operating system.  This leaves the OS mostly intact, but adds in the missing bits of Android and Marketplace access, which can allow you to get some apps that B&N haven’t approved.  This is semi-destructive, but still a nice compromise.  This is a little harder than the SD card boot and slightly more risky.
  3. Flash your own OS onto the Nook. This is the highest risk, but most performance and convenience.  This nukes the B&N OS right off the device and replaces it with a ROM that has been specially formulated to work on the Nook.

My next post will discuss the SD card option.  We’ll take a specific ROM and walk you through the process of burning it to the SD card and playing around with your new hardware.  After that, I’ll discuss the other options and some gotchas and neat tricks.

Attributions

Almost nothing in this series of blog posts will be my own work.  I’m simply curating data from a lot of great sources.  The two big ones you should familiarize yourself with are:

The NookColor portal at nookdevs.com.  Anything I say can either be found or at

The XDA Forums for the Nook.  This is where the wizards live.  They can make almost any phone dance and do things that it was never intended to do.  Just be sure to search before asking a question… Wizards are subtle and quick to anger.

WPF Ink Friendly Editable Text Control

By benvonhandorf at March 16, 2010 05:34
Filed Under: WPF, .NET

I’m rescuing some posts from my old blog. 

This topic was suggested by Mike Wood.  It’s a control I’m putting together for my WPF project for fun.  I really like the Tablet PC idea and enjoy using the pen as an input device where it makes sense, so I wanted a label that you could click on and bring up an ink editing panel.  So here we have a list of strings:

image 

Click on one of them and get out the pen!

image

Through the magic of the control and WPF’s 2 way data binding, your listing is now updated!

image

The control itself is reasonably straightforward… it’s pretty much a label with a popup containing an InkCanvas and a few buttons.  There are still a few quirks I’m trying to work though (e.g. the right way to clear the list of strokes out of the InkAnalyzer, getting automatic recognition working so that you don’t have to click OK), but on the whole it’s functional.

One strange/irritating thing is that even though the ink stuff is more or less a 1st class control now in WPF, you still need to include some obscure references to get handwriting recognition.  You have to go to C:\Program Files\Reference Assemblies\Microsoft\Tablet PC\v1.7\ and add all the files there to your solution so that you can use classes like the InkAnalyzer.

 You can find this sample code here.  Enjoy!

Managed C++ and Unmanaged Libraries

By benvonhandorf at March 16, 2010 05:30
Filed Under: .NET

I’m rescuing some posts from my old blog and this seemed like something I would want to know again at some point, so I’m starting with this one:

This started with an offhand remark on the Polymorphic Podcast that there was an accelerated feed available.  Listening to it, I realized that a lot of technical podcasts could be easily digested at, say, 120-130% of normal speed.  For some, it’s a lot more tolerable for me to listen to them this way.

This led to the Dream Application.  It would run on a web server and refactor a requested RSS feed to point back to itself.  When a feed reader went to download an mp3, the application would download the mp3 from the actual source, speed it up and stream it down to the reader.  After about 2 weeks of light work on that application, someone pointed me to PodShifter, which is exactly what I was building.  My only problem with their solution, and I do not think it is their implementation, is that it is slow.  The feed reader requests the mp3, it gets 404ed and then, maybe 15 minutes later, the mp3 is actually available to download.

So I’ve refactored my approach… what I want now is a service that watches the podcast directories I want to accelerate.  When it sees a new mp3 stored there, it should pick it up, accelerate it and store it back in the same filename so that when I plug my Zune in, the Zune software will pick up the accelerated version.

Bricks in the Wall

There are really 3 bits to this solution and, luckily, there are libraries available for each of them.  I don’t have to learn all about audio formats to do this!  (Or DO I?)

  1. Decoding an existing mp3.  Libmpg123 takes care of this.  It’s a fairly straightforward C style interface which suits itself to PInvoke fairly well.
  2. Accelerating the data (without pitch shifting it).  SoundTouch seems to be the default solution to this.  Unfortunately, this is implemented as a C++ Class rather than a C library.  There’s no real way to PInvoke to a C++ class… unless you want to do all the work of normalizing the actual function names out of the DLL and passing the “this” pointer around.  Not Fun.
  3. Encoding the decoded data.  LAME is the standard “free” solution to this problem, and there is a liblame implementation that is also fairly PInvoke friendly.

Since SoundTouch threw a wrench into my initial plan of doing C# and PInvoke, I decided to reboot and start writing a managed C++ wrapper class for each of the libraries and using C# to wire the wrappers together.  Each interface would basically take an input stream and an output stream.

Managing the unmanageable

The only real HARD part of all this was re-learning C++ and figuring out how C++ works in a managed environment.  There are 2 things I learned that were really key:

  1. To work with framework objects, you wind up using ^ in the declaration… like this:
    System::IO::Stream ^inputStreamLeft 

    This tells C++ that this is a managed, garbage collected class and you get all the benefits of doing that, just like you would in C#.  If you need to create a new managed class, you use gcnew rather than new.  At that point, your work is done… no need to call delete on such an item.
  2. Creating unmanaged pointers is more interesting.  Obviously, the C and C++ libraries I am calling don’t know anything about a System.Byte pointer.  More interestingly, managed objects can be moved around in memory at the whim of the runtime… which doesn’t work out so well for C libraries that just want some memory they can dump stuff into.  The solution is to pin the object in memory with pin_ptr.  For example, to create an array of bytes that I can get to with managed and unmanaged code, I do the following:
        array<System::Byte>    ^ inputBufferLeftManaged ; //Managed byte buffer
        inputBufferLeftManaged = gcnew array<System::Byte>(327680) ; //Allocate the byte buffer
        cli::pin_ptr<unsigned char> inputBufferLeft = &inputBufferLeftManaged[0] ; //Get an unmanaged pointer to the memory.  This pins the object in memory so it can’t move 

    You can then cast the pinned pointer to other kinds of pointers, and pass it into the relevant functions.
    NOTE: This is all recent learnings, so I suspect I have a memory leak in here.  I’ll update this if I learn this is the case and how to deal with it.

Whatever floats your boat

After getting things wired up, I was getting nothing but garbage out of the sound modification library.  If I just wired the decoder and encoder together, I got a reasonable mp3, but running it through the tempo adjustment meant that I got nothing but static.  Some investigation later revealed that recompiling that library to deal with float samples rather than the 16-bit unsigned samples I had been using resolved this issue… so I changed the other libraries to work with float samples instead so I have a consistent data stream throughout the process.

Don’t Cross the Streams

A side effect of the change to floats is that the lame encoding library doesn’t support a single interleaved buffer when dealing with floats… instead I have to pass in a buffer for the left channel and a buffer for the right channel.  I wound up writing a loop after the audio modification stem to pull data off the stream and drop it onto a left or right stream, de-interleaving the data myself.  I wound up doing this in the C# code for simplicity… less chance of overrunning a buffer off into infinity.

Wall of Silence

At the moment, I’ve hit something of a wall with this project.  Everything seems to work OK, but ever since switching to float audio data, I’ve had nothing but silence from the encoded mp3.  It appears there’s real data going INTO it, but nothing but silence coming out.  After several hours of debugging, I’ve set it to the side for the time being.  Hopefully I’ll be back to this before too long, but there’s so much out there to do I’ll probably just live with the quirks of PodShifter (which IS really good).

Eliminating magic strings when using INotifyPropertyChanged

By benvonhandorf at January 22, 2010 04:13
Filed Under: .NET, Silverlight, WPF

Like a lot of others, I'm learning Silverlight, WPF and all the other facinating new technologies coming out of Microsoft (and elsewhere) these days.  Most of this stuff is incredible, but occasionally you'll run into something that has a bit of a code smell about it.  One of those is the INotifyPropertyChange interface in WPF and Silverlight.

In order to make data binding work in these two technologies, entities that have their data bound to WPF or Silverlight controls need to implement INotifyPropertyChanged in order to ensure that the controls are updated when the data in the entity changes.  All well and good, but let's take a look at the interface:

    // Summary:
    //     Notifies clients that a property value has changed.
    public interface INotifyPropertyChanged
    {
        // Summary:
        //     Occurs when a property value changes.
        event PropertyChangedEventHandler PropertyChanged;
    }

Looks fine.  And the PropertyChangedEventHandler delegate looks pretty standard... a sender and then a PropertyChangedEventArgs class that descends from EventArgs.  But how do you indicate which property changed?

        public PropertyChangedEventArgs(string propertyName);

A string matching the name of the property, passed into the constructor of the PropertyChangedEventArgs.  So most people I've seen wind up implementing it everywhere something like this:

        public string MyStringProperty
        {
            get
            {
                return _myStringProperty;
            }
            private set
            {
                _myStringProperty = value;
                if( PropertyChanged != null )
                    PropertyChanged( this, new PropertyChangedEventArgs("MyStringProperty"));
            }
        }

If having a hardcoded string inside a property setter that has to match the name of the property doesn't constitute a "Code Smell" then I'm not sure I understand the concept.

Now, most people abstract the PropertyChanged null check down into a base class on their ViewModel objects in keeping with DRY.

            private set
            {
                _myStringProperty = value;
                RaisePropertyChanged("MyStringProperty");
            }

 

Better, but the hard coded string is still there.  What can we do about that?

Expression Trees to the rescue. 

If you haven't dug into this technology yet, it's quite facinating.  You build up a tree of expressions that does not have to be executed.  It's a structure describing the code without actually executing it.  This is how deferred execution in LINQ works and how LINQ to SQL is able to take your Where(...) and Select(...) calls and turn them into SQL statements.

In my base ViewModel class, I declare a delegate that is simply anything that returns an object:

        public delegate object PropertyAccess( ) ;

And now I re-implement my RaisePropertyChanged method to take an expression which contains a PropertyAccess delegate:

        protected void RaisePropertyChanged(Expression<PropertyAccess> propertyExpression)
        {
            MemberExpression getMemberExpression = propertyExpression.Body as MemberExpression;

            if (getMemberExpression != null 
                && getMemberExpression.Member.MemberType == System.Reflection.MemberTypes.Property)
            {
                RaisePropertyChanged(getMemberExpression.Member.Name);
            }

        }

OK... but how do you call it?

            public string TestProperty
            {
                get 
                {
                    return _testProperty; 
                }
                set
                {
                    _testProperty = value;
                    RaisePropertyChanged(() => this.TestProperty);
                }
            }

But Ben!  You're accessing TestProperty in the Setter!  If there was real logic in there (for example, lazy loading some data), you might do all kinds of bad things!

No.  The () => this.TextProperty call is never evaluated... it is only used to build an Expression tree which is then examined by the RaisePropertyChanged method, which extracts the appropriate property name.

The best part, in my mind?  A magic string change becomes a compile time error.  No more broken unit tests... in fact, probably no need for a unit test on every property set to ensure that the event is loaded.

I hope this was useful to you... I'll be back soon with more of my learnings.  If you've got something you're curious about or a comment on this or any of my posts, please drop me a line using the comment feature!