Failing Properly
/There's nothing like writing a program to get you thinking about how to do things properly. My Magic Marker program is one such example. Turns it it is possible to use it incorrectly. If a file is open when you try to save it (because you've got the spreadsheet open in Excel for example) the save is doomed to fail. Above is the message that you see if you try to save in this situation.
private bool saveEverything()
{
try
{
// write the file
}
}
catch (Exception e)
{
System.Windows.MessageBox.Show("File error: " + e.Message,
"Magic Marker");
return false;
}
return true;
}
This the code that makes it happen. It catches files exception and displays it. It then returns false to indicate that the save has failed.
I've also written the program so that it automatically saves the data when you exit it, which seems sensible. It's what most people will expect to happen these days. But if the save fails when you exit you get this message:
This is the best (i.e. least worst) way I can come up with for dealing with this problem. At least it gives the user the chance to go back and fix the problem (for example they might not have entered a valid mark value which is stopping the save from working).
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (!saveEverything())
{
if (System.Windows.MessageBox.Show(
"The file save has failed. Do you really want to exit?", "Magic Marker",
MessageBoxButton.YesNo) != MessageBoxResult.Yes)
e.Cancel = true;
}
}
Here's the code that makes it happen. This is the event handler for the WindowClosing event for the application page. It tries to save everything and then, if the save fails, gives the user the option to cancel the exit. I've tried to make the answer options (yes or no) directly match the question.
The only thing I'm not completely happy with is that it is possible for a programmer to use my saveEverything method and ignore the situation where the method doesn't work properly (you don't have to use the result of a method call).
Ideally saveEverything should rethrow the exception or not catch it and rely on the caller to deal with the problem. However, in this case I'm happy to keep things comparatively simple.