ReactiveXaml: A compelling combination of MVVM and Reactive Extensions (Rx)
I’ve been hacking on a library in my spare time (Hah!) that I really think has the potential to change how folks write Silverlight/WPF applications and I’m really excited about it. After testing concepts and refining the interface using several different sample apps, I believe I’m confident enough in the concept that it needs to be seen by more people. I also have a newfound respect for the folks who worked on the BCL and the PMs in DevDiv – writing a library to get something done is easy; writing a library that gets stuff done and is elegant and straightforward is decidedly not.
This library is an exploration I’ve been working on for several weeks on combining WPF Model-View-ViewModel paradigm with the Reactive Extensions for .NET (Rx). Combining these two make managing concurrency as well as expressing complicated interactions between objects possible in a declarative, functional way. Put simply, if you’ve ever had to chain events / callbacks together and declare state ints/booleans to keep track of what’s going on, Reactive Extensions provides a sane alternative.
I’m going to be posting quite a bit more about this library as well as a sample application, but for now, check out the code to ReactiveXaml on Github.
What’s in this library
ReactiveCommand – an implementation of ICommand that is also a Subject whose OnNext is raised when Execute is executed. Its CanExecute can also be defined by an IObservable<bool> which means the UI will instantly update instead of implementations which rely on RequerySuggested.
ReactiveAsyncCommand – a derivative of ReactiveCommand that encapsulates the common pattern of “Fire asynchronous command, then marshal result back onto dispatcher thread”. Allows you to set a maximum level of concurrency as well (i.e. “I only want 3 inflight requests” – when the maximum is reached, CanExecute returns false).
ReactiveObject – a ViewModel object based on Josh Smith’s implementation, that also implements IObservable as a way to notify property changes. It also allows a straightforward way to observe the changes of a single property.
ReactiveValidatedObject – a derivative of ReactiveObject that is validated via DataAnnotations by implementing IDataErrorInfo, so properties can be annotated with their restrictions and the UI will automatically reflect the errors.
ObservableAsPropertyHelper – a class that easily lets you convert an IObservable<T> into a property that stores its latest value, as well as fires NotifyPropertyChanged when the property changes. This is really useful for combining existing properties together and replacing IValueConverters, since your ViewModels will also be IObservables.
StopwatchTestScheduler – this class allows you to enforce time limits on items scheduled on other threads. The main use for this is in unit tests, as well as being able to say things in Debug mode like, “If any item runs in the Dispatcher scheduler for longer than 400ms that would’ve made the UI unresponsive, crash the application”.
Blend SDK Integration
AsyncCommandVisualStateBehavior – this behavior will watch a ReactiveAsyncCommand and transition its target to different states based on the command’s status – for example, displaying a Spinner while a command is running.
FollowObservableStateBehavior – this behavior will use the output of an IObservable<string> and call VisualStateManager.GoToState on its target; using Observable.Merge makes it fairly straightforward to build a state machine based on the changes in the ViewModel.
ObservableTrigger – this trigger will fire when an IObservable calls OnNext and can be tied to any arbitrary Expression Action.
Other stuff that’s useful
MemoizingMRUCache – this class is non-threadsafe most recently used cache, and can be used to cache the results of expensive lookups. You provide thefunction to use to look up values that aren’t known, then it will save the results. It also allows a “destructor” to be run when an item is released from the cache, so you can use this to manage an on-disk file cache as well (where the “Get” function downloads a file, then the “Release” function deletes it).
QueuedAsyncMRUCache – this class is by far the most complicated in this library, its goals are similar to MemoizingMRUCache, but instead of returning the result immediately, it will schedule a Task to run in the background and return an IObservable representing the result (a Future). Once the Future completes, its result is cached so subsequent requests will come from memory.
The advantage of this class is that subsequent identical requests will block on the outstanding one (so if you ask for “foo.com” on 3 separate threads, one of them will send out the web request and the other two threads will receive the result as well). This class also allows you to place a blocking limit on the number of outstanding requests, so that further requests will block until some of the inflight requests have been satisfied.
IEnableLogger – this is an implementation of a simple logger that combines some of log4net’s syntax with the ubiquity of the Rails logger – any class that implements the dummy IEnableLogger interface will able to access a logger for that class (i.e. this.Log().Warn("Something bad happened!");)
WPF Data Validation using DataAnnotations
Data Validation in WPF isn’t that great
As part of trying to put together a “base application” for starting projects at work, I’ve had a look at WPF Data Validation for the first time. Compared to ASP.NET MVC, WPF’s data validation is really primitive – it basically leaves you to do everything by hand. Fortunately, the DataAnnotations DLL is sufficiently decoupled, that we can actually use it – props to Brad Wilson’s Data Annotations article for the inspiration to add it to WPF.
Disclaimer: The DataAnnotation guys would probably tell me I’m Doing It Wrong(r) here, and this code is proof-of-concept and very inefficient. However, it’ll gets the idea across
Using DataAnnotations
First, we’ll make a dummy class:
{
[StringLength(35, MinimumLength = 3)]
public string Name {get; set;}
[StringLength(10, MinimumLength = 10)]
public string PhoneNumber {get; set;}
}
public class DataValidatable : IDataErrorInfo
{
public class Foo : IDataErrorInfo
{
public string Error{
get { throw new NotImplementedException(); }
}
public string this[string columnName] {
get { throw new NotImplementedException(); }
}
}
}
Now, let’s implement IDataErrorInfo using data annotations:
{
get {
var prop = GetType().GetProperty(columnName);
var validationMap = prop
.GetCustomAttributes(typeof(ValidationAttribute, true)
.Cast<validationattribute>();
foreach(var v in validationMap) {
try {
v.Validate(prop.GetValue(this, null), columnName);
} catch (Exception ex) {
return ve.Message;
}
}
return null;
}
}
</validationattribute>
Making it show up in the view:
To actually see your validations get called, you need some magic words in the binding – here’s how to do it:
You can get the crash reports from Windows Error Reporting (Watson)
One of the things I see pop up on Stack Overflow all the time is, people wanting to hide or suppress the Windows Error Reporting dialog – the feature of Windows where crash reports are sent to Microsoft when your app crashes. Developers say, “MS doesn’t care about my app, what’s the point?” If they’re not so bright, they’ll write a try/catch block around their main() and hide all errors, then they’ll never find out why their apps crash in the field. Smarter developers will essentially write their own hacked-up version of WER with varying degrees of success. However, there’s a 3rd option that is superior:
Register with Microsoft, and get the WER Reports
Microsoft doesn’t just trash your reports, we will automatically aggregate them into distinct crashes (called ‘buckets’) and show you a ‘popularity contest’ of crashes – you can find out a ton of detailed information about what is happening in the field. Here’s the MSDN article detailing how to sign up. It takes a bit of leg work, but if you’re writing any sort of production-quality application, it’s 100% worth it.
But here’s what to do if you don’t believe me
Alright, so you have some super-good reason as to why you really don’t want this dialog to show up. Here’s what works on Win2k and higher (Vista has an API to do this explicitly though):
{
TerminateProcess(GetCurrentProcess(),
WhyGodWhy->ExceptionRecord->ExceptionCode);
// Never gonna get here
return EXCEPTION_EXECUTE_HANDLER;
}
int main(int, char**)
{
SetUnhandledExceptionFilter(KillSelfOnUnhandledException)
}
How to move Windows to another computer
Moving a Linux install is easy
One of the awesome things about Linux was always, that it’s so incredibly easy to move your stuff to another machine – just stick the drive in another computer and it boots right up; if you do this directly with Windows, it will probably blow up in your face. Installing everything from scratch takes forever and generally sucks.
Windows can do this too, but with some more work
So, if you’re a Dell or a Toshiba or a Lenovo, here’s how you operate – you have a lot of different machines you’re trying to sell, but you don’t want to maintain an OS image for every one. OEMs didn’t like this, so they asked MS to help out, and Microsoft gave them Sysprep.
One of the main features of Sysprep is called “generalize”, where we’ll keep the installed stuff, but “forget” everything about the specific hardware of the machine. The next boot, Windows will go through the same process as when it was first installed, and reinstall everything.
This is where you come in, intrepid reader
So basically, you need to download the Windows Automated Installation Kit for Win7. Update: Apparently this tool comes in-box, no download needed! This gives you Sysprep (and ImageX, which is an interesting tool itself). Then, run the following magic command:
Windows shuts down, and then you move the drive to another computer.
Moving a VM to a Native Boot-to-VHD
The same trick is also how you can take a VHD image of a machine and run it using Windows’s “Native VHD boot” feature. You know, where you can take a VHD and just run it, on your machine, full speed. Awesome. While it’s a VM, Sysprep it, then boot from it – you won’t have any of the STOP 0×7F problems that you might have if you ran it natively, and you just saved yourself a ton of time versus waiting for Windows to install.
Running Hyper-V on Windows 7 Client
Run Hyper-V on Windows 7? Unpossible!
Ok, so I lured everyone in with a provocative title, and I can’t exactly deliver – there is no way as far as I know to directly run Hyper-V on any client version of Windows 7. But there’s an important bit of software that has an obscure name that can really help you out.
The caveat is, you need a machine that’s free and supports hardware virtualization (i.e. AMD-V or VT-x). Not all machines support it, and a lot of them need some BIOS fiddling to make it work properly.
Hyper-V Server 2008 R2 costs exactly zero dollars
Nobody knows about this, and I don’t know why it’s not more popular – Microsoft gives away the Server Core Hyper-V SKU. For free. No dollars. Go over here and download it. Set this up on a machine and it should drop you at a command prompt – that’s all there is to Server Core, just a cmd prompt; that’s all you need for Hyper-V though.
Remote Server Administration Tools for Windows 7
A lot of people think that you need to have Windows Server installed to be able to administer other servers – otherwise you don’t have the MMC snap-ins, so people resort to TSing into their boxes to administer them. Ever since Vista, we’ve made a package called the Remote Server Administration Tools (RSAT), which brings all of the snap-ins like the Active Directory admin page, the DNS page, everything that’s on Server – only on Vista / Win7.
This won’t magically make your Windows 7 box be able to be a Domain Controller though, you’ll only be able to connect to other machines. However, this includes all of the Hyper-V client components – you’ll be able to view the console, manage/add machines, etc. Here’s the only trick though, the installer is kind of goofy – installing the package only adds the entry in the Add Optional Features list. Then, you have to actually choose what to install.
Combine these two, and you’ve got Hyper-V on Win7 for free
Just like the heading says, if you combine these two, you’ve got Hyper-V for free. Yahtzee! Combine this with disk2vhd, and you can get rid of a bunch of test machines and move them to VMs. Move VHDs using the SMB admin shares, like \\mycoolbox\C$\Users\Public\Documents\Hyper-V Disks
Live Mesh – good UI changes how you use software
This article was supposed to be longer, but I hit “Publish” too fast. Mea culpa.
Because once again, I’ve turned into a giant Microsoft shill now that I work there, I thought I’d try Live Mesh, Microsoft’s new file sharing/storage service; especially since they now have a Mac Beta. After using it for a few weeks, I can now definitely say that it’s a pretty well-written piece of software, and that’s not a compliment I give out lightly.
Good UI sucks to write
Good UI execution is hard for two big reasons. It’s hard because you’ll build a UI based on how the underlying code is set up, you’ll sit down to use it, and then you’ll find it completely unusable – programmers are bad at design because their entire mindset is to build it right the first time. Contrast this to Industrial / Product Designers, who from the very beginning of school are taught, “come up with 50 ideas for the same project and turn them in”. Making good UI is a process that requires a lot of iteration and experimentation, and a willingness to come up with 25 ideas and throw away 23 of them.
In design, iteration is made to be very cheap – you’ve got a pencil and a piece of paper, and you draw it all out; coming up with those 50 ideas doesn’t involve tertiary work, 100% of your efforts are moving your ideas forward. With making UI, it’s not so easy – even with tools like Expression Blend trying to make UI work easier, it’s still a ton of effort to create all of the little interactions that make a UI great. Writing a UI is difficult, and writing a great UI is difficulty multiplied.
So why is Live Mesh’s UI so good? No modal dialogs!
One reason that I like Live Mesh is, unlike a lot of other software products (mostly ones written by Microsoft), I’ve never seen Live Mesh pop up a message box forcing me to answer some question when it wasn’t prompted by me. That last part is important, because it touches on the concept of user intent. When I click on “Send/Receive mail” and it needs my password, it’s okay to pop up a dialog to ask it, because I asked the program to do something. When apps pop a dialog on their own, imagine someone suddenly walking up to you in the middle of a conversation with someone else – impolite at best.
Smartcard Readers, Windows 7, and VMWare Fusion
At work, I’m on the pilot for one of the new features in Windows 7, DirectAccess. You know how Outlook just magically works, whether you’re connecting inside your LAN or outside it, even though they use different servers/protocols/whatever? Imagine that, only with every app – it’s totally transparent VPN, and except for a few apps that can’t grok IPv6, it works great.

I’m a Smartcard reader, and I’m about to throw some salt in your game
One of the caveats at least at Microsoft is, you have to use a Smartcard reader, like the one pictured above. Unfortunately for me, these appear to be some kind of broken under VMWare Fusion 2.0; trying the advice in the thread unfortunately got me nowhere.
Here’s the workaround, though it’s super-annoying because it basically makes suspending the VM worthless.
- Power off the VM completely
- Plug in the Smartcard reader, with the card inserted
- Hit the Power button on the VM
- Before the machine boots completely, click on the USB icon at the bottom right, and select the “Connect Omnicard USB Reader” menu item that pops up
The Smartcard reader will appear to be dead until right before LogonUI spins up (i.e. right when you see the blue “underwater” screen where you type in your Smartcard PIN). It should work from then on, as long as you never detach the reader.
Like I said, super annoying; if anyone’s got any better ideas, I’m definitely willing to hear them; I suspect this has something to do with the new Smartcard support that VMWare added in their Workstation product – maybe there’s a way to disable this via a VMX config option?
Essentials 2008
Continuing from last year’s edition, here’s the software that I use on a day-to-day basis. Because of my traitorous switch to Mac, this list looks quite a bit different than it did earlier. As before, this is cribbing from Mark Pilgrim’s series – his 2008 edition is also full of good recommendations.
- Mac OS X 10.5 – after using a Mac as my primary machine for over a year now, I’m on the fence as to whether I’d ever go back to Linux or not. On one hand, the UI design and software support is great, but there’s just enough proprietary bullshit to make me reconsider. For the time being though, it’s the best there is, because my other favorite OS Ubuntu and Linux in general seems to be on a steady decline to crap city. If anyone takes offense to this assertion, I’ll be glad to write up a detailed response as to why it’s a mess.
- F-Spot, delicious, Vim – still continue to kick ass. Because of the wedding, I ended up effectively doubling my picture library, mostly with U’s 2MB pictures from her SLR camera – F-Spot handles it like a champ.
- Git and GitHub – Git is so mind-blowingly useful to anyone who is a developer, power-user, or anyone who works with text files, that I can’t possibly leave it off this list. This program continues to help me out just about every time I program; at work, I use it to manage multiple in-flight hotfixes to certain train-wreck components who shall remain nameless (but not linkless), as well as whenever I have to do any large change to Windows source code. At home, GitHub is a great way to manage my developer tools as well as my personal projects.
Seriously, if you’re any sort of programmer whatsoever, learn Git.
- Quicksilver – it’s hard to describe what QS actually is, the term “app launcher” betrays its real utility, but it’s by-far one of the best reasons to use Mac OS X. Basically, it’s a GUI version of a fast command-line interface, one that learns which commands you use most often and shortens the number of keystrokes you need to use them. Taking some time to learn everything that QS can do pays off quite a bit for your productivity.
- Firefox – continues to be the browser of choice, with its fantastic plugins (the “It’s All Text!” plugin being one of my favorite, lets me use GVim to type Emails or this blog entry for example). Great developer tools like Web Developer Toolbar and Firebug make it way better than Safari for most things. Speed and platform-integration are two of the things I do miss though…
- Live Mesh – file synchronization that just works. Works great with both Windows and Mac, and its remote desktop feature while somewhat anemic, is beautifully simple to use. If you don’t have a backup solution (and if you don’t, you will lose your stuff – storing everything on a USB stick does not count), this is a fantastic way to do it with almost zero work
- VMware Fusion – solid virtualization software for Mac, great integration with the guest without the evil hacks that Parallels uses (trust me as a Windows developer when I say this, you are much safer with VMware than with Parallels). These days however, I prefer more to use a dedicated VM running on another machine that I can remote desktop into rather than a local VM.
- Cygwin – without this, work would be way more painful. A Windows machine without Cygwin is nearly worthless to me.
- iTunes – …and I f’ing hate it. Please, someone write a music player for OS X that doesn’t epically suck. Amarok 2.0 and Songbird don’t count – Amarok went from the best music player on the planet without question, to a giant pile of gray crap. Trolltech systematically destroyed every decent KDE piece of software by releasing Qt4 and causing everyone to decide to make massive rewrites of their software, but I digress.
Anyways, some of the few things that iTunes got very, very right are, how it remembers exactly where I am in a podcast and syncs it with the iPhone, its podcast support in general, and its great sync support with devices (letting me choose whether to auto/manual sync music, making automatic backups of my phone, etc). The iTunes store would also be a gigantic win if it wasn’t so DRM-encumbered, and I would spend way more money there, instead of at Amazon MP3, which is also a fantastic service.
- XBMC – I’ve been using this on the XBox for years, and now that it’s a 100% cross-platform app, it’s even more awesome. Playing back video on your TV with this is fantastic, I stream movies and TV from my desktop machine over wireless and it works near-flawlessly, and understands just about any format. Setting up a cheap box with XBMC on it is the best way to get your music and movies onto your TV, hands-down. There’s also versions for hacked AppleTVs, which turns an AppleTV to me, from “complete trash” to “very compelling”. If the AppleTV had decent audio/video outputs, it would’ve been my new media box.
Stuff I don’t use anymore
- Tomboy – only runs on Linux until recently, and is local-only. The original developer also annoys me by coming up with fantastic ideas then abandoning them (I could also point that right towards myself, but anyways…)
- sshfs – I still use this occasionally when I have to traverse firewalls, but for everything local, Samba is faster and a bit less of a pain on OS X
- Unison – since I do much less work on my desktop than I used to, having two-way sync isn’t as useful to me; I just rsync from laptop -> desktop.
- Ubuntu – too many things broken on MacBook Pros, most the fault of Apple’s strange hardware, but it doesn’t change the fact that it’s broken.
How 64-bit Windows works – cause no one seems to get it
64-bit is the future
Despite everyone dragging their heels as much as possible, eventually developers and users will start moving soon to 64-bit; in WinSE, we predict that this is going to accelerate quite a bit because computer manufacturers are starting to sell machines with more than 4GB of RAM, and customers start complaining when they pay for 4GB and only get 3ish or so
However, even among experienced developers, I hear a lot of confusion about how 64-bit works, and how I can run 32-bit programs on 64-bit. Listening to the .NET Rocks episode on the subject shows that even fairly knowledgeable guys can be pretty confused about how all of this works. Hopefully, this blog post can set the record straight for some of you – if anything seems like it makes no sense, leave a comment or send me an Email and I’ll try to update the entry!
The one thing to remember
Whether you’re on Windows, Linux, or OS X, there’s one fundamental problem that underlies all of the complexity; if you remember this one fact, everything else in this article will make sense. Here it is:
You can not load a 32-bit library in a 64-bit process.
Repeat that out loud a few times, it’ll help. This is a fundamental aspect of 64-bit computing and 32-bit compatibility mode on the amd64 and IA64 architecture, it’s not specific to Windows. This rule shows up in a lot of places that you wouldn’t expect, like Explorer shell extensions, browser plugins like Flash, and multimedia codecs in Linux.
In an “all 64-bit” world, there are no problems – everything is simple and works pretty much just like 32-bit. However, one of the advantages of the amd64 architecture is that it allows 32-bit code to be run in compatibility mode, with almost no loss in performance. Being able to run both 64-bit and 32-bit apps in the same OS is huge for application compatibility, and AMD was very smart to make it possible (unlike Itanium, which pretty much threw x86 compatibility out the window, and felt the much-deserved consequences). However, to make this actually work is most-definitely not a trivial affair – there’s a lot of things to fix up to make everything as seamless as 32-bit.
How does Windows deal with it?
The core infrastructure in Windows NT to handle this is called WOW64 – this code manages emulating the 32-bit architecture (either by only setting the processor mode in amd64, or actually performing emulation in IA64). As a result of the rule I’ve described above, there are actually two copies of almost every API in Windows – one for native binaries and one for 32-bit binaries.
For every system DLL, there’s two versions!
When a 32-bit app gets launched on x64, all of the DLLs being used are from the \Windows\SysWOW64 directory; usually these follow an identical codepath to the 32-bit version of the DLL, though certain DLLs like user32.dll actually operate differently in WOW64 mode. There’s a lot of stuff behind the scenes to make this happen, such as Filesystem Redirection (almost all apps don’t need to know anything about WOW64!) However, there’s still one problem – for 100% user-mode DLLs, this solution works, but the kernel is 64-bit, and only 64-bit. We surely can’t load a separate 32-bit kernel running at the same time!
When it comes down to it, you need to get the data to the kernel in a different way, some sort of IPC mechanism – in Windows this involves the RPC/LPC mechanism, or more commonly, via a syscall. When a 32-bit app calls CreateFileW, it calls NtCreateFile, which pushes the appropriate parameters into registers, and invokes the SYSENTER instruction to switch back into 64-bit mode. This mechanism works because there is only the kernel to worry about transitioning to, and it can have special knowledge as to whether the calling process was 32-bit or 64-bit.
What about .NET?
.NET is an interesting case; when you install the 64-bit .NET framework, two versions of the CLR are installed as well as the GAC (knowing that there are two GAC’s can avoid a major Gotcha!). However, most .NET binaries are MSIL – since the binary is in a processor-agnostic instruction set, which one does it choose?
The answer is, “usually 64-bit, except for when it doesn’t.” .NET assemblies can be marked as “only run on x86/x64″ via the compiler or via the Corflags tool,and there’s one very important reason to do so, if you use P/Invoke to a library that only has a x86 version. Unfortunately, the check for x86-only will only extend so far down the dependency chain, so if you have a library who uses a library who uses a native library, the CLR will end up throwing a BadImageFormatException.
Debugging using WinDbg
There’s one special trick to debugging an x86 binary on 64-bit with WinDbg, via this blog entry, that if you’re having trouble getting a call stack, you need to load the wow64exts debugger extension and use the “!sw” command to switch between 64-bit and 32-bit mode. VS is luckily smart enough to handle this for you (though I haven’t tried it recently!)