«Элегантный» контрольный фильтр (без LINQ)
Благодаря C # 3 существует множество элегантных решений. Этот не использует операторы запросов LINQ; он использует лямбды и делегаты.
Фильтрует все элементы управления по заданным критериям (может фильтровать по нескольким критериям). Возвращает несколько совпадений. Это позволяет обнаруживать не только имена.
/// <summary>
/// Recurses through all controls, starting at given control,
/// and returns an array of those matching the given criteria.
/// </summary>
public Control[] FilterControls(Control start, Func<Control, bool> isMatch) {
var matches = new List<Control>();
Action<Control> filter = null;
(filter = new Action<Control>(c => {
if (isMatch(c))
matches.Add(c);
foreach (Control c2 in c.Controls)
filter(c2);
}))(start);
return matches.ToArray();
}
Использование фильтра ...
Это довольно гибкий способ использования
Control[] foundControls = null;
// Find control with Name="tabs1".
foundControls = FilterControls(this,
c => c.Name != null && c.Name.Equals("tabs1"));
// Find all controls that start with ID="panel*...
foundControls = FilterControls(this,
c => c.Name != null && c.Name.StartsWith("panel"));
// Find all Tab Pages in this form.
foundControls = FilterControls(this,
c => c is TabPage);
Console.Write(foundControls.Length); // is an empty array if no matches found.
Эквивалентный метод расширения
Методы расширения также добавляют наследнику элегантности в приложения.
Точно такую же логику можно внедрить в метод расширения следующим образом.
static public class ControlExtensions {
static public Control[] FilterControls(this Control start, Func<Control, bool> isMatch) {
// Put same logic here as seen above (copy & paste)
}
}
Расширение Использование :
// Find control with Name="tabs1" in the Panel.
panel1.FilterControls(c => c.Name != null && c.Name.Equals("tabs1"));
// Find all panels in this form
this.FilterControls(c => c is Panel);
Другое расширение для возврата одного элемента управления или null
Вызывает первый метод расширения (см. Выше), чтобы получить все совпадающие элементы управления, затем возвращает первый в совпадениях, иначе ноль, если список совпадений пуст.
Это неэффективно, потому что оно перебирает все элементы управления даже после нахождения первого совпадения - но просто играет здесь ради SO комментариев.
static public Control FilterControlsOne(this Control start, Func<Control, bool> isMatch) {
Control[] arrMatches = ControlExtensions.FilterControls(start, isMatch);
return arrMatches.Length == 0 ? null : arrMatches[0];
}