Доступность проверенных узлов TreeView в C#
В предыдущем примере использовалась рекурсия для перемещения узлов в элементе управления TreeView и заполнения списка проверяемыми узлами. В этом примере используется несколько иной подход. Он перемещает узлы управления TreeView и использует оператор yield return, чтобы вернуть отмеченные узлы TreeView. Затем основная программа может перебирать возвращаемые узлы.
Следующий метод рекурсивно сканирует узлы в TreeNodeCollection и выводит отмеченные узлы TreeView.
// Возвращает список проверяемых TreeNodes. private IEnumerableCheckedNodes(TreeNodeCollection nodes) { foreach (TreeNode node in nodes) { // Допустим этот узел. if (node.Checked) yield return node; // Допускаем проверенных потомков этого узла. foreach (TreeNode checked_child in CheckedNodes(node.Nodes)) yield return checked_child; } }
Метод проходит через TreeNodeCollection. Если узел проверен, он использует yield return, чтобы вернуть этот узел.
Затем метод вызывает себя рекурсивно, чтобы найти проверенных потомков этого узла, которые находятся в коллекции Nodes. Он выполняет итерацию над этими потомками и использует yield return, чтобы вернуть их.
Это одна из наиболее распространенных жалоб на синтаксис yield return: он не позволяет вам возвращать IEnumerable в одном выражении. Например, было бы неплохо сделать что-то вроде yield return CheckedNodes (nodes.Nodes).
К сожалению, вы не можете этого сделать. Вместо этого вы должны выполнять итерацию через другой IEnumerable и возвращать каждый элемент по отдельности.
Если вы думаете о том, как работает yield, вы поймете, что это не имеет большого значения с точки зрения производительности. Оператор yield возвращает значение циклу, который выполняет итерацию по своим значениям, а затем приостанавливает собственное выполнение до следующего значения времени. Возможность вернуть IEnumerable в одном из операторов может быть синтаксически удобна, но это не изменит того факта, что программе нужно ждать между каждым возвращаемым значением.
Но вернемся к этому примеру. Чтобы упростить поиск проверенных элемента управления TreeView, программа определяет следующий метод.
// Возвращает список проверенных узлов TreeView. private IEnumerableCheckedNodes(TreeView trv) { return CheckedNodes(trv.Nodes); }
Этот метод просто вызывает предыдущий, чтобы найти проверенные узлы TreeView в коллекции Nodes элемента управления.
Обратите внимание, что этот метод просто возвращает результат вызова другому методу CheckedNodes без использования yield return. Если метод использует yield return, то Visual Studio знает, что метод является итератором, и он может возвращать только значения с yield return.
Однако это не так. Этот метод не использует yield return, поэтому разрешено использовать обычный return оператор, чтобы вернуть результат IEnumerable вызова метода. Tt> р>
Наконец, основная программа использует следующий код для вызова этого метода.
// Список проверочных TreeNodes. private void btnShowChecked_Click(object sender, EventArgs e) { string results = ""; foreach (TreeNode node in CheckedNodes(trvMeals)) results += node.Text + "\n"; MessageBox.Show(results); }