If you’re writing a WPF application or some other XAML-based application, you’re probably using the Model-View-ViewModel (MVVM) pattern. If you’re being “good” about your MVVM implementation, you’re putting all your button click handling code into ICommand properties on your ViewModels. (What!? You’re not doing that? Naughty naughty! You should! It makes it so much more testable!)
Anyway, one of the tricky things about using ICommands and then binding your user interface buttons to them is exception handling. If you just created a click handler in the code behind for your user interface, you’d just put a try-catch block in that method and probably put a MessageBox.Show() in the catch to display the error on the screen. Since no good deeds go unpunished, if you’re using MVVM and ICommand, you really can’t do that. And just to make it a little worse, if you don’t do some kind of try-catch somewhere in your ICommand implementation, you’ll end up with a pretty darned unfriendly error message just before your app crashes.
So you can fix this by putting a try catch inside of the methods that your ICommand properties call to do work but that gets repetitive and if you miss a spot then — BOOM! — ugly exception and then a crash.
The Fix:
Create a class that implements ICommand that handles exceptions for you automatically from within the ICommand.Execute() method. If you’re using the MvvmLight libraries, this can be done really easily by extending the RelayCommand class.
public class ExceptionHandlingRelayCommand : RelayCommand { public ExceptionHandlingRelayCommand(Action execute) : base(execute) {}
public override void Execute(object parameter) { try { base.Execute(parameter); } catch (Exception ex) { HandleException(ex); } }
private void HandleException(Exception ex) { new ViewModelLocator().Messages.ShowMessage(ex); } }
In the code sample above, it’s as easy as putting a try-catch in an override of the Execute() method, calling the original implementation of Execute() from the RelayCommand base class, and then handling any exceptions that come flying out. Now anywhere that you use the ExceptionHandlingRelayCommand rather than just RelayCommand or some other implementation of ICommand, you’ll automatically get your exception handling logic.
Here’s the code for a sample application that demonstrates this.
Hope this helps.
-Ben
Leave a Reply