Tag Archives: Yodelay
Yodelay Project Structure Update

I’ve been exposed to some better repository organization lately. In response to what I’ve learned, I’ve updated the yodelay project structure to make it easier to build with the external dependencies. It seems obvious in retrospect :-). The new structure looks like this:

 

/     // source root

/src // directory for project source code

/libs // directory for non-Framework assembly dependencies

This should make it possible to download and build whether or not you have already installed NUnit and Rhino mocks on your machine.

ObservableCollectionHandler & ChangeTracker

When working with the ObservableCollection or INotifyCollectionChanged interface, it is common to see code like the following:

void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    switch (e.Action)
    {
        case NotifyCollectionChangedAction.Add:
            HandleAddedItems(e);
            break;

        case NotifyCollectionChangedAction.Move:
            break;

        case NotifyCollectionChangedAction.Remove:
            HandleRemovedItems(e);
            break;

        case NotifyCollectionChangedAction.Replace:
            HandleReplacedItems(e);
            break;

        case NotifyCollectionChangedAction.Reset:
            HandleClearItems(e);
            break;
    }
}

There’s nothing particularly wrong with this code except that it’s kind of bulky, and that it starts to crop up all over your application. There’s another problem that’s not immediately obvious. The “Reset” action only gets fired when the ObservableCollection is cleared, but it’s eventargs does not contain the items that were removed from the collection. If your logic calls for processing removed items when they’re cleared, the built-in API offers you nothing. You have to do your own shadow copy of the collection so that you can respond to the Clear() correctly.

For that reason I wrote and added ObservableCollectionHandler to manage these events for you. It accepts three kinds of delegates for responding to changes in the source collection: ItemAdded, ItemRemoved, and ItemReplaced actions. (It would be easy to add ItemMoved as well, but I have seldom had a need for that so I coded the critical path first.) The handler maintains a shadow copy of the list so that the ItemRemoved delegates are called in response to the Clear() command.

[Test]
public void OnItemAdded_ShouldPerformAction()
{
    // Arrange: Setup the test context
    int i = 0;
    var collection = new ObservableCollection<Employee>();
    var handler = new ObservableCollectionHandler<Employee>(collection)
        .OnItemAdded(e => i++);

    // Act: Perform the action under test
    collection.Add(new Employee());

    // Assert: Verify the results of the action.
    Require.That(i).IsEqualTo(1);
}

Another common need with respect to ObservableCollections is the need to track which items were added, modified, and removed from the source collection. To facilitate this need I wrote the ChangeTracker class. ChangeTracker makes use of ObservableCollectionHandler to setup activities in response to changes in the source collection. ChangeTracker maintains a list of additions and removals from the source collection. It can also maintain a list of modified items assuming the items in the collection implement INotifyPropertyChanged.

Here is a sample unit test indicating it’s usage:

[Test]
public void GetChanges_AfterAdd_ShouldReturnAddedItems()
{
    // Arrange: Setup the test context
    var source = new ObservableCollection<Employee>();
    var tracker = new ChangeTracker<Employee>(source);

    // Act: Perform the action under test
    var added = new Employee();
    source.Add(added);

    // Assert: Verify the results of the action.
    var changes = tracker.GetChanges(ChangeType.All);
    Require.That(changes.Any()).IsTrue();
    Require.That(tracker.HasChanges).IsTrue();

    var change = changes.First();
    Require.That(change).IsNotNull();
    Require.That(change.Type).IsEqualTo(ChangeType.Add);
    Require.That(change.Value).IsTheSameAs(added);
}

The full source code and unit tests can be found here.

Yodelay Updated

Yodelay has been updated. I’ve modified the Regular Expression tester so that it supports n-number of test contexts with a single expression. In addition, you can search regexlib.com for a useful expression.

This screen is fully implemented using MVVM. The search window serves as an example of using MVVM with dialogs.

I’ve also pulled in the themes from WpfThemes and integrated the ThemeManager.

Check it out!

Neoshooter 1

Announcing the Yodelay .NET Framework Extensions Project

I have created an open-source project on CodePlex called “Yodelay”. From the project description:

The Yodelay .NET Framework Extensions project provides a library of components that make many kinds of programming tasks simpler. These include basic MVVM components, Unit Test Extensions, and a poor-man’s Dependency Injection library.

Most of the classes and extension methods in this library are rei-mplementations or adaptations of components I have written in other places. Some of them have been found in various forms on developer blogs. Where this is true, I have indicated where I retrieved the original source code in the comments. This library is not just a collection of random classes. The attempt here is to bring all of these components together and use them in an integrated fashion to develop stable applications faster.

Not all code in this project is currently covered by unit tests. This is because many of the classes were adapted from blogs or other existing projects and may not have been developed using TDD. Every effort will be made to bring existing classes under test coverage, and to practice TDD when adding new code.

Why did I call it Yodelay? For no other reason than I like the way the word sounds. It rolls off the tongue easily, which is the effect I hope the library has on applications.

There is no installer yet. Yodelay is in version 0.1, but there are already quite a few goodies in the library. Everything is built against the 4.0 framework. I will try to work on it a little each week, adding new components and demo projects when I can. In the near future I will be signing the assemblies and building an installer for them.

Enjoy!