UndoRecorder Action Groups now leverage IDisposable to ensure they are cleaned up.

@Benglin 

We had a few test cases where an exception thrown in the middle of an Action Group left the Undo Group open, which was messing up all subsequent tests.

Working with Action Groups before the change:
```csharp
UndoRecorder.BeginActionGroup();
try
{
    ... perform a bunch of actions ...
}
finally //ensure that EndActionGroup() is called, even if an exception is thrown.
{
    UndoRecorder.EndActionGroup();
}
```

After the change:
```csharp
using (UndoRecorder.BeginActionGroup())
{
    ... perform a bunch of actions ...
}
```

This PR contains changes to UndoRecorder to support the IDisposable pattern, and updates all usages of `BeginActionGroup` and `EndActionGroup`.
Thanks for making this :)