Узлы на основе NodeModel обеспечивают гораздо больше гибкости и мощности, чем узлы Zero-Touch. В этом примере мы улучшим узел сетки Zero-Touch, добавив встроенный ползунок, который случайным образом изменяет размер прямоугольника.
Регулятор масштабирует ячейки относительно их размера, чтобы пользователю не приходилось указывать в ползунке нужный диапазон.
В Dynamo используется архитектурный шаблон Model-View-Viewmodel (MVVM), благодаря чему пользовательский интерфейс не зависит от серверной части. При создании узлов ZeroTouch в Dynamo выполняется привязка данных между данными узла и его пользовательским интерфейсом. Чтобы создать пользовательский интерфейс, необходимо добавить логику привязки данных.
В общих чертах, для установления взаимосвязи между моделью и видом в Dynamo используется два класса:
Класс NodeModel
для определения основной логики узла (модель).
Класс INodeViewCustomization
для настройки способа просмотра NodeModel
(вид).
У объектов NodeModel уже есть связанная пара модели и вида (NodeViewModel), поэтому мы можем сосредоточиться только на модели и виде для пользовательского интерфейса.
Узлы NodeModel имеют несколько существенных отличий от узлов Zero-Touch. Мы рассмотрим их на следующем примере. Прежде чем мы перейдем к настройке пользовательского интерфейса, создадим логику NodeModel.
1. Создадим структуру проекта.
Узел NodeModel может вызывать только функции, поэтому необходимо поместить NodeModel и функции в разные библиотеки. Стандартный способ сделать это в пакетах Dynamo — создать отдельные проекты для каждой библиотеки. Начнем с создания нового решения, куда будут входить эти проекты.
Выберите
File > New > Project
(Файл > Создать > Проект).Выберите
Other Project Types
(Другие типы проектов), чтобы открыть параметр решения.Выберите
Blank Solution
(Пустое решение).Присвойте решению имя
CustomNodeModel
.Нажмите
Ok
.
Создайте два проекта библиотеки классов C# в решении: один для функций, а другой для реализации интерфейса NodeModel.
Щелкните правой кнопкой мыши на решении и выберите
Add > New Project
(Добавить > Новый проект).Выберите библиотеку классов.
Присвойте ей имя
CustomNodeModel
.Нажмите
Ok
Повторите процедуру, чтобы добавить другой проект, с именем
CustomNodeModelFunctions
.
Теперь необходимо переименовать библиотеки классов, которые были созданы автоматически, и добавить их в проект CustomNodeModel
. Класс GridNodeModel
реализует абстрактный класс NodeModel, GridNodeView
используется для настройки вида, а GridFunction
содержит все функции, которые необходимо вызвать.
Добавьте другой класс: щелкните правой кнопкой мыши проект
CustomNodeModel
, нажмитеAdd > New Item...
(Добавить > Новый элемент) и выберитеClass
(Класс).В проекте
CustomNodeModel
нам необходимы классыGridNodeModel.cs
иGridNodeView.cs
.В проекте
CustomNodeModelFunction
требуется классGridFunctions.cs
.
Прежде чем добавить к классам код, добавьте необходимые пакеты для этого проекта. Для CustomNodeModel
потребуются ZeroTouchLibrary и WpfUILibrary, а для CustomNodeModelFunction
— только ZeroTouchLibrary. WpfUILibrary будет использоваться в настройке адаптации пользовательского интерфейса, а ZeroTouchLibrary будет использоваться для создания геометрии. Пакеты можно добавлять для проектов по отдельности. Так как эти пакеты имеют зависимости, будут автоматически установлены Core и DynamoServices.
Щелкните проект правой кнопкой мыши и выберите
Manage NuGet Packages
(Управлять пакетами NuGet).Установите только необходимые пакеты для данного проекта.
Visual Studio скопирует пакеты NuGet, на которые мы ссылались в каталоге сборки. Для этого параметра можно установить значение false, чтобы в пакете не было ненужных файлов.
Выберите пакет Dynamo NuGet.
Задайте для параметра
Copy Local
(Скопировать локально) значение false.
2. Наследование от класса NodeModel.
Как упоминалось ранее, основное отличие узла NodeModel от узла ZeroTouch заключается в реализации класса NodeModel
. Узлу NodeModel требуется несколько функций из этого класса, и их можно получить, добавив :NodeModel
после имени класса.
Скопируйте следующий код в GridNodeModel.cs
.
В этом отличие от Zero-Touch. Давайте попробуем разобраться, что делает каждый элемент.
Задайте атрибуты узла, такие как имя, категория, имена и типы InPort/OutPort (входящего и выходящего портов), описания.
public class GridNodeModel : NodeModel
— это класс, наследующий класс NodeModel
от класса Dynamo.Graph.Nodes
.
public GridNodeModel() { RegisterAllPorts(); }
является конструктором, регистрирующим входные и выходные данные узла.
BuildOutputAst()
возвращает AST (абстрактное синтаксическое дерево) — необходимую структуру для возврата данных из узла NodeModel.
AstFactory.BuildFunctionCall()
вызывает функцию RectangularGrid из GridFunctions.cs
.
new Func<int, int, double, List<Rectangle>>(GridFunction.RectangularGrid)
задает функцию и ее параметры.
new List<AssociativeNode> { inputAstNodes[0], inputAstNodes[1], sliderValue });
сопоставляет входные данные узла с параметрами функции.
AstFactory.BuildNullNode()
создает пустой узел, если входные порты не подключены. Это позволяет избежать отображения предупреждения на узле.
RaisePropertyChanged("SliderValue")
уведомляет пользовательский интерфейс об изменении значения ползунка.
var sliderValue = AstFactory.BuildDoubleNode(SliderValue)
создает узел AST, представляющий значение ползунка.
Измените входные данные на переменную sliderValue
в переменной functionCall new List<AssociativeNode> { inputAstNodes[0], sliderValue });
.
3. Вызов функции.
Проект CustomNodeModelFunction
будет создан в отдельной сборке из CustomNodeModel
, чтобы его можно было вызвать.
Скопируйте следующий код в GridFunction.cs
.
Этот класс функций очень похож на пример использования Zero-Touch Grid, но есть одно отличие:
При указании [IsVisibleInDynamoLibrary(false)]
Dynamo не видит следующий метод и класс, поскольку функция уже вызывается из CustomNodeModel
.
Так же как мы добавили ссылки на пакеты NuGet, CustomNodeModel
должен будет ссылаться на CustomNodeModelFunction
для вызова функции.
Оператор using для CustomNodeModel будет неактивен до тех пор, пока мы не сошлемся на функцию.
Щелкните правой кнопкой мыши
CustomNodeModel
и выберитеAdd > Reference
(Добавить > Ссылка).Выберите
Projects > Solution
(Проекты > Решение).Выберите
CustomNodeModelFunction
.Нажмите
Ok
4. Настройка вида.
Чтобы создать ползунок, необходимо настроить пользовательский интерфейс, реализовав интерфейс INodeViewCustomization
.
Скопируйте следующий код в GridNodeView.cs
.
public class CustomNodeModelView : INodeViewCustomization<GridNodeModel>
определяет функции, необходимые для настройки пользовательского интерфейса.
После настройки структуры проекта используйте среду разработки Visual Studio, чтобы собрать пользовательский элемент управления и определить его параметры в файле .xaml
. В окне инструментов добавьте ползунок в элемент <Grid>...</Grid>
.
Щелкните правой кнопкой мыши
CustomNodeModel
и выберитеAdd > New Item
(Добавить > Новый элемент).Выберите
WPF
.Присвойте пользовательскому элементу управления имя
Slider
(Ползунок).Нажмите
Add
(Добавить).
Скопируйте следующий код в Slider.xaml
.
Параметры ползунка определяются в файле .xaml
. Атрибуты минимума и максимума определяют числовой диапазон этого ползунка.
Внутри <Grid>...</Grid>
можно разместить различные пользовательские элементы управления с панели инструментов Visual Studio.
При создании файла Slider.xaml
Visual Studio был автоматически создан файл C# с именем Slider.xaml.cs
, который инициализирует ползунок. Измените пространство имен в этом файле.
Нам требуется пространство имен CustomNodeModel.CustomNodeModel
.
GridNodeModel.cs
определяет логику вычисления ползунка.
5. Настройка пакета.
Перед сборкой проекта добавьте файл pkg.json
, чтобы Dynamo мог прочитать пакет.
Щелкните правой кнопкой мыши
CustomNodeModel
и выберитеAdd > New Item
(Добавить > Новый элемент).Выберите
Web
(Веб).Выберите
JSON File
(Файл JSON).Присвойте файлу имя
pkg.json
.Нажмите
Add
(Добавить).
Скопируйте следующий код в pkg.json
.
"name":
определяет имя пакета и его группу в библиотеке Dynamo.
"keywords":
предоставляет условия поиска по библиотеке Dynamo.
"node_libraries": []
— библиотеки, связанные с пакетом
Последний шаг — собрать решение и опубликовать его в виде пакета Dynamo. Сведения о создании локального пакета перед публикацией в Интернете и о сборке пакета непосредственно в Visual Studio см. в разделе «Развертывание пакета».