Если вы вернетесь к коду листинга 12.1, который был сгенерирован для вас при записи вашего расширения узлов Solution Explorer, то увидите, что он очень прост и представляет собой буквальное воспроизведение всего того, что вы вручную выполняли в окне Solution Explorer. Макрос ссылается на каждый отдельный элемент в окне Solution Explorer при помощи метода ActiveWindow.Object.Getltem, передавая ему название объекта для тогол чтобы получить ссылку UlHierarchyltem. А там необходимо только настроить простое свойство для того, чтобы развернуть все элементы на нижних уровнях (UIHierarchyltems . Expand = True).
Код работает, но, вероятно, это не совсем то, чего вы хотели. Например, он ссылается на проекты и элементы проектов (которые вы разворачиваете) по пути и имени. Это означает, что данный макрос не является универсальным. Он будет работать только с этим конкретным примером решения Contoso — и даже при этом он весьма "хрупкий": если вы добавите или удалите проект или элемент проекта, то макрос не узнает об этом и будет по-прежнему пытаться настроить свойство Expanded для бывшего элемента. Для того чтобы сделать данный макрос действительно полезным, вам нужно переработать этот код. Преимущество использования записи макроса состоит в том, что таким образом можно получить хорошую стартовую точку для разработки макроса. Фактически при этой записи выявилось использование объекта UlHierarchyltem, который мы в предыдущей главе не обсуждали. При оценке общей структуры программы становится понятно, что должен существовать способ рефакторинга этого кода в цикл, который будет рекурсивно разворачивать узлы дерева до тех пор, пока не развернет их все. Возможно, что вместо разворачивания или сворачивания узлов вы могли бы попробовать переключать свойство Expanded данного объекта.
Вы редактируете макрокод при помощи редактора кода точно так же, как вы редактировали бы любой другой документ в Visual Studio. Для переработки данного макроса вы можете начать с создания рекурсивной вспомогательной процедуры, которая принимает объект UlHierarchyltem, переключает его свойство Expanded в значение True и вызывает сама себя для каждого подэлемента, обнаруженного в коллекции UIHierarchyltems:
For Each subNode As UlHierarchyltem In node.UIHierarchyltems ExpandNodes(subNode)
Next
node.UIHierarchyltems.Expanded = True
Примечание
В отличие от редакторов среды Visual Studio, текстовый редактор среды Macros автоматически сохраняет редактируемый вами файл при его закрытии. Это делается без всякого запроса. Если вы не отмените сделанные вами при редактировании изменения, то они будут сохранены при закрывании редактора (независимо от того, сохранили ли вы их явным образом).
Затем вам нужна родительская управляющая процедура, которая создает экземпляр объекта окна (представляющего Solution Explorer) и получает от этого окна объект UIHierarchy корневого уровня. Здесь вы делаете цикл по первому уровню узлов дерева и вызываете рекурсивную процедуру:
Dim tree As UIHierarchy Dim explorer As Window2
explorer = DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer)
tree = explorer.Object
For Each node As UlHierarchyltem In tree.UIHierarchyltems ExpandNodes(node)
Next
Следующий шаг: если вы модифицируете рекурсивную процедуру, чтобы она принимала булево значение, то у вас получится процедура общего характера, которая может разворачивать или сворачивать узлы. Если свести все это воедино, то у вас получатся два макроса: один разворачивает все узлы в дереве Solution Explorer, а другой сворачивает все узлы в дереве Solution Explorer. В листинге 12.2 вы видите эти два макроса как публичные процедуры: ExpandAll и CollapseAll. Закрытая процедура ExpandCollapseNodes вызывается обоими макросами.
Imports EnvDTE Imports EnvDTE80
Imports Microsoft.VisualStudio.CommandBars Imports System Imports System.Collections Imports System.Diagnostics
Imports System.Text Imports System.Windows.Forms
Public Module MacroExamples
' Разворачивает все узлы в Solution Explorer Public Sub ExpandAll()
Dim tree As UIHierarchy Dim explorer As Window2
0
' Ссылка на окно Solution Explorer
explorer = DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer)
' Ссылка на объект UIHierarchy, полученная из окна Solution Explorer tree = explorer.Object
1 Перебрать узлы верхнего уровня, вызвать рекурсивную процедуру ' для разворачивания каждого узла
For Each node As UIHierarchyltem In tree.UIHierarchyltems ExpandCollapseNodes(node, True)
Next 1 End Sub
' Сворачивает все узлы в Solution Explorer
Public Sub CollapseAll()
Dim tree As UIHierarchy Dim explorer As Window2
1 Ссылка на окно Solution Explorer
explorer = DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer)
' Ссылка на объект UIHierarchy, полученная из окна Solution Explorer tree = explorer.Object
' Перебрать узлы верхнего уровня, вызвать рекурсивную процедуру ' для разворачивания каждого узла
For Each node As UIHierarchyltem In tree.UIHierarchyltems ExpandCollapseNodes(node, True)
Next End Sub
%
' Рекурсивная процедура для разворачивания или сворачивания всех т подузлов данного UIHierarchyltem
Private Sub ExpandCollapseNodes(ByRef node As UIHierarchyltem,
ByVal expanded As Boolean)
For Each subNode As UIHierarchyltem In node.UIHierarchyltems
1 Повторный вызов этой процедуры с новым подузлом ' в качестве родительского узла ExpandCollapseNodes(subNode, expanded)
Next
' Выполнить сворачивание/разворачивание node.UIHierarchyltems.Expanded = True End Sub End Module
При сравнении с кодом, созданным при записи макроса, сходства обнаруживается не слишком много; однако повторим еще раз — записанный код полезен с познавательной точки зрения, он дал вам понятие о возможном подходе и концепции использования объектов UIHierarchy/uiHierarchy'Item/UIHierarchyltems для разворачивания узлов.