Download Bug Pad for Free. Download

Download the code in a Visual Studio solution

Bug Pad Icon

Also from Software Productions: Our Free Bug Tracker Bug Pad.

Free Open Source C# Utility library


All these utilities are available as full source code, so you can modify and enhance them to meet your own needs as required. You can use the sample code for any purpose, including commercial applications. See the full license terms.

Software Productions' C# Code Samples

Complete Undo/Redo Library

Users love undo. Being able to undo and redo actions in an application saves users from losing work through simple mistakes, and gives them the confidence to experiment while learning new features. Undo and Redo are difficult features to implement however, so it is left out of many applications where it would be useful.

The Undo Redo library provides a lot of the difficult part of implementing Undo/Redo pre-built. All you have to do is record data changes in the UndoChain. Undoing and Redoing those changes is then handled by the library. If your data is stored in ADO.NET DataSets, it can even record data changes itself, leaving you practically no work to do!

  • Uses a circular buffer to store changes, so you can specify any number of actions that are allowed to be undone, and the UndoChain will never use more memory or perform expensive array copying operations.
  • Automatically records changes to an ADO.NET DataSet or DataTable.
  • Allows multiple changes to be grouped so they are Undone/Redone as a unit.
  • Automatically modifies the values of your data when the user performs an undo/redo, and calls an event so you can update the UI if required.
  • Can undo changes to your data model, or to the controls on a form, depending on how changes are logged.
  • Built in actions modifying a property value, adding or removing an item from a list or dictionary, changing a value in a DataRow, adding and removing a DataRow from a DataTable.
  • Can be extended by adding Custom actions which implement a simple interface.
  • Can be used to keep track of changes in the UI, so the user can be promted to save if they try to close without saving, but will not be prompted if there are no changes, even if they make changes and then undo them.
  • Automatically suspends recording changes that occur during an undo/redo operation, so that these actions do not pollute the UndoChain. This means you can send the UndoChain updates whenever the data changes, without having to worry about whether the change was caused by an undo/redo action or not, keeping the code to record changes as simple as possible.
  • Automatically merges repeated changes to the same property, so it does not undo/redo one character at a time.

//Creates a new UndoChain that can undo the last 50 actions.
undoChain = new UndoChain(50);

//When the user edits a value, we log the change in the undo chain so it can be undone.
//This example records the change to the value in the control. This means 
//that we do not need to update the control when an undo is performed, the UndoChain will do it for us.
//If you record the property change to our data model, and do not use data binding, 
//you may need to update the UI by handling the UndoChain events (see below).
undoChain.AddUndoItem(new PropertyChangeUndoItem(notesTextBox, oldNotes, notesTextBox.Text, "Text"));

//Changes that add or remove items from a collection also need to be recorded.
undoChain.AddUndoItem(new ListAddUndoItem(list, newItem, newIndex));


//We can avoid having to log changes as above if our data is stored in an ADO.NET DataSet.
//In this case we can use the DataSetChangeLogger to automatically record changes.
undoLogger = new DataSetChangeLogger(undoChain);
undoLogger.RecordChanges(_workItemManager.WorkItemTable);


//If we need to update the user interface after an undo or redo,
//we can handle the events raised by the UndoChain.
undoChain.Undone += new UndoActionEventHandler(UndoChain_Acted);
undoChain.Redone += new UndoActionEventHandler(UndoChain_Acted);

//To undo an operation
undoChain.Undo();

//To redo an operation
undoChain.Redo();


//After we have initialized the form and after it is saved,
//we tell the UndoChain to reset its dirty flag.
undoChain.Dirty = false;

//Then when the form is closing we can check if there are
//any unsaved changes and prompt the user to save them.
//If the user makes changes and then undoes them they will not be prompted.
if (undoChain.Dirty) 
{
    //Prompt the user to save changes...
}

Serialize any object to elegant human readable XML

There are a number of ways to serialize objects to XML in .NET. None of them are perfect however: The built in XmlSerilaizer class cannot serialize objects the implement IDicionary, that contain circular references, and has other limitations as well. The SoapFormatter can serialize any object graph but produces unreadable XML intended for machine consumption only. You can implement IXmlSerializable on all the classes you might want to serialize to gain full control, but this can require considerable effort. The Software Productions XmlSerializer falls between these options. It can serialize and deserialize almost any .NET object graph, and produces human readable XML. It does not provide the level of control that implementing IXmlSerializable does, but it is as simple to use as the the SoapFormatter.

//Serialize an object to a stream (e.g. An XmlTextWriter).
XmlSerializer serilaizer = new XmlSerializer();
serilaizer.Serialize(object, stream)

//Deserialize the object to restore its state.
object = serializer.Deserialize(stream);

Save files in SQL Server without loading the entire file into memory

If you use text or binary fields to store file contents in SQL Server as BLOB (Binary Long Object) data, you may run into a problem. The ADO.NET mechanism for reading and writing the BLOB works fine for small files, but takes longer and longer and consumes more memory as the file size increases. The solution to this problem is to use SQL Server TEXTPOINTERs to read and write the data in sections. The SqlBinaryDataManager class implements this and provides a simple, easy to use interface.

//Save a file into an SQL Server database.
using (SqlConnection connection = new SqlConnection(ConnectionString)) 
{
    connection.Open();

    using (SqlTransaction transaction = connection.BeginTransaction())
    {
        SqlBinaryDataManager.StoreFile(localFileName, connection, transaction, 
            "<TableName>", "<DataFieldName>", "<PrimaryKeyFieldName>", "<PrimaryKeyValue>");

        transaction.Commit();
    }
}

//Load a file from SQL Server and save it in the file system.
using (SqlConnection connection = new SqlConnection(ConnectionString)) 
{
    connection.Open();

    SqlBinaryDataManager.FetchFile(localFileName, connection, null, "<TableName>", 
        "<DataFieldName>", "<PrimaryKeyFieldName>", "<PrimaryKeyValue>");
}

Automatically arrange the tab order of all the controls on a form

AutoTabOrder is a class to automatically arrange the tab orders of the controls on a form from left to right and top to bottom. It arranges the tab orders of controls on Panels and other container controls, including TabStrips. Simply call the ArrangeTabOrders method after the controls are loaded in the form constructor or Form Load event.

AutoTabOrder.ArrangeTabOrders(form);



Software Productions © 2006 - 2009. All rights reserved. — info@softwareproductions.com.au