Dot Net Perls

Query Windows Forms Controls in LINQ

by Sam Allen - Updated April 30, 2009

Problem. You want to use LINQ to find specific Windows Forms controls, such as the first matching control. Efficiently find the first focused TextBox. Solution. Here we implement a loop on the Windows controls in different ways.

=== LINQ test on Windows Forms controls ===

Foreach:      780 ms
LINQ version: 889 ms

1. Using var keyword

First we see the LINQ version. It uses the var keyword for simpler syntax. This is just one of many different ways to accomplish the task.

/// <summary>
/// Use a LINQ query to find the first focused text box on a windows form.
/// </summary>
public TextBox TextBoxFocusedFirst1()
{
    var res = from box in this.Controls.OfType<TextBox>()
              where box.Focused == true
              select box;
    return res.First();
}

2. Combining LINQ with foreach

LINQ allows you to write database-like queries on various objects, including Windows Form controls. We would like to test the performance penalty with LINQ, so here is a different version of our method.

/// <summary>
/// Use a combination of methods to find the right TextBox.
/// </summary>
public TextBox TextBoxFocusedFirst2()
{
    foreach (TextBox t in mainForm.Controls.OfType<TextBox>())
    {
        if (t.Focused == true)
        {
            return t;
        }
    }
}

3. Use the is operator

Here we look at a method that doesn't use LINQ. It uses the equivalent old-style code, which tests every control for whether it is a TextBox and has focus.

/// <summary>
/// Classic code to search form collections.
/// </summary>
public TextBox TextBoxFocusedFirst3()
{
    foreach (Control con in mainForm.Controls)
    {
        if (con is TextBox && con.Focused == true)
        {
            return con as TextBox;
        }
    }
}

4. Use the as operator

After taking the above benchmarks, I did a bit more tinkering and I found an even better version. This version will avoid 1 cast and performs about 10% better than the second version. Note that it doesn't use any LINQ.

/// <summary>
/// Classic code to search form collections.
/// </summary>
public TextBox TextBoxFocusedFirstX()
{
    foreach (Control con in mainForm.Controls)
    {
        if (con.Focused == true)
        {
            TextBox textBox = con as TextBox;
            if (textBox != null)
            {
                return textBox;
            }
        }
    }
}

5. Summary

Here we saw ways to use LINQ on Windows Forms controls. However, avoiding the LINQ syntax and OfType is faster. So, my recommendation is this: Don't use LINQ just because it is there. However, if it makes your life easier, it doesn't have a large penalty.

Dot Net Perls
LINQ | Enumerable.Range | Sum Method | ToDictionary Method | Var Examples | XElement Example
C# | Dictionary StringComparer Tip | DateTime.TryParse Example | Reflection Field Example | Validate Characters in String
© 2009 Sam Allen. All rights reserved.