Pulled Apart - Part XIV: DevExpress
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, and Silverlight.
When I started with Pull, I used mostly the standard WinForms controls, but over time changed it to be almost 100% DevExpress controls for a number of reasons:
- Rudi Grobler, a 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, and that value decreases over time. So, standing on the shoulders of giants means my development cost is much lower. This also means I can focus on the business aspects rather than the UI aspects.
- There’s a lot of parity between DevExpress controls across different platforms, so if I want to change platforms—for example, to Silverlight—I know the feature set will be close, and lots of code can be reused.
Below is the first public version of Pull, which uses only DevExpress GroupBoxes, while the rest is all WinForms:
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’ll agree it looks way better now, plus there are many new features there—like filtering grids—which weren’t supported previously.
Grid Extensions
For the January 2011 release, we switched to DevExpress grids, which meant a lot of code needed to be changed (or deleted). I ended up writing a few extensions for the grids that I believe may be useful to others:
Return a collection of selected items
Instead of working with a collection of selected rows, this lets you 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 allows you to select a single row or a continuous range. However, often I want to provide a list of item values and have the rows matching 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 a grid to a stream, the registry, or an XML file. However, I have a settings file and 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
I have an enum for the podcast state and, rather than show the text—which is the default—I want to show an image in the cell. However, this isn’t the easiest thing to figure out, as there’s no designer support for this 🙁. However, you can do most of this in the designer and then only need one line of code per enum value 😊.
Step 1
Set the Column Edit property of the column to an ImageComboBoxEdit: ![]()
Step 2
On the ImageComboBoxEdit editor settings, set the small images (and/or large images) property to the image list containing the items you want to show. It’s important to know the position (or index) of the 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 overloads that 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—that’s so 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));