Звучит так, как будто вы ищете здесь поиск в ширину , где вы сначала просматриваете всех детей, затем детей каждого ребенка и т. Д., Пока не найдете совпадение.
Для этого типа поиска мы хотим использовать Queue
, который является «первым пришел - первым вышел» (в отличие от стека, который является «последним первым вышел»).Таким образом, мы можем Enqueue
корневые TreeNode
элементы в очередь, затем в цикле мы Dequeue
каждый элемент по одному, проверяем, является ли он действительным, возвращаем его, если это так, и если это не так, мыEnqueue
это дети.Это гарантирует, что мы всегда проверяем родителей перед детьми.
Я также сделал этот метод немного более гибким, позволив клиенту передать функцию validator
, которая будет использоваться для проверки TreeNode
.Таким образом, мы можем повторно использовать метод для поиска в ширину по любому желаемому критерию (мы просто передаем ему метод, который принимает TreeNode
и возвращает bool
, то есть true
, если проверка прошла успешнодля этого узла):
private static TreeNode GetFirstMatch(TreeNodeCollection allNodes,
Func<TreeNode, bool> validator)
{
if (allNodes == null) return null;
// Initialize a Queue with all the root nodes
var nodeQueue = new Queue<TreeNode>(allNodes.OfType<TreeNode>());
// Use a queue for a breadth-first search
while (nodeQueue.Any())
{
// Remove the next item
var current = nodeQueue.Dequeue();
// Return it if it passes our validation
if (validator.Invoke(current)) return current;
// Add it's children to the end of the queue
foreach (TreeNode child in current.Nodes)
{
nodeQueue.Enqueue(child);
}
}
// If we didn't find any matches, return null
return null;
}
При использовании мы можем просто передать свойство Nodes
нашего элемента управления TreeView
методу вместе с функцией проверки (в этом примере я передаю лямбду)выражение для функции проверки):
TreeNode firstMatch = GetFirstMatch(treeView1.Nodes,
node => node.Tag.ToString().Split('|')[0].Equals(designKey.ToString()));