<< Click to Display Table of Contents >> Navigation: Проект > Элементы дерева объектов > Палитра ФБ > Служебные > Скрипт > Руководство и примеры > Работа с трендами > Добавление и удаление перьев |
Добавление и удаление перьев можно выполнять перетаскиванием мышью или используя окно добавления перьев. В ряде случае может потребоваться добавление перьев по определенному алгоритму, которое можно сделать с помощью скрипта.
Сделаем заготовку - две дискретных команды для добавления и удаления перьев, скрипт с одноименными входами и два параметра которые мы будем добавлять на тренд. Команды разместим на мнемосхеме.
Перейдем к скрипту. Создадим две заготовки кода, для обработки фронта на входе Добавить и Удалить.
bool? M = false;
bool? L = false;
public override void Execute()
{
if (Добавить == true && M == false)
{
}
M = Добавить;
if (Удалить == true && L == false)
{
}
L = Удалить;
}
Получить тренд можно точно также как и в прошлых примерах.
Получить коллекцию перьев уже добавленных на тренд можно используя метод:
var list = trend.Settings.Objects.OfType<MasterSCADA.Graph.Objects.Graph2D>().ToList();
list будет представлять собой коллекцию, которую можно перебрать в цикле.
Для того чтобы добавить перья в тренд нужно
trend.AddParametr(ITreePinHlp Pin);
Чтобы данный метод был доступен, нужно добавить пространство имен:
using MasterSCADA.Trend.Helpers;
Для удаления, нужно найти нужное перо в коллекции (например по имени, или по привязке к определенной переменной) и вызвать метод:
trend.DeleteParameter(pen);
Теперь скомпонуем данные методы в скрипт. Нам нужно с помощью одного скрипта выполнять удаление и добавление перьев. Большая часть код будет сводится к тому, чтобы получить сам класс тренда (который мы уже не раз получали). Чтобы не делать дублирование кода для удаления и вставки перьев, можно поступить следующим образом - разместить обращение к тренду в отдельном методе, в который передать делегат. Делегат - это указатель на метод, с его помощью можно сделать некий шаблон метода, а затем присвоить ему конкретный метод и передать его дальше в другой метод. Подробнее про делегаты можно посмотреть тут:
https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/delegates/
Сначала напишем методы для добавления и удаления. В качестве аргументов, мы будем передавать в них наш класс тренда, и коллекцию List с именами наших перьев, которые нужно удалить или добавить.
Метод добавления перьев будет выглядеть так:
private void AddPen(Trend trend, List<string> Names)
{
var list = trend.Settings.Objects.OfType<MasterSCADA.Graph.Objects.Graph2D>().ToList();
foreach (string name in Names)
{
if (list.FindIndex(x => x.Name == name) >= 0) continue; //переменая есть добавлять нельзя
var pin = (ITreePinHlp)HostFB.TreeItemHlp.Parent.GetChild(name); //находим переменную в дереве объектов
if (pin == null) continue; //переменной нет - проходим дальше
trend.AddParametr(pin); //добавляем в тренд
}
}
В нем мы сначала получаем коллекцию перьев, затем перебираем эту коллекцию в цикле foreach. С помощью поиска FindIndex мы ищем перо с таким именем, если перо уже добавлено - то пропускаем это имя, поскольку такое перо уже добавлено. А если же такого пера нет, то находим переменную по данному имени, как мы делали ранее, и если такая переменная есть - добавляем ее в тренд.
Метод удаления перьев будет выглядеть так:
private void DeletePen(Trend trend, List<string> Names)
{
var list = trend.Settings.Objects.OfType<MasterSCADA.Graph.Objects.Graph2D>().ToList();
foreach (string name in Names)
{
var pen = list.Find(x => x.Name == name); //находим перо
if (pen != null) trend.DeleteParameter(pen); //если нашли - удаляем
}
}
Теперь сделаем делегат для данных функций. Для этого в теле класса объявим его:
delegate void Operation(Trend trend, List<string> Names);
Обратите внимание что метод имеет аналогичную сигнатуру, как и методы DeletePen и AddPen - не возвращает значение (void), и имеет два входных аргумента Trend и List<string>.
Теперь создадим метод для обращения к тренду и в него передадим наш делегат и коллекцию имен.
private void ChangeTrend(Operation Oper, List<string> Collect)
{
//Ссылка на текущий проект
var Project = HostFB.TreeItemHlp.Project;
//получаем корневой объект
var ParentObject = (ITreeItemHlp)HostFB.TreeItemHlp.Parent;
//получаем тренд
RTManager.Instance.ThreadHolder.BeginInvoke(new ThreadStart(delegate
{
foreach (var trend in Project.GetService<TrendService>().Opened)
{
var host = trend.Host as System.Windows.Forms.Control;
if (host != null)
{
Object name = WinFormsControlBase.GetAmbientProperty(host, WindowlessControlBase.DISPID.DISPID_AMBIENT_NAME);
if (name.ToString() != ИМЯ_ТРЕНДА || trend.Attribute.TreeItem.ID != ParentObject.ID || trend.Attribute.DisplayName != ИМЯ_ОКНА) continue;
Oper(trend, Collect); //вызов метода
break;
}
}
}));
}
Код внутри метода нам уже знаком. Новая по сути одна строчка:
Oper(trend,Collect); //вызов метода
Здесь вызывается метод, который мы получили как аргумент.
Осталось только добавить вызов метода ChangeTrend в метод Execute.
public override void Execute()
{
if (Добавить == true && M == false)
{
ChangeTrend(AddPen, Collect);
}
M = Добавить;
if (Удалить == true && L == false)
{
ChangeTrend(DeletePen, Collect);
}
L = Удалить;
}
Все что нужно сделать - передать вместо первого аргумента нужный нам метод, добавления или удаления пера.
Итоговый код будет выглядеть так:
public partial class ФБ : ScriptBase
{
const string ИМЯ_ТРЕНДА = "Тренд";
const string ИМЯ_ОКНА = "Мнемосхема";
bool? M = false;
bool? L = false;
delegate void Operation(Trend trend, List<string> Names);
List<string> Collect = new List<string>() { "Параметр 1", "Параметр 2" };
public override void Execute()
{
if (Добавить == true && M == false)
{
ChangeTrend(AddPen, Collect);
}
M = Добавить;
if (Удалить == true && L == false)
{
ChangeTrend(DeletePen, Collect);
}
L = Удалить;
}
private void ChangeTrend(Operation Oper, List<string> Collect)
{
//Ссылка на текущий проект
var Project = HostFB.TreeItemHlp.Project;
//получаем корневой объект
var ParentObject = (ITreeItemHlp)HostFB.TreeItemHlp.Parent;
//получаем тренд
RTManager.Instance.ThreadHolder.BeginInvoke(new ThreadStart(delegate
{
foreach (var trend in Project.GetService<TrendService>().Opened)
{
var host = trend.Host as System.Windows.Forms.Control;
if (host != null)
{
Object name = WinFormsControlBase.GetAmbientProperty(host, WindowlessControlBase.DISPID.DISPID_AMBIENT_NAME);
if (name.ToString() != ИМЯ_ТРЕНДА || trend.Attribute.TreeItem.ID != ParentObject.ID || trend.Attribute.DisplayName != ИМЯ_ОКНА) continue;
Oper(trend, Collect); //вызов метода
break;
}
}
}));
}
private void AddPen(Trend trend, List<string> Names)
{
var list = trend.Settings.Objects.OfType<MasterSCADA.Graph.Objects.Graph2D>().ToList();
foreach (string name in Names)
{
if (list.FindIndex(x => x.Name == name) >= 0) continue; //переменая есть добавлять нельзя
var pin = (ITreePinHlp)HostFB.TreeItemHlp.Parent.GetChild(name); //находим переменную в дереве объектов
if (pin == null) continue; //переменной нет - проходим дальше
trend.AddParametr(pin); //добавляем в тренд
}
}
private void DeletePen(Trend trend, List<string> Names)
{
var list = trend.Settings.Objects.OfType<MasterSCADA.Graph.Objects.Graph2D>().ToList();
foreach (string name in Names)
{
var pen = list.Find(x => x.Name == name); //находим перо
if (pen != null) trend.DeleteParameter(pen); //если нашли - удаляем
}
}
}
Проверим работу нашего скрипта.
Переменные добавляются и удаляются.
Готовый пример можно скачать по ссылке.