Pulled Apart - Part XIV: DevExpress

Submitted by Robert MacLean on Mon, 12/13/2010 - 10:25

Note: This is part of a series, you can find the rest of the parts in the series index.

I make no attempt to hide my love for a company called DevExpress which produces enhancements for Visual Studio and additional controls for WinForms, ASP.NET Web Forms, ASP.NET MVC, WPF & Silverlight.

When I started with Pull I used mostly the standard WinForm controls and over time have changed it be almost 100% DevExpress controls for a number of reasons:

  • Rudi Grobler, Silverlight expert sits across the partition from me and loves to point out how ugly standard WinForms is compared to Silverlight. DevExpress helps me make my applications look MUCH better.
  • Every line of code has a cost to it and the value of that line of code decreases overtime. So standing on the shoulders of giants means my cost of development is MUCH less. This also means I focus on the business aspects and not on the UI aspects.
  • There is a lot of parity between DevExpress controls over different platforms, so if I want to change platform (for example to Silverlight) then I know the feature set will be close, lot’s of code could be reused.

Below is the first public version of Pull, which uses just DevExpress GroupBoxes, the rest is all WinForms:

image

versus the UI currently in development (for the January 2011 release) where only the status bar and web browser control are not from DevExpress! I think you will agree it looks way better now, plus there are many new features there (like filtering grids) which were not supported previously.

image

Grid Extensions

For the January 2011 release we switched to the DevExpress grids, which meant a lot of code needed to be changed (or just deleted) and I ended up writing a few extensions for the grids which I believe may be of use to other people:

Return a collection selected items

Rather than working with a collection of selected rows, this allows you to get the values of the selected rows:

public static IEnumerable<T> SelectedItems<T>(this ColumnView view) where T : class
{
    foreach (int selectedRowHandle in view.GetSelectedRows())
    {
        T item = view.GetRow(selectedRowHandle) as T;
        yield return item;
    }
}

Select a collection of items

The grid normally lets you select a single row or a continuous range, however often I want to provide a list of item values and have the rows which match those values selected:

public static void SelectRows<T>(this GridView view, IList<T> selectedItems) where T : class
{
    foreach (T selectedItem in selectedItems)
    {
        for (int counter = 0; counter < view.DataRowCount; counter++)
        {
            T item = view.GetRow(counter) as T;
            if (item == selectedItem)
            {
                view.SelectRow(counter);
            }
        }
    }
}

Layouts and Strings

You can persist the layout of the grid to a stream, the registry or XML file. However I have a settings file and I would like to save and restore the layout from strings so I can easily add it to my settings file:

public static string SaveLayoutToString(this GridView view)
{
    MemoryStream gridStream = new MemoryStream();
    view.SaveLayoutToStream(gridStream, OptionsLayoutBase.FullLayout);
    gridStream.Position = 0;
    using (StreamReader reader = new StreamReader(gridStream))
    {
        return reader.ReadToEnd();
    }
}

public static void RestoreLayoutFromString(this GridView view, string layout)
{
    if (!string.IsNullOrWhiteSpace(layout))
    {
        using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(layout)))
        {
            stream.Position = 0;
            view.RestoreLayoutFromStream(stream, OptionsLayoutBase.FullLayout);
        }
    }
}

Enum + Grid + Images = Headache

imageI have an enum for the podcast state and rather than show the text, which is the default, I want to show an image on the cell. However this is not the easiest thing to figure out since there is no designer support for this Sad smile However you can do most of this in the designer and then only need one line of code per enum value Smile.

Step 1

Set the Column Edit property of the column to an ImageComboxBoxEdit: image

imageStep 2

On the ImageComboBoxEdit editor settings set the small images (and/or large images) property to the image list which contains the items you want to show.

It is important that you know the position (or index) of image in the image list.

Step 3

Now all you need to do is add the item values for the editor in code using the Items.Add method, which takes an ImageComboBoxItem. That class has some overloads which accept an Object for the value and here you can put in the enum value. Once this is done it all works fantastically.

You’ll note in the demo code below that I have an image index of –1 for the first item, this is so that no image is shown!

editor.Items.Add(new ImageComboBoxItem("None", PodcastState.None, -1));
editor.Items.Add(new ImageComboBoxItem("Downloading", PodcastState.Downloading, 0));
editor.Items.Add(new ImageComboBoxItem("Pending", PodcastState.Pending, 1));
editor.Items.Add(new ImageComboBoxItem("New Episodes", PodcastState.NewEpisodes, 3));
editor.Items.Add(new ImageComboBoxItem("Error", PodcastState.Error, 2));